Title: [211777] trunk
Revision
211777
Author
utatane....@gmail.com
Date
2017-02-07 00:17:17 -0800 (Tue, 07 Feb 2017)

Log Message

Web Inspector: allow import() inside the inspector
https://bugs.webkit.org/show_bug.cgi?id=167457

Reviewed by Ryosuke Niwa.

Source/_javascript_Core:

We relax import module hook to accept null SourceOrigin.
Such a script can be evaluated from the inspector console.

* jsc.cpp:
(GlobalObject::moduleLoaderImportModule):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncImportModule):

Source/WebCore:

When evaluating `import("...")`, we need the caller's context to resolve
the module specifier correctly. For example, if `import("./cocoa.js")` is
evaluated in the script "drinks/hot.js", this module name is resolved to
"drinks/cocoa.js". If the same import operator is evaluated in the script
"menu/all.js", the module specifier becomes "menu/cocoa.js".

Previously we reject the import operator if the caller does not have such
a context. These context is SourceOrigin and its ScriptFetcher. While they
are offered in the script tag and other code evaluations, the inspector
console does not offer that. These class are offered in the WebCore side
and we should not touch these classes in the JSC's inspector code.

Now we relax the above restriction. If the above caller information is not
offered, we fallback to the default one. In the web page, we use the page's
URL as the caller's source origin. This allows us to evaluate the import
operator in the inspector console.

And as of r167698, the console recognizes `await import("...")` form. We use
this to test this `import()` in the console functionality.

* bindings/js/ScriptModuleLoader.cpp:
(WebCore::ScriptModuleLoader::importModule):

LayoutTests:

* inspector/controller/resources/cappuccino.js: Added.
* inspector/controller/resources/cocoa.js: Added.
* inspector/controller/resources/drink.js: Added.
* inspector/controller/runtime-controller-expected.txt:
* inspector/controller/runtime-controller.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (211776 => 211777)


--- trunk/LayoutTests/ChangeLog	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/LayoutTests/ChangeLog	2017-02-07 08:17:17 UTC (rev 211777)
@@ -1,3 +1,16 @@
+2017-02-07  Yusuke Suzuki  <utatane....@gmail.com>
+
+        Web Inspector: allow import() inside the inspector
+        https://bugs.webkit.org/show_bug.cgi?id=167457
+
+        Reviewed by Ryosuke Niwa.
+
+        * inspector/controller/resources/cappuccino.js: Added.
+        * inspector/controller/resources/cocoa.js: Added.
+        * inspector/controller/resources/drink.js: Added.
+        * inspector/controller/runtime-controller-expected.txt:
+        * inspector/controller/runtime-controller.html:
+
 2017-02-06  Carlos Garcia Campos  <cgar...@igalia.com>
 
         Overlay scrolling with iframe-s broken

Added: trunk/LayoutTests/inspector/controller/resources/cappuccino.js (0 => 211777)


--- trunk/LayoutTests/inspector/controller/resources/cappuccino.js	                        (rev 0)
+++ trunk/LayoutTests/inspector/controller/resources/cappuccino.js	2017-02-07 08:17:17 UTC (rev 211777)
@@ -0,0 +1,2 @@
+export let name = "Cappuccino";
+export let taste = "Awesome";

Added: trunk/LayoutTests/inspector/controller/resources/cocoa.js (0 => 211777)


--- trunk/LayoutTests/inspector/controller/resources/cocoa.js	                        (rev 0)
+++ trunk/LayoutTests/inspector/controller/resources/cocoa.js	2017-02-07 08:17:17 UTC (rev 211777)
@@ -0,0 +1,2 @@
+export let name = "Cocoa";
+export let taste = "Sweet";

Added: trunk/LayoutTests/inspector/controller/resources/drink.js (0 => 211777)


--- trunk/LayoutTests/inspector/controller/resources/drink.js	                        (rev 0)
+++ trunk/LayoutTests/inspector/controller/resources/drink.js	2017-02-07 08:17:17 UTC (rev 211777)
@@ -0,0 +1,7 @@
+import * as Cocoa from './cocoa.js'
+import * as Cappuccino from './cappuccino.js'
+
+export {
+    Cocoa,
+    Cappuccino
+}

Modified: trunk/LayoutTests/inspector/controller/runtime-controller-expected.txt (211776 => 211777)


--- trunk/LayoutTests/inspector/controller/runtime-controller-expected.txt	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/LayoutTests/inspector/controller/runtime-controller-expected.txt	2017-02-07 08:17:17 UTC (rev 211777)
@@ -7,6 +7,12 @@
 CONSOLE MESSAGE: line 9: Rejection
 CONSOLE MESSAGE: line 7: %o
 CONSOLE MESSAGE: line 7: %o
+CONSOLE MESSAGE: line 9: TypeError: Module specifier does not start with "/", "./", or "../".
+CONSOLE MESSAGE: line 9: TypeError: Importing a module script failed.
+CONSOLE MESSAGE: line 6: Cocoa is Sweet.
+CONSOLE MESSAGE: line 7: %o
+CONSOLE MESSAGE: line 6: Cocoa is Sweet. Cappuccino is Awesome.
+CONSOLE MESSAGE: line 7: %o
 Tests for RuntimeManager operations.
 
 
@@ -58,3 +64,13 @@
 Source: x = y = await 10
 PASS: Exception. Should not get transformed and produce a SyntaxError.
 
+-- Running test case: RuntimeManager.prototype.evaluateInInspectedWindow.ImportFromConsole
+Source: await import('')
+PASS: Transformed. Should log the value or an exception.
+Source: await import('./not-found.js')
+PASS: Transformed. Should log the value or an exception.
+Source: await import('./resources/cocoa.js').then((cocoa) => console.log(`${cocoa.name} is ${cocoa.taste}.`))
+PASS: Transformed. Should log the value or an exception.
+Source: await import('./resources/drink.js').then((ns) => console.log(`${ns.Cocoa.name} is ${ns.Cocoa.taste}. ${ns.Cappuccino.name} is ${ns.Cappuccino.taste}.`))
+PASS: Transformed. Should log the value or an exception.
+

Modified: trunk/LayoutTests/inspector/controller/runtime-controller.html (211776 => 211777)


--- trunk/LayoutTests/inspector/controller/runtime-controller.html	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/LayoutTests/inspector/controller/runtime-controller.html	2017-02-07 08:17:17 UTC (rev 211777)
@@ -124,6 +124,26 @@
         }
     });
 
+    suite.addTestCase({
+        name: "RuntimeManager.prototype.evaluateInInspectedWindow.ImportFromConsole",
+        description: "Test evaluating an import _expression_ from console.",
+        test(resolve, reject) {
+            function testSource(_expression_) {
+                WebInspector.runtimeManager.evaluateInInspectedWindow(_expression_, {objectGroup: "test"}, (result, wasThrown) => {
+                    InspectorTest.log("Source: " + _expression_);
+                    InspectorTest.expectThat(result.isUndefined(), "Transformed. Should log the value or an exception.");
+                });
+            }
+
+            testSource("await import('')");
+            testSource("await import('./not-found.js')");
+            testSource("await import('./resources/cocoa.js').then((cocoa) => console.log(`${cocoa.name} is ${cocoa.taste}.`))");
+            testSource("await import('./resources/drink.js').then((ns) => console.log(`${ns.Cocoa.name} is ${ns.Cocoa.taste}. ${ns.Cappuccino.name} is ${ns.Cappuccino.taste}.`))");
+
+            InspectorBackend.runAfterPendingDispatches(resolve);
+        }
+    });
+
     suite.runTestCasesAndFinish();
 }
 </script>

Modified: trunk/Source/_javascript_Core/ChangeLog (211776 => 211777)


--- trunk/Source/_javascript_Core/ChangeLog	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/Source/_javascript_Core/ChangeLog	2017-02-07 08:17:17 UTC (rev 211777)
@@ -1,3 +1,18 @@
+2017-02-07  Yusuke Suzuki  <utatane....@gmail.com>
+
+        Web Inspector: allow import() inside the inspector
+        https://bugs.webkit.org/show_bug.cgi?id=167457
+
+        Reviewed by Ryosuke Niwa.
+
+        We relax import module hook to accept null SourceOrigin.
+        Such a script can be evaluated from the inspector console.
+
+        * jsc.cpp:
+        (GlobalObject::moduleLoaderImportModule):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncImportModule):
+
 2017-02-06  Joseph Pecoraro  <pecor...@apple.com>
 
         Web Inspector: Do not use RunLoop when dispatching inspector GC event

Modified: trunk/Source/_javascript_Core/jsc.cpp (211776 => 211777)


--- trunk/Source/_javascript_Core/jsc.cpp	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/Source/_javascript_Core/jsc.cpp	2017-02-07 08:17:17 UTC (rev 211777)
@@ -1551,6 +1551,9 @@
         return JSInternalPromiseDeferred::create(exec, globalObject)->reject(exec, error);
     };
 
+    if (sourceOrigin.isNull())
+        return rejectPromise(createError(exec, ASCIILiteral("Could not resolve the module specifier.")));
+
     auto referrer = sourceOrigin.string();
     auto moduleName = moduleNameValue->value(exec);
     if (UNLIKELY(scope.exception())) {

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (211776 => 211777)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2017-02-07 08:17:17 UTC (rev 211777)
@@ -944,11 +944,6 @@
     RETURN_IF_EXCEPTION(catchScope, { });
 
     auto sourceOrigin = exec->callerSourceOrigin();
-    if (sourceOrigin.isNull()) {
-        promise->reject(exec, createError(exec, ASCIILiteral("Could not resolve the module specifier.")));
-        return JSValue::encode(promise->promise());
-    }
-
     RELEASE_ASSERT(exec->argumentCount() == 1);
     auto* specifier = exec->uncheckedArgument(0).toString(exec);
     if (Exception* exception = catchScope.exception()) {

Modified: trunk/Source/WebCore/ChangeLog (211776 => 211777)


--- trunk/Source/WebCore/ChangeLog	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/Source/WebCore/ChangeLog	2017-02-07 08:17:17 UTC (rev 211777)
@@ -1,3 +1,33 @@
+2017-02-07  Yusuke Suzuki  <utatane....@gmail.com>
+
+        Web Inspector: allow import() inside the inspector
+        https://bugs.webkit.org/show_bug.cgi?id=167457
+
+        Reviewed by Ryosuke Niwa.
+
+        When evaluating `import("...")`, we need the caller's context to resolve
+        the module specifier correctly. For example, if `import("./cocoa.js")` is
+        evaluated in the script "drinks/hot.js", this module name is resolved to
+        "drinks/cocoa.js". If the same import operator is evaluated in the script
+        "menu/all.js", the module specifier becomes "menu/cocoa.js".
+
+        Previously we reject the import operator if the caller does not have such
+        a context. These context is SourceOrigin and its ScriptFetcher. While they
+        are offered in the script tag and other code evaluations, the inspector
+        console does not offer that. These class are offered in the WebCore side
+        and we should not touch these classes in the JSC's inspector code.
+
+        Now we relax the above restriction. If the above caller information is not
+        offered, we fallback to the default one. In the web page, we use the page's
+        URL as the caller's source origin. This allows us to evaluate the import
+        operator in the inspector console.
+
+        And as of r167698, the console recognizes `await import("...")` form. We use
+        this to test this `import()` in the console functionality.
+
+        * bindings/js/ScriptModuleLoader.cpp:
+        (WebCore::ScriptModuleLoader::importModule):
+
 2017-02-07  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         Move platform-independent parts of ComplexTextController out of mac/ subfolder

Modified: trunk/Source/WebCore/bindings/js/ScriptModuleLoader.cpp (211776 => 211777)


--- trunk/Source/WebCore/bindings/js/ScriptModuleLoader.cpp	2017-02-07 08:14:06 UTC (rev 211776)
+++ trunk/Source/WebCore/bindings/js/ScriptModuleLoader.cpp	2017-02-07 08:17:17 UTC (rev 211777)
@@ -218,15 +218,30 @@
     JSC::VM& vm = exec->vm();
     auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
 
-    // FIXME: setTimeout and setInterval with "string()" should propagate SourceOrigin.
-    // https://webkit.org/b/167097
-    ASSERT_WITH_MESSAGE(!sourceOrigin.isNull(), "If SourceOrigin is null, this function is not invoked.");
-    if (!sourceOrigin.fetcher())
-        return rejectPromise(state, globalObject, TypeError, ASCIILiteral("Could not use import operator in this context."));
+    // If SourceOrigin and/or CachedScriptFetcher is null, we import the module with the default fetcher.
+    // SourceOrigin can be null if the source code is not coupled with the script file.
+    // The examples,
+    //     1. The code evaluated by the inspector.
+    //     2. The other unusual code execution like the evaluation through the NPAPI.
+    //     3. The code from injected bundle's script.
+    //     4. The code from extension script.
+    URL baseURL;
+    RefPtr<JSC::ScriptFetcher> scriptFetcher;
+    if (sourceOrigin.isNull()) {
+        baseURL = m_document.baseURL();
+        scriptFetcher = CachedScriptFetcher::create(m_document.charset());
+    } else {
+        baseURL = URL(URL(), sourceOrigin.string());
+        if (!baseURL.isValid())
+            return rejectPromise(state, globalObject, TypeError, ASCIILiteral("Importer module key is not a Symbol or a String."));
 
-    URL baseURL(URL(), sourceOrigin.string());
-    if (!baseURL.isValid())
-        return rejectPromise(state, globalObject, TypeError, ASCIILiteral("Importer module key is not Symbol or String."));
+        if (sourceOrigin.fetcher())
+            scriptFetcher = sourceOrigin.fetcher();
+        else
+            scriptFetcher = CachedScriptFetcher::create(m_document.charset());
+    }
+    ASSERT(baseURL.isValid());
+    ASSERT(scriptFetcher);
 
     auto specifier = moduleName->value(exec);
     auto result = resolveModuleSpecifier(m_document, specifier, baseURL);
@@ -233,7 +248,7 @@
     if (!result)
         return rejectPromise(state, globalObject, TypeError, result.error());
 
-    return JSC::importModule(exec, JSC::Identifier::fromString(&vm, result->string()), JSC::JSScriptFetcher::create(vm, sourceOrigin.fetcher() ));
+    return JSC::importModule(exec, JSC::Identifier::fromString(&vm, result->string()), JSC::JSScriptFetcher::create(vm, WTFMove(scriptFetcher) ));
 }
 
 void ScriptModuleLoader::notifyFinished(CachedModuleScriptLoader& loader, RefPtr<DeferredPromise> promise)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to