Title: [230697] trunk
Revision
230697
Author
utatane....@gmail.com
Date
2018-04-16 19:38:59 -0700 (Mon, 16 Apr 2018)

Log Message

[WebAssembly][Modules] Prototype wasm import
https://bugs.webkit.org/show_bug.cgi?id=184600

Reviewed by JF Bastien.

JSTests:

Add wasm and wat files since module loader want to load wasm files from FS.
Currently, importing the other modules from wasm is not supported.

* wasm.yaml:
* wasm/modules/constant.wasm: Added.
* wasm/modules/constant.wat: Added.
* wasm/modules/js-wasm-function-namespace.js: Added.
(assert.throws):
* wasm/modules/js-wasm-function.js: Added.
(assert.throws):
* wasm/modules/js-wasm-global-namespace.js: Added.
(assert.throws):
* wasm/modules/js-wasm-global.js: Added.
(assert.throws):
* wasm/modules/js-wasm-memory-namespace.js: Added.
(assert.throws):
* wasm/modules/js-wasm-memory.js: Added.
(assert.throws):
* wasm/modules/js-wasm-start.js: Added.
(then):
* wasm/modules/js-wasm-table-namespace.js: Added.
(assert.throws):
* wasm/modules/js-wasm-table.js: Added.
(assert.throws):
* wasm/modules/memory.wasm: Added.
* wasm/modules/memory.wat: Added.
* wasm/modules/start.wasm: Added.
* wasm/modules/start.wat: Added.
* wasm/modules/sum.wasm: Added.
* wasm/modules/sum.wat: Added.
* wasm/modules/table.wasm: Added.
* wasm/modules/table.wat: Added.

Source/_javascript_Core:

This patch is an initial attempt to implement Wasm loading in module pipeline.
Currently,

1. We only support Wasm loading in the JSC shell. Once loading mechanism is specified
   in whatwg HTML, we should integrate this into WebCore.

2. We only support exporting values from Wasm. Wasm module cannot import anything from
   the other modules now.

When loading a file, JSC shell checks wasm magic. If the wasm magic is found, JSC shell
loads the file with WebAssemblySourceProvider. It is wrapped into JSSourceCode and
module loader pipeline just handles it as the same to JS. When parsing a module, we
checks the type of JSSourceCode. If the source code is Wasm source code, we create a
WebAssemblyModuleRecord instead of JSModuleRecord. Our module pipeline handles
AbstractModuleRecord and Wasm module is instantiated, linked, and evaluated.

* builtins/ModuleLoaderPrototype.js:
(globalPrivate.newRegistryEntry):
(requestInstantiate):
(link):
* jsc.cpp:
(convertShebangToJSComment):
(fillBufferWithContentsOfFile):
(fetchModuleFromLocalFileSystem):
(GlobalObject::moduleLoaderFetch):
* parser/SourceProvider.h:
(JSC::WebAssemblySourceProvider::create):
(JSC::WebAssemblySourceProvider::WebAssemblySourceProvider):
* runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::hostResolveImportedModule):
(JSC::AbstractModuleRecord::link):
(JSC::AbstractModuleRecord::evaluate):
(JSC::identifierToJSValue): Deleted.
* runtime/AbstractModuleRecord.h:
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::evaluate):
* runtime/JSModuleRecord.cpp:
(JSC::JSModuleRecord::link):
(JSC::JSModuleRecord::instantiateDeclarations):
* runtime/JSModuleRecord.h:
* runtime/ModuleLoaderPrototype.cpp:
(JSC::moduleLoaderPrototypeParseModule):
(JSC::moduleLoaderPrototypeRequestedModules):
(JSC::moduleLoaderPrototypeModuleDeclarationInstantiation):
* wasm/js/JSWebAssemblyHelpers.h:
(JSC::getWasmBufferFromValue):
(JSC::createSourceBufferFromValue):
* wasm/js/JSWebAssemblyInstance.cpp:
(JSC::JSWebAssemblyInstance::finalizeCreation):
(JSC::JSWebAssemblyInstance::createPrivateModuleKey):
(JSC::JSWebAssemblyInstance::create):
* wasm/js/JSWebAssemblyInstance.h:
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::prepareLink):
(JSC::WebAssemblyModuleRecord::link):
* wasm/js/WebAssemblyModuleRecord.h:
* wasm/js/WebAssemblyPrototype.cpp:
(JSC::resolve):
(JSC::instantiate):
(JSC::compileAndInstantiate):
(JSC::WebAssemblyPrototype::instantiate):
(JSC::webAssemblyInstantiateFunc):
(JSC::webAssemblyValidateFunc):
* wasm/js/WebAssemblyPrototype.h:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (230696 => 230697)


--- trunk/JSTests/ChangeLog	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/JSTests/ChangeLog	2018-04-17 02:38:59 UTC (rev 230697)
@@ -1,3 +1,43 @@
+2018-04-16  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [WebAssembly][Modules] Prototype wasm import
+        https://bugs.webkit.org/show_bug.cgi?id=184600
+
+        Reviewed by JF Bastien.
+
+        Add wasm and wat files since module loader want to load wasm files from FS.
+        Currently, importing the other modules from wasm is not supported.
+
+        * wasm.yaml:
+        * wasm/modules/constant.wasm: Added.
+        * wasm/modules/constant.wat: Added.
+        * wasm/modules/js-wasm-function-namespace.js: Added.
+        (assert.throws):
+        * wasm/modules/js-wasm-function.js: Added.
+        (assert.throws):
+        * wasm/modules/js-wasm-global-namespace.js: Added.
+        (assert.throws):
+        * wasm/modules/js-wasm-global.js: Added.
+        (assert.throws):
+        * wasm/modules/js-wasm-memory-namespace.js: Added.
+        (assert.throws):
+        * wasm/modules/js-wasm-memory.js: Added.
+        (assert.throws):
+        * wasm/modules/js-wasm-start.js: Added.
+        (then):
+        * wasm/modules/js-wasm-table-namespace.js: Added.
+        (assert.throws):
+        * wasm/modules/js-wasm-table.js: Added.
+        (assert.throws):
+        * wasm/modules/memory.wasm: Added.
+        * wasm/modules/memory.wat: Added.
+        * wasm/modules/start.wasm: Added.
+        * wasm/modules/start.wat: Added.
+        * wasm/modules/sum.wasm: Added.
+        * wasm/modules/sum.wat: Added.
+        * wasm/modules/table.wasm: Added.
+        * wasm/modules/table.wat: Added.
+
 2018-04-14  Filip Pizlo  <fpi...@apple.com>
 
         Function.prototype.caller shouldn't return generator bodies

Added: trunk/JSTests/wasm/modules/constant.wasm (0 => 230697)


--- trunk/JSTests/wasm/modules/constant.wasm	                        (rev 0)
+++ trunk/JSTests/wasm/modules/constant.wasm	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1 @@
+asmA*constant
\ No newline at end of file

Added: trunk/JSTests/wasm/modules/constant.wat (0 => 230697)


--- trunk/JSTests/wasm/modules/constant.wat	                        (rev 0)
+++ trunk/JSTests/wasm/modules/constant.wat	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,2 @@
+(module
+    (global $constant (export "constant") i32 i32.const 42))

Added: trunk/JSTests/wasm/modules/js-wasm-function-namespace.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-function-namespace.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-function-namespace.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,11 @@
+import * as sum from "./sum.wasm"
+import * as assert from '../assert.js';
+
+assert.isObject(sum);
+assert.isFunction(sum.sum);
+assert.eq(sum.sum(32, 42), 74);
+assert.eq(sum.sum(-2, 42), 40);
+
+assert.throws(() => {
+    sum.sum = 32;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/js-wasm-function.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-function.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-function.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,10 @@
+import { sum } from "./sum.wasm"
+import * as assert from '../assert.js';
+
+assert.isFunction(sum);
+assert.eq(sum(32, 42), 74);
+assert.eq(sum(-2, 42), 40);
+
+assert.throws(() => {
+    sum = 32;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/js-wasm-global-namespace.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-global-namespace.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-global-namespace.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,8 @@
+import * as constant from "./constant.wasm"
+import * as assert from '../assert.js';
+
+assert.isNumber(constant.constant);
+assert.eq(constant.constant, 42);
+assert.throws(() => {
+    constant.constant = 200;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/js-wasm-global.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-global.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-global.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,8 @@
+import { constant } from "./constant.wasm"
+import * as assert from '../assert.js';
+
+assert.isNumber(constant);
+assert.eq(constant, 42);
+assert.throws(() => {
+    constant = 200;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/js-wasm-memory-namespace.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-memory-namespace.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-memory-namespace.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,12 @@
+import * as memory from "./memory.wasm"
+import * as assert from '../assert.js';
+
+assert.instanceof(memory.memory, WebAssembly.Memory);
+let buffer = new Uint8Array(memory.memory.buffer);
+assert.eq(buffer[4], 0x10);
+assert.eq(buffer[5], 0x00);
+assert.eq(buffer[6], 0x10);
+assert.eq(buffer[7], 0x00);
+assert.throws(() => {
+    memory.memory = 200;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/js-wasm-memory.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-memory.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-memory.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,12 @@
+import { memory } from "./memory.wasm"
+import * as assert from '../assert.js';
+
+assert.instanceof(memory, WebAssembly.Memory);
+let buffer = new Uint8Array(memory.buffer);
+assert.eq(buffer[4], 0x10);
+assert.eq(buffer[5], 0x00);
+assert.eq(buffer[6], 0x10);
+assert.eq(buffer[7], 0x00);
+assert.throws(() => {
+    memory = 200;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/js-wasm-start.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-start.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-start.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,9 @@
+import * as assert from '../assert.js';
+
+Promise.all([
+    import("./start.wasm"),
+    import("./start.wasm"),
+]).then(([start0, start1]) => {
+    assert.eq(start0, start1);
+    assert.eq(start0.get(), 1);
+}, $vm.abort);

Added: trunk/JSTests/wasm/modules/js-wasm-table-namespace.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-table-namespace.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-table-namespace.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,15 @@
+import * as table from "./table.wasm"
+import * as assert from '../assert.js';
+
+assert.instanceof(table.table, WebAssembly.Table);
+assert.eq(table.table.length, 3);
+assert.isFunction(table.table.get(0));
+assert.isFunction(table.table.get(1));
+assert.eq(table.table.get(2), null);
+
+assert.eq(table.table.get(0)(), 42);
+assert.eq(table.table.get(1)(), 83);
+
+assert.throws(() => {
+    table.table = 32;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/js-wasm-table.js (0 => 230697)


--- trunk/JSTests/wasm/modules/js-wasm-table.js	                        (rev 0)
+++ trunk/JSTests/wasm/modules/js-wasm-table.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,15 @@
+import { table } from "./table.wasm"
+import * as assert from '../assert.js';
+
+assert.instanceof(table, WebAssembly.Table);
+assert.eq(table.length, 3);
+assert.isFunction(table.get(0));
+assert.isFunction(table.get(1));
+assert.eq(table.get(2), null);
+
+assert.eq(table.get(0)(), 42);
+assert.eq(table.get(1)(), 83);
+
+assert.throws(() => {
+    table = 32;
+}, TypeError, `Attempted to assign to readonly property.`);

Added: trunk/JSTests/wasm/modules/memory.wasm (0 => 230697)


--- trunk/JSTests/wasm/modules/memory.wasm	                        (rev 0)
+++ trunk/JSTests/wasm/modules/memory.wasm	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,3 @@
+asm
+memory
+A
\ No newline at end of file

Added: trunk/JSTests/wasm/modules/memory.wat (0 => 230697)


--- trunk/JSTests/wasm/modules/memory.wat	                        (rev 0)
+++ trunk/JSTests/wasm/modules/memory.wat	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,3 @@
+(module
+    (memory $memory (export "memory") 17)
+    (data (i32.const 4) "\10\00\10\00"))

Added: trunk/JSTests/wasm/modules/start.wasm (0 => 230697)


--- trunk/JSTests/wasm/modules/start.wasm	                        (rev 0)
+++ trunk/JSTests/wasm/modules/start.wasm	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,2 @@
+asm``Aget
+	#Aj$#
\ No newline at end of file

Added: trunk/JSTests/wasm/modules/start.wat (0 => 230697)


--- trunk/JSTests/wasm/modules/start.wat	                        (rev 0)
+++ trunk/JSTests/wasm/modules/start.wat	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,12 @@
+(module
+    (global $g0 (mut i32) i32.const 0)
+    (type $t0 (func))
+    (func $increment (type $t0)
+        get_global $g0
+        i32.const 1
+        i32.add
+        set_global $g0)
+    (start $increment)
+    (type $t1 (func (result i32)))
+    (func $get (export "get") (type $t1) (result i32)
+        get_global $g0))

Added: trunk/JSTests/wasm/modules/sum.wasm (0 => 230697)


--- trunk/JSTests/wasm/modules/sum.wasm	                        (rev 0)
+++ trunk/JSTests/wasm/modules/sum.wasm	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,2 @@
+asm`sum
+	  j
\ No newline at end of file

Added: trunk/JSTests/wasm/modules/sum.wat (0 => 230697)


--- trunk/JSTests/wasm/modules/sum.wat	                        (rev 0)
+++ trunk/JSTests/wasm/modules/sum.wat	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,6 @@
+(module
+    (type $t0 (func (param i32 i32) (result i32)))
+    (func $sum (export "sum") (type $t0) (param $p0 i32) (param $p1 i32) (result i32)
+        get_local $p1
+        get_local $p0
+        i32.add))

Added: trunk/JSTests/wasm/modules/table.wasm (0 => 230697)


--- trunk/JSTests/wasm/modules/table.wasm	                        (rev 0)
+++ trunk/JSTests/wasm/modules/table.wasm	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,2 @@
+asm`p	table	A
+A*A\xD3
\ No newline at end of file

Added: trunk/JSTests/wasm/modules/table.wat (0 => 230697)


--- trunk/JSTests/wasm/modules/table.wat	                        (rev 0)
+++ trunk/JSTests/wasm/modules/table.wat	2018-04-17 02:38:59 UTC (rev 230697)
@@ -0,0 +1,5 @@
+(module
+    (table $table (export "table") 3 anyfunc)
+    (func $f0 (result i32) i32.const 42)
+    (func $f1 (result i32) i32.const 83)
+    (elem (i32.const 0) $f0 $f1))

Modified: trunk/JSTests/wasm.yaml (230696 => 230697)


--- trunk/JSTests/wasm.yaml	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/JSTests/wasm.yaml	2018-04-17 02:38:59 UTC (rev 230697)
@@ -37,6 +37,8 @@
   cmd: runWebAssemblyLowExecutableMemory unless parseRunCommands
 - path: wasm/regress/
   cmd: runWebAssembly unless parseRunCommands
+- path: wasm/modules/
+  cmd: runWebAssembly unless parseRunCommands
 
 - path: wasm/spec-tests/address.wast.js
   cmd: runWebAssemblySpecTest :normal

Modified: trunk/Source/_javascript_Core/ChangeLog (230696 => 230697)


--- trunk/Source/_javascript_Core/ChangeLog	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/ChangeLog	2018-04-17 02:38:59 UTC (rev 230697)
@@ -1,3 +1,77 @@
+2018-04-16  Yusuke Suzuki  <utatane....@gmail.com>
+
+        [WebAssembly][Modules] Prototype wasm import
+        https://bugs.webkit.org/show_bug.cgi?id=184600
+
+        Reviewed by JF Bastien.
+
+        This patch is an initial attempt to implement Wasm loading in module pipeline.
+        Currently,
+
+        1. We only support Wasm loading in the JSC shell. Once loading mechanism is specified
+           in whatwg HTML, we should integrate this into WebCore.
+
+        2. We only support exporting values from Wasm. Wasm module cannot import anything from
+           the other modules now.
+
+        When loading a file, JSC shell checks wasm magic. If the wasm magic is found, JSC shell
+        loads the file with WebAssemblySourceProvider. It is wrapped into JSSourceCode and
+        module loader pipeline just handles it as the same to JS. When parsing a module, we
+        checks the type of JSSourceCode. If the source code is Wasm source code, we create a
+        WebAssemblyModuleRecord instead of JSModuleRecord. Our module pipeline handles
+        AbstractModuleRecord and Wasm module is instantiated, linked, and evaluated.
+
+        * builtins/ModuleLoaderPrototype.js:
+        (globalPrivate.newRegistryEntry):
+        (requestInstantiate):
+        (link):
+        * jsc.cpp:
+        (convertShebangToJSComment):
+        (fillBufferWithContentsOfFile):
+        (fetchModuleFromLocalFileSystem):
+        (GlobalObject::moduleLoaderFetch):
+        * parser/SourceProvider.h:
+        (JSC::WebAssemblySourceProvider::create):
+        (JSC::WebAssemblySourceProvider::WebAssemblySourceProvider):
+        * runtime/AbstractModuleRecord.cpp:
+        (JSC::AbstractModuleRecord::hostResolveImportedModule):
+        (JSC::AbstractModuleRecord::link):
+        (JSC::AbstractModuleRecord::evaluate):
+        (JSC::identifierToJSValue): Deleted.
+        * runtime/AbstractModuleRecord.h:
+        * runtime/JSModuleLoader.cpp:
+        (JSC::JSModuleLoader::evaluate):
+        * runtime/JSModuleRecord.cpp:
+        (JSC::JSModuleRecord::link):
+        (JSC::JSModuleRecord::instantiateDeclarations):
+        * runtime/JSModuleRecord.h:
+        * runtime/ModuleLoaderPrototype.cpp:
+        (JSC::moduleLoaderPrototypeParseModule):
+        (JSC::moduleLoaderPrototypeRequestedModules):
+        (JSC::moduleLoaderPrototypeModuleDeclarationInstantiation):
+        * wasm/js/JSWebAssemblyHelpers.h:
+        (JSC::getWasmBufferFromValue):
+        (JSC::createSourceBufferFromValue):
+        * wasm/js/JSWebAssemblyInstance.cpp:
+        (JSC::JSWebAssemblyInstance::finalizeCreation):
+        (JSC::JSWebAssemblyInstance::createPrivateModuleKey):
+        (JSC::JSWebAssemblyInstance::create):
+        * wasm/js/JSWebAssemblyInstance.h:
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::prepareLink):
+        (JSC::WebAssemblyModuleRecord::link):
+        * wasm/js/WebAssemblyModuleRecord.h:
+        * wasm/js/WebAssemblyPrototype.cpp:
+        (JSC::resolve):
+        (JSC::instantiate):
+        (JSC::compileAndInstantiate):
+        (JSC::WebAssemblyPrototype::instantiate):
+        (JSC::webAssemblyInstantiateFunc):
+        (JSC::webAssemblyValidateFunc):
+        * wasm/js/WebAssemblyPrototype.h:
+
 2018-04-14  Filip Pizlo  <fpi...@apple.com>
 
         Function.prototype.caller shouldn't return generator bodies

Modified: trunk/Source/_javascript_Core/builtins/ModuleLoaderPrototype.js (230696 => 230697)


--- trunk/Source/_javascript_Core/builtins/ModuleLoaderPrototype.js	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/builtins/ModuleLoaderPrototype.js	2018-04-17 02:38:59 UTC (rev 230697)
@@ -95,7 +95,6 @@
         instantiate: @undefined,
         satisfy: @undefined,
         dependencies: [], // To keep the module order, we store the module keys in the array.
-        dependenciesMap: @undefined,
         module: @undefined, // JSModuleRecord
         linkError: @undefined,
         linkSucceeded: true,
@@ -197,22 +196,22 @@
         entry.instantiate = instantiatePromise;
 
         var key = entry.key;
-        var moduleRecord = this.parseModule(key, source);
-        var dependenciesMap = moduleRecord.dependenciesMap;
-        var requestedModules = this.requestedModules(moduleRecord);
-        var dependencies = @newArrayWithSize(requestedModules.length);
-        for (var i = 0, length = requestedModules.length; i < length; ++i) {
-            var depName = requestedModules[i];
-            var depKey = this.resolveSync(depName, key, fetcher);
-            var depEntry = this.ensureRegistered(depKey);
-            @putByValDirect(dependencies, i, depEntry);
-            dependenciesMap.@set(depName, depEntry);
-        }
-        entry.dependencies = dependencies;
-        entry.dependenciesMap = dependenciesMap;
-        entry.module = moduleRecord;
-        @setStateToMax(entry, @ModuleSatisfy);
-        return entry;
+        return this.parseModule(key, source).then((moduleRecord) => {
+            var dependenciesMap = moduleRecord.dependenciesMap;
+            var requestedModules = this.requestedModules(moduleRecord);
+            var dependencies = @newArrayWithSize(requestedModules.length);
+            for (var i = 0, length = requestedModules.length; i < length; ++i) {
+                var depName = requestedModules[i];
+                var depKey = this.resolveSync(depName, key, fetcher);
+                var depEntry = this.ensureRegistered(depKey);
+                @putByValDirect(dependencies, i, depEntry);
+                dependenciesMap.@set(depName, depEntry);
+            }
+            entry.dependencies = dependencies;
+            entry.module = moduleRecord;
+            @setStateToMax(entry, @ModuleSatisfy);
+            return entry;
+        });
     });
     return instantiatePromise;
 }
@@ -288,7 +287,7 @@
         for (var i = 0, length = dependencies.length; i < length; ++i)
             this.link(dependencies[i], fetcher);
 
-        this.moduleDeclarationInstantiation(entry.module, entry.key, fetcher);
+        this.moduleDeclarationInstantiation(entry.module, fetcher);
     } catch (error) {
         entry.linkSucceeded = false;
         entry.linkError = error;

Modified: trunk/Source/_javascript_Core/jsc.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/jsc.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/jsc.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -186,7 +186,8 @@
 
 }
 
-static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
+template<typename Vector>
+static bool fillBufferWithContentsOfFile(const String& fileName, Vector& buffer);
 static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName);
 
 class CommandLine;
@@ -844,7 +845,8 @@
     return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
 }
 
-static void convertShebangToJSComment(Vector<char>& buffer)
+template<typename Vector>
+static void convertShebangToJSComment(Vector& buffer)
 {
     if (buffer.size() >= 2) {
         if (buffer[0] == '#' && buffer[1] == '!')
@@ -882,7 +884,8 @@
     return result;
 }
 
-static bool fillBufferWithContentsOfFile(FILE* file, Vector<char>& buffer)
+template<typename Vector>
+static bool fillBufferWithContentsOfFile(FILE* file, Vector& buffer)
 {
     // We might have injected "use strict"; at the top.
     size_t initialSize = buffer.size();
@@ -920,7 +923,8 @@
     return true;
 }
 
-static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector<char>& buffer)
+template<typename Vector>
+static bool fetchModuleFromLocalFileSystem(const String& fileName, Vector& buffer)
 {
     // We assume that fileName is always an absolute path.
 #if OS(WINDOWS)
@@ -971,14 +975,25 @@
     }
 
     // Here, now we consider moduleKey as the fileName.
-    Vector<char> utf8;
-    if (!fetchModuleFromLocalFileSystem(moduleKey, utf8)) {
+    Vector<uint8_t> buffer;
+    if (!fetchModuleFromLocalFileSystem(moduleKey, buffer)) {
         auto result = deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
         scope.releaseAssertNoException();
         return result;
     }
 
-    auto result = deferred->resolve(exec, JSSourceCode::create(vm, makeSource(stringFromUTF(utf8), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
+#if ENABLE(WEBASSEMBLY)
+    // FileSystem does not have mime-type header. The JSC shell recognizes WebAssembly's magic header.
+    if (buffer.size() >= 4) {
+        if (buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' && buffer[3] == 'm') {
+            auto result = deferred->resolve(exec, JSSourceCode::create(vm, SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleKey }, moduleKey))));
+            scope.releaseAssertNoException();
+            return result;
+        }
+    }
+#endif
+
+    auto result = deferred->resolve(exec, JSSourceCode::create(vm, makeSource(stringFromUTF(buffer), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
     scope.releaseAssertNoException();
     return result;
 }

Modified: trunk/Source/_javascript_Core/parser/SourceProvider.h (230696 => 230697)


--- trunk/Source/_javascript_Core/parser/SourceProvider.h	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/parser/SourceProvider.h	2018-04-17 02:38:59 UTC (rev 230697)
@@ -120,9 +120,9 @@
 #if ENABLE(WEBASSEMBLY)
     class WebAssemblySourceProvider : public SourceProvider {
     public:
-        static Ref<WebAssemblySourceProvider> create(const Vector<uint8_t>& data, const SourceOrigin& sourceOrigin, const String& url)
+        static Ref<WebAssemblySourceProvider> create(Vector<uint8_t>&& data, const SourceOrigin& sourceOrigin, const String& url)
         {
-            return adoptRef(*new WebAssemblySourceProvider(data, sourceOrigin, url));
+            return adoptRef(*new WebAssemblySourceProvider(WTFMove(data), sourceOrigin, url));
         }
 
         unsigned hash() const override
@@ -141,10 +141,10 @@
         }
 
     private:
-        WebAssemblySourceProvider(const Vector<uint8_t>& data, const SourceOrigin& sourceOrigin, const String& url)
+        WebAssemblySourceProvider(Vector<uint8_t>&& data, const SourceOrigin& sourceOrigin, const String& url)
             : SourceProvider(sourceOrigin, url, TextPosition(), SourceProviderSourceType::WebAssembly)
             , m_source("[WebAssembly source]")
-            , m_data(data)
+            , m_data(WTFMove(data))
         {
         }
 

Modified: trunk/Source/_javascript_Core/runtime/AbstractModuleRecord.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/runtime/AbstractModuleRecord.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/runtime/AbstractModuleRecord.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -32,7 +32,9 @@
 #include "JSMap.h"
 #include "JSModuleEnvironment.h"
 #include "JSModuleNamespaceObject.h"
+#include "JSModuleRecord.h"
 #include "UnlinkedModuleProgramCodeBlock.h"
+#include "WebAssemblyModuleRecord.h"
 
 namespace JSC {
 namespace AbstractModuleRecordInternal {
@@ -137,19 +139,11 @@
     return Resolution { Type::Ambiguous, nullptr, Identifier() };
 }
 
-static JSValue identifierToJSValue(ExecState* exec, const Identifier& identifier)
-{
-    VM& vm = exec->vm();
-    if (identifier.isSymbol())
-        return Symbol::create(vm, static_cast<SymbolImpl&>(*identifier.impl()));
-    return jsString(&vm, identifier.impl());
-}
-
 AbstractModuleRecord* AbstractModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName)
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    JSValue moduleNameValue = identifierToJSValue(exec, moduleName);
+    JSValue moduleNameValue = identifierToJSValue(vm, moduleName);
     JSValue entry = m_dependenciesMap->JSMap::get(exec, moduleNameValue);
     RETURN_IF_EXCEPTION(scope, nullptr);
     scope.release();
@@ -775,6 +769,31 @@
     return moduleNamespaceObject;
 }
 
+void AbstractModuleRecord::link(ExecState* exec, JSValue scriptFetcher)
+{
+    VM& vm = exec->vm();
+    if (auto* jsModuleRecord = jsDynamicCast<JSModuleRecord*>(vm, this))
+        return jsModuleRecord->link(exec, scriptFetcher);
+#if ENABLE(WEBASSEMBLY)
+    if (auto* wasmModuleRecord = jsDynamicCast<WebAssemblyModuleRecord*>(vm, this))
+        return wasmModuleRecord->link(exec, scriptFetcher);
+#endif
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+JS_EXPORT_PRIVATE JSValue AbstractModuleRecord::evaluate(ExecState* exec)
+{
+    VM& vm = exec->vm();
+    if (auto* jsModuleRecord = jsDynamicCast<JSModuleRecord*>(vm, this))
+        return jsModuleRecord->evaluate(exec);
+#if ENABLE(WEBASSEMBLY)
+    if (auto* wasmModuleRecord = jsDynamicCast<WebAssemblyModuleRecord*>(vm, this))
+        return wasmModuleRecord->evaluate(exec);
+#endif
+    RELEASE_ASSERT_NOT_REACHED();
+    return jsUndefined();
+}
+
 static String printableName(const RefPtr<UniquedStringImpl>& uid)
 {
     if (uid->isSymbol())

Modified: trunk/Source/_javascript_Core/runtime/AbstractModuleRecord.h (230696 => 230697)


--- trunk/Source/_javascript_Core/runtime/AbstractModuleRecord.h	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/runtime/AbstractModuleRecord.h	2018-04-17 02:38:59 UTC (rev 230697)
@@ -119,6 +119,9 @@
         return m_moduleEnvironment.get();
     }
 
+    void link(ExecState*, JSValue scriptFetcher);
+    JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
+
 protected:
     AbstractModuleRecord(VM&, Structure*, const Identifier&);
     void finishCreation(ExecState*, VM&);

Modified: trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -275,10 +275,9 @@
     if (globalObject->globalObjectMethodTable()->moduleLoaderEvaluate)
         return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, scriptFetcher);
 
-    JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(exec->vm(), moduleRecordValue);
-    if (!moduleRecord)
-        return jsUndefined();
-    return moduleRecord->evaluate(exec);
+    if (auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(exec->vm(), moduleRecordValue))
+        return moduleRecord->evaluate(exec);
+    return jsUndefined();
 }
 
 JSModuleNamespaceObject* JSModuleLoader::getModuleNamespaceObject(ExecState* exec, JSValue moduleRecordValue)

Modified: trunk/Source/_javascript_Core/runtime/JSModuleRecord.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/runtime/JSModuleRecord.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/runtime/JSModuleRecord.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -78,7 +78,7 @@
     visitor.append(thisObject->m_moduleProgramExecutable);
 }
 
-void JSModuleRecord::link(ExecState* exec, JSValue key, JSValue scriptFetcher)
+void JSModuleRecord::link(ExecState* exec, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -89,12 +89,12 @@
         throwSyntaxError(exec, scope);
         return;
     }
-    instantiateDeclarations(exec, executable, key, scriptFetcher);
+    instantiateDeclarations(exec, executable, scriptFetcher);
     RETURN_IF_EXCEPTION(scope, void());
     m_moduleProgramExecutable.set(vm, this, executable);
 }
 
-void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecutable* moduleProgramExecutable, JSValue key, JSValue scriptFetcher)
+void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecutable* moduleProgramExecutable, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -208,7 +208,7 @@
     }
 
     {
-        JSObject* metaProperties = exec->lexicalGlobalObject()->moduleLoader()->createImportMetaProperties(exec, key, this, scriptFetcher);
+        JSObject* metaProperties = exec->lexicalGlobalObject()->moduleLoader()->createImportMetaProperties(exec, identifierToJSValue(vm, moduleKey()), this, scriptFetcher);
         RETURN_IF_EXCEPTION(scope, void());
         bool putResult = false;
         symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, vm.propertyNames->builtinNames().metaPrivateName(), metaProperties, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true, putResult);

Modified: trunk/Source/_javascript_Core/runtime/JSModuleRecord.h (230696 => 230697)


--- trunk/Source/_javascript_Core/runtime/JSModuleRecord.h	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/runtime/JSModuleRecord.h	2018-04-17 02:38:59 UTC (rev 230697)
@@ -45,7 +45,7 @@
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
     static JSModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const SourceCode&, const VariableEnvironment&, const VariableEnvironment&);
 
-    void link(ExecState*, JSValue key, JSValue scriptFetcher);
+    void link(ExecState*, JSValue scriptFetcher);
     JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
 
     const SourceCode& sourceCode() const { return m_sourceCode; }
@@ -60,7 +60,7 @@
     static void visitChildren(JSCell*, SlotVisitor&);
     static void destroy(JSCell*);
 
-    void instantiateDeclarations(ExecState*, ModuleProgramExecutable*, JSValue key, JSValue scriptFetcher);
+    void instantiateDeclarations(ExecState*, ModuleProgramExecutable*, JSValue scriptFetcher);
 
     SourceCode m_sourceCode;
     VariableEnvironment m_declaredVariables;

Modified: trunk/Source/_javascript_Core/runtime/ModuleLoaderPrototype.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/runtime/ModuleLoaderPrototype.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/runtime/ModuleLoaderPrototype.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -45,6 +45,7 @@
 #include "Nodes.h"
 #include "Parser.h"
 #include "ParserError.h"
+#include "WebAssemblyPrototype.h"
 
 namespace JSC {
 
@@ -76,7 +77,7 @@
     requestInstantiate             JSBuiltin                                           DontEnum|Function 3
     requestSatisfy                 JSBuiltin                                           DontEnum|Function 3
     link                           JSBuiltin                                           DontEnum|Function 2
-    moduleDeclarationInstantiation moduleLoaderPrototypeModuleDeclarationInstantiation DontEnum|Function 3
+    moduleDeclarationInstantiation moduleLoaderPrototypeModuleDeclarationInstantiation DontEnum|Function 2
     moduleEvaluation               JSBuiltin                                           DontEnum|Function 2
     evaluate                       moduleLoaderPrototypeEvaluate                       DontEnum|Function 3
     provideFetch                   JSBuiltin                                           DontEnum|Function 2
@@ -103,16 +104,30 @@
 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeParseModule(ExecState* exec)
 {
     VM& vm = exec->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
+    auto scope = DECLARE_CATCH_SCOPE(vm);
 
+    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, exec->lexicalGlobalObject());
+    scope.releaseAssertNoException();
+
+    auto reject = [&] {
+        JSValue exception = scope.exception();
+        scope.clearException();
+        return JSValue::encode(deferred->reject(exec, exception));
+    };
+
     const Identifier moduleKey = exec->argument(0).toPropertyKey(exec);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    if (UNLIKELY(scope.exception()))
+        return reject();
 
-    auto* jsSourceCode = jsDynamicCast<JSSourceCode*>(vm, exec->argument(1));
-    if (!jsSourceCode)
-        return throwVMTypeError(exec, scope);
+    JSValue source = exec->argument(1);
+    auto* jsSourceCode = jsCast<JSSourceCode*>(source);
     SourceCode sourceCode = jsSourceCode->sourceCode();
 
+#if ENABLE(WEBASSEMBLY)
+    if (sourceCode.provider()->sourceType() == SourceProviderSourceType::WebAssembly)
+        return JSValue::encode(WebAssemblyPrototype::instantiate(exec, deferred, moduleKey, jsSourceCode));
+#endif
+
     CodeProfiling profile(sourceCode);
 
     ParserError error;
@@ -119,18 +134,15 @@
     std::unique_ptr<ModuleProgramNode> moduleProgramNode = parse<ModuleProgramNode>(
         &vm, sourceCode, Identifier(), JSParserBuiltinMode::NotBuiltin,
         JSParserStrictMode::Strict, JSParserScriptMode::Module, SourceParseMode::ModuleAnalyzeMode, SuperBinding::NotNeeded, error);
-
-    if (error.isValid()) {
-        throwVMError(exec, scope, error.toErrorObject(exec->lexicalGlobalObject(), sourceCode));
-        return JSValue::encode(jsUndefined());
-    }
+    if (error.isValid())
+        return JSValue::encode(deferred->reject(exec, error.toErrorObject(exec->lexicalGlobalObject(), sourceCode)));
     ASSERT(moduleProgramNode);
 
     ModuleAnalyzer moduleAnalyzer(exec, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    JSModuleRecord* moduleRecord = moduleAnalyzer.analyze(*moduleProgramNode);
+    if (UNLIKELY(scope.exception()))
+        return reject();
 
-    return JSValue::encode(moduleRecord);
+    return JSValue::encode(deferred->resolve(exec, moduleAnalyzer.analyze(*moduleProgramNode)));
 }
 
 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeRequestedModules(ExecState* exec)
@@ -137,7 +149,7 @@
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(vm, exec->argument(0));
+    auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(vm, exec->argument(0));
     if (!moduleRecord) {
         scope.release();
         return JSValue::encode(constructEmptyArray(exec, nullptr));
@@ -157,7 +169,7 @@
 {
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
-    JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(vm, exec->argument(0));
+    auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(vm, exec->argument(0));
     if (!moduleRecord)
         return JSValue::encode(jsUndefined());
 
@@ -164,7 +176,7 @@
     if (Options::dumpModuleLoadingState())
         dataLog("Loader [link] ", moduleRecord->moduleKey(), "\n");
 
-    moduleRecord->link(exec, exec->argument(1), exec->argument(2));
+    moduleRecord->link(exec, exec->argument(1));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     return JSValue::encode(jsUndefined());

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyHelpers.h (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyHelpers.h	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyHelpers.h	2018-04-17 02:38:59 UTC (rev 230697)
@@ -29,6 +29,7 @@
 
 #include "JSArrayBuffer.h"
 #include "JSCJSValue.h"
+#include "JSSourceCode.h"
 #include "WebAssemblyFunction.h"
 #include "WebAssemblyWrapperFunction.h"
 
@@ -49,10 +50,16 @@
     return static_cast<uint32_t>(doubleValue);
 }
 
-ALWAYS_INLINE std::pair<uint8_t*, size_t> getWasmBufferFromValue(ExecState* exec, JSValue value)
+ALWAYS_INLINE std::pair<const uint8_t*, size_t> getWasmBufferFromValue(ExecState* exec, JSValue value)
 {
     VM& vm = exec->vm();
     auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+    if (auto* source = jsDynamicCast<JSSourceCode*>(vm, value)) {
+        auto* provider = static_cast<WebAssemblySourceProvider*>(source->sourceCode().provider());
+        return { provider->data().data(), provider->data().size() };
+    }
+
     // If the given bytes argument is not a BufferSource, a TypeError exception is thrown.
     JSArrayBuffer* arrayBuffer = value.getObject() ? jsDynamicCast<JSArrayBuffer*>(vm, value.getObject()) : nullptr;
     JSArrayBufferView* arrayBufferView = value.getObject() ? jsDynamicCast<JSArrayBufferView*>(vm, value.getObject()) : nullptr;
@@ -76,7 +83,7 @@
 ALWAYS_INLINE Vector<uint8_t> createSourceBufferFromValue(VM& vm, ExecState* exec, JSValue value)
 {
     auto throwScope = DECLARE_THROW_SCOPE(vm);
-    uint8_t* data;
+    const uint8_t* data;
     size_t byteSize;
     std::tie(data, byteSize) = getWasmBufferFromValue(exec, value);
     RETURN_IF_EXCEPTION(throwScope, Vector<uint8_t>());

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -91,7 +91,7 @@
         visitor.append(*thisObject->instance().importFunction<PoisonedBarrier<JSObject>>(i)); // This also keeps the functions' JSWebAssemblyInstance alive.
 }
 
-void JSWebAssemblyInstance::finalizeCreation(VM& vm, ExecState* exec, Ref<Wasm::CodeBlock>&& wasmCodeBlock)
+void JSWebAssemblyInstance::finalizeCreation(VM& vm, ExecState* exec, Ref<Wasm::CodeBlock>&& wasmCodeBlock, ModuleRunMode moduleRunMode)
 {
     m_instance->finalizeCreation(this, wasmCodeBlock.copyRef());
 
@@ -127,16 +127,25 @@
     }
 
     auto* moduleRecord = jsCast<WebAssemblyModuleRecord*>(m_moduleNamespaceObject->moduleRecord());
-    moduleRecord->link(exec, m_module.get(), this);
-    RETURN_IF_EXCEPTION(scope, void());
+    moduleRecord->prepareLink(vm, this);
 
-    JSValue startResult = moduleRecord->evaluate(exec);
-    UNUSED_PARAM(startResult);
-    RETURN_IF_EXCEPTION(scope, void());
+    if (moduleRunMode == ModuleRunMode::Run) {
+        moduleRecord->link(exec, jsNull());
+        RETURN_IF_EXCEPTION(scope, void());
+
+        JSValue startResult = moduleRecord->evaluate(exec);
+        UNUSED_PARAM(startResult);
+        RETURN_IF_EXCEPTION(scope, void());
+    }
 }
 
-JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure, Ref<Wasm::Module>&& module)
+Identifier JSWebAssemblyInstance::createPrivateModuleKey()
 {
+    return Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance"));
+}
+
+JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, const Identifier& moduleKey, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure, Ref<Wasm::Module>&& module)
+{
     auto throwScope = DECLARE_THROW_SCOPE(vm);
     auto* globalObject = exec->lexicalGlobalObject();
 
@@ -158,7 +167,6 @@
     if (moduleInformation.imports.size() && !importObject)
         return exception(createTypeError(exec, ASCIILiteral("can't make WebAssembly.Instance because there is no imports Object and the WebAssembly.Module requires imports")));
 
-    Identifier moduleKey = Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance"));
     WebAssemblyModuleRecord* moduleRecord = WebAssemblyModuleRecord::create(exec, vm, globalObject->webAssemblyModuleRecordStructure(), moduleKey, moduleInformation);
     RETURN_IF_EXCEPTION(throwScope, nullptr);
 

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.h	2018-04-17 02:38:59 UTC (rev 230697)
@@ -50,12 +50,15 @@
 public:
     typedef JSDestructibleObject Base;
 
-    static JSWebAssemblyInstance* create(VM&, ExecState*, JSWebAssemblyModule*, JSObject* importObject, Structure*, Ref<Wasm::Module>&&);
+    static Identifier createPrivateModuleKey();
+
+    static JSWebAssemblyInstance* create(VM&, ExecState*, const Identifier& moduleKey, JSWebAssemblyModule*, JSObject* importObject, Structure*, Ref<Wasm::Module>&&);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_EXPORT_INFO;
 
-    void finalizeCreation(VM&, ExecState*, Ref<Wasm::CodeBlock>&&);
+    enum class ModuleRunMode { Run, None };
+    void finalizeCreation(VM&, ExecState*, Ref<Wasm::CodeBlock>&&, ModuleRunMode);
     
     Wasm::Instance& instance() { return m_instance.get(); }
     JSModuleNamespaceObject* moduleNamespaceObject() { return m_moduleNamespaceObject.get(); }
@@ -76,6 +79,8 @@
         instance().setTable(makeRef(*table()->table()));
     }
 
+    JSWebAssemblyModule* module() const { return m_module.get(); }
+
     static size_t offsetOfPoisonedInstance() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_instance); }
     static size_t offsetOfPoisonedCallee() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_callee); }
 
@@ -89,8 +94,6 @@
     static void visitChildren(JSCell*, SlotVisitor&);
 
 private:
-    JSWebAssemblyModule* module() const { return m_module.get(); }
-
     PoisonedRef<JSWebAssemblyInstancePoison, Wasm::Instance> m_instance;
 
     PoisonedBarrier<JSWebAssemblyModule> m_module;

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyInstanceConstructor.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -77,10 +77,10 @@
     Structure* instanceStructure = InternalFunction::createSubclassStructure(exec, exec->newTarget(), exec->lexicalGlobalObject()->WebAssemblyInstanceStructure());
     RETURN_IF_EXCEPTION(scope, { });
 
-    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, instanceStructure, Ref<Wasm::Module>(module->module()));
+    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, JSWebAssemblyInstance::createPrivateModuleKey(), module, importObject, instanceStructure, Ref<Wasm::Module>(module->module()));
     RETURN_IF_EXCEPTION(scope, { });
 
-    instance->finalizeCreation(vm, exec, module->module().compileSync(&vm.wasmContext, instance->memoryMode(), &Wasm::createJSToWasmWrapper, &Wasm::wasmToJSException));
+    instance->finalizeCreation(vm, exec, module->module().compileSync(&vm.wasmContext, instance->memoryMode(), &Wasm::createJSToWasmWrapper, &Wasm::wasmToJSException), JSWebAssemblyInstance::ModuleRunMode::Run);
     RETURN_IF_EXCEPTION(scope, { });
     return JSValue::encode(instance);
 }

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -86,14 +86,23 @@
     visitor.append(thisObject->m_startFunction);
 }
 
-void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module, JSWebAssemblyInstance* instance)
+void WebAssemblyModuleRecord::prepareLink(VM& vm, JSWebAssemblyInstance* instance)
 {
+    RELEASE_ASSERT(!m_instance);
+    m_instance.set(vm, this, instance);
+}
+
+void WebAssemblyModuleRecord::link(ExecState* exec, JSValue)
+{
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
     UNUSED_PARAM(scope);
     auto* globalObject = exec->lexicalGlobalObject();
 
-    Wasm::CodeBlock* codeBlock = instance->instance().codeBlock();
+    RELEASE_ASSERT(m_instance);
+
+    Wasm::CodeBlock* codeBlock = m_instance->instance().codeBlock();
+    JSWebAssemblyModule* module = m_instance->module();
     const Wasm::ModuleInformation& moduleInformation = module->moduleInformation();
 
     SymbolTable* exportSymbolTable = module->exportSymbolTable();
@@ -110,12 +119,12 @@
             //   ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.)
             if (exp.kindIndex < functionImportCount) {
                 unsigned functionIndex = exp.kindIndex;
-                JSObject* functionImport = instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(functionIndex)->get();
+                JSObject* functionImport = m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(functionIndex)->get();
                 if (isWebAssemblyHostFunction(vm, functionImport))
                     exportedValue = functionImport;
                 else {
                     Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(functionIndex);
-                    exportedValue = WebAssemblyWrapperFunction::create(vm, globalObject, functionImport, functionIndex, instance, signatureIndex);
+                    exportedValue = WebAssemblyWrapperFunction::create(vm, globalObject, functionImport, functionIndex, m_instance.get(), signatureIndex);
                 }
             } else {
                 //   iii. Otherwise:
@@ -126,7 +135,7 @@
                 Wasm::WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock->entrypointLoadLocationFromFunctionIndexSpace(exp.kindIndex);
                 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
                 const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex);
-                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), String::fromUTF8(exp.field), instance, embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
+                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), String::fromUTF8(exp.field), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
                 exportedValue = function;
             }
             break;
@@ -133,16 +142,16 @@
         }
         case Wasm::ExternalKind::Table: {
             // This should be guaranteed by module verification.
-            RELEASE_ASSERT(instance->table()); 
+            RELEASE_ASSERT(m_instance->table()); 
             ASSERT(exp.kindIndex == 0);
 
-            exportedValue = instance->table();
+            exportedValue = m_instance->table();
             break;
         }
         case Wasm::ExternalKind::Memory: {
             ASSERT(exp.kindIndex == 0);
 
-            exportedValue = instance->memory();
+            exportedValue = m_instance->memory();
             break;
         }
         case Wasm::ExternalKind::Global: {
@@ -152,7 +161,7 @@
             // Return ToJSValue(v).
             switch (global.type) {
             case Wasm::I32:
-                exportedValue = JSValue(instance->instance().loadI32Global(exp.kindIndex));
+                exportedValue = JSValue(m_instance->instance().loadI32Global(exp.kindIndex));
                 break;
 
             case Wasm::I64:
@@ -160,11 +169,11 @@
                 return;
 
             case Wasm::F32:
-                exportedValue = JSValue(instance->instance().loadF32Global(exp.kindIndex));
+                exportedValue = JSValue(m_instance->instance().loadF32Global(exp.kindIndex));
                 break;
 
             case Wasm::F64:
-                exportedValue = JSValue(instance->instance().loadF64Global(exp.kindIndex));
+                exportedValue = JSValue(m_instance->instance().loadF64Global(exp.kindIndex));
                 break;
 
             default:
@@ -191,18 +200,15 @@
         ASSERT(!signature.argumentCount());
         ASSERT(signature.returnType() == Wasm::Void);
         if (startFunctionIndexSpace < codeBlock->functionImportCount()) {
-            JSObject* startFunction = instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(startFunctionIndexSpace)->get();
+            JSObject* startFunction = m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(startFunctionIndexSpace)->get();
             m_startFunction.set(vm, this, startFunction);
         } else {
             Wasm::Callee& embedderEntrypointCallee = codeBlock->embedderEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
             Wasm::WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock->entrypointLoadLocationFromFunctionIndexSpace(startFunctionIndexSpace);
-            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), "start", instance, embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
+            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), "start", m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
             m_startFunction.set(vm, this, function);
         }
     }
-
-    RELEASE_ASSERT(!m_instance);
-    m_instance.set(vm, this, instance);
     m_moduleEnvironment.set(vm, this, moduleEnvironment);
 }
 

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.h (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.h	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.h	2018-04-17 02:38:59 UTC (rev 230697)
@@ -48,7 +48,8 @@
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
     static WebAssemblyModuleRecord* create(ExecState*, VM&, Structure*, const Identifier&, const Wasm::ModuleInformation&);
 
-    void link(ExecState*, JSWebAssemblyModule*, JSWebAssemblyInstance*);
+    void prepareLink(VM&, JSWebAssemblyInstance*);
+    void link(ExecState*, JSValue scriptFetcher);
     JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
 
 private:

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp	2018-04-17 02:38:59 UTC (rev 230697)
@@ -32,6 +32,7 @@
 #include "Exception.h"
 #include "FunctionPrototype.h"
 #include "JSCInlines.h"
+#include "JSModuleNamespaceObject.h"
 #include "JSPromiseDeferred.h"
 #include "JSToWasm.h"
 #include "JSWebAssemblyHelpers.h"
@@ -120,16 +121,21 @@
     }
 }
 
-enum class Resolve { WithInstance, WithModuleAndInstance };
-static void resolve(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyInstance* instance, JSWebAssemblyModule* module, Ref<Wasm::CodeBlock>&& codeBlock, Resolve resolveKind)
+enum class Resolve { WithInstance, WithModuleRecord, WithModuleAndInstance };
+static void resolve(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyInstance* instance, JSWebAssemblyModule* module, Ref<Wasm::CodeBlock>&& codeBlock, Resolve resolveKind, JSWebAssemblyInstance::ModuleRunMode moduleRunMode)
 {
     auto scope = DECLARE_CATCH_SCOPE(vm);
-    instance->finalizeCreation(vm, exec, WTFMove(codeBlock));
+    instance->finalizeCreation(vm, exec, WTFMove(codeBlock), moduleRunMode);
     RETURN_IF_EXCEPTION(scope, reject(exec, scope, promise));
 
     if (resolveKind == Resolve::WithInstance)
         promise->resolve(exec, instance);
-    else {
+    else if (resolveKind == Resolve::WithModuleRecord) {
+        auto* moduleRecord = instance->moduleNamespaceObject()->moduleRecord();
+        if (Options::dumpModuleRecord())
+            moduleRecord->dump();
+        promise->resolve(exec, moduleRecord);
+    } else {
         JSObject* result = constructEmptyObject(exec);
         result->putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("module")), module);
         result->putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("instance")), instance);
@@ -138,11 +144,11 @@
     CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
 }
 
-static void instantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyModule* module, JSObject* importObject, Resolve resolveKind)
+static void instantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAssemblyModule* module, JSObject* importObject, const Identifier& moduleKey, Resolve resolveKind, JSWebAssemblyInstance::ModuleRunMode moduleRunMode)
 {
     auto scope = DECLARE_CATCH_SCOPE(vm);
     // In order to avoid potentially recompiling a module. We first gather all the import/memory information prior to compiling code.
-    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, module, importObject, exec->lexicalGlobalObject()->WebAssemblyInstanceStructure(), Ref<Wasm::Module>(module->module()));
+    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, exec, moduleKey, module, importObject, exec->lexicalGlobalObject()->WebAssemblyInstanceStructure(), Ref<Wasm::Module>(module->module()));
     RETURN_IF_EXCEPTION(scope, reject(exec, scope, promise));
 
     Vector<Strong<JSCell>> dependencies;
@@ -150,30 +156,32 @@
     dependencies.append(Strong<JSCell>(vm, instance));
     vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies));
     // Note: This completion task may or may not get called immediately.
-    module->module().compileAsync(&vm.wasmContext, instance->memoryMode(), createSharedTask<Wasm::CodeBlock::CallbackType>([promise, instance, module, resolveKind, &vm] (Ref<Wasm::CodeBlock>&& refCodeBlock) mutable {
+    module->module().compileAsync(&vm.wasmContext, instance->memoryMode(), createSharedTask<Wasm::CodeBlock::CallbackType>([promise, instance, module, resolveKind, moduleRunMode, &vm] (Ref<Wasm::CodeBlock>&& refCodeBlock) mutable {
         RefPtr<Wasm::CodeBlock> codeBlock = WTFMove(refCodeBlock);
-        vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, instance, module, resolveKind, &vm, codeBlock = WTFMove(codeBlock)] () mutable {
+        vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, instance, module, resolveKind, moduleRunMode, &vm, codeBlock = WTFMove(codeBlock)] () mutable {
             ExecState* exec = instance->globalObject()->globalExec();
-            resolve(vm, exec, promise, instance, module, codeBlock.releaseNonNull(), resolveKind);
+            resolve(vm, exec, promise, instance, module, codeBlock.releaseNonNull(), resolveKind, moduleRunMode);
         });
     }), &Wasm::createJSToWasmWrapper, &Wasm::wasmToJSException);
 }
 
-static void compileAndInstantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSValue buffer, JSObject* importObject)
+static void compileAndInstantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, const Identifier& moduleKey, JSValue buffer, JSObject* importObject, Resolve resolveKind, JSWebAssemblyInstance::ModuleRunMode moduleRunMode)
 {
     auto scope = DECLARE_CATCH_SCOPE(vm);
 
     auto* globalObject = exec->lexicalGlobalObject();
 
+    JSCell* moduleKeyCell = identifierToJSValue(vm, moduleKey).asCell();
     Vector<Strong<JSCell>> dependencies;
     dependencies.append(Strong<JSCell>(vm, importObject));
+    dependencies.append(Strong<JSCell>(vm, moduleKeyCell));
     vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies));
 
     Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, buffer);
     RETURN_IF_EXCEPTION(scope, reject(exec, scope, promise));
 
-    Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, importObject, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable {
-        vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, importObject, globalObject, result = WTFMove(result), &vm] () mutable {
+    Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, importObject, moduleKeyCell, globalObject, resolveKind, moduleRunMode, &vm] (Wasm::Module::ValidationResult&& result) mutable {
+        vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, importObject, moduleKeyCell, globalObject, result = WTFMove(result), resolveKind, moduleRunMode, &vm] () mutable {
             auto scope = DECLARE_CATCH_SCOPE(vm);
             ExecState* exec = globalObject->globalExec();
             JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(result));
@@ -180,11 +188,22 @@
             if (UNLIKELY(scope.exception()))
                 return reject(exec, scope, promise);
 
-            instantiate(vm, exec, promise, module, importObject, Resolve::WithModuleAndInstance);
+            const Identifier moduleKey = JSValue(moduleKeyCell).toPropertyKey(exec);
+            if (UNLIKELY(scope.exception()))
+                return reject(exec, scope, promise);
+
+            instantiate(vm, exec, promise, module, importObject, moduleKey, resolveKind, moduleRunMode);
         });
     }));
 }
 
+JSValue WebAssemblyPrototype::instantiate(ExecState* exec, JSPromiseDeferred* promise, const Identifier& moduleKey, JSValue argument)
+{
+    VM& vm = exec->vm();
+    compileAndInstantiate(vm, exec, promise, moduleKey, argument, nullptr, Resolve::WithModuleRecord, JSWebAssemblyInstance::ModuleRunMode::None);
+    return promise->promise();
+}
+
 static EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec)
 {
     VM& vm = exec->vm();
@@ -206,9 +225,9 @@
         } else {
             JSValue firstArgument = exec->argument(0);
             if (auto* module = jsDynamicCast<JSWebAssemblyModule*>(vm, firstArgument))
-                instantiate(vm, exec, promise, module, importObject, Resolve::WithInstance);
+                instantiate(vm, exec, promise, module, importObject, JSWebAssemblyInstance::createPrivateModuleKey(), Resolve::WithInstance, JSWebAssemblyInstance::ModuleRunMode::Run);
             else
-                compileAndInstantiate(vm, exec, promise, firstArgument, importObject);
+                compileAndInstantiate(vm, exec, promise, JSWebAssemblyInstance::createPrivateModuleKey(), firstArgument, importObject, Resolve::WithModuleAndInstance, JSWebAssemblyInstance::ModuleRunMode::Run);
         }
 
         return JSValue::encode(promise->promise());
@@ -220,7 +239,7 @@
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    uint8_t* base;
+    const uint8_t* base;
     size_t byteSize;
     std::tie(base, byteSize) = getWasmBufferFromValue(exec, exec->argument(0));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());

Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.h (230696 => 230697)


--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.h	2018-04-17 02:02:06 UTC (rev 230696)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.h	2018-04-17 02:38:59 UTC (rev 230697)
@@ -42,6 +42,8 @@
 
     DECLARE_INFO;
 
+    static JSValue instantiate(ExecState*, JSPromiseDeferred*, const Identifier&, JSValue);
+
 protected:
     void finishCreation(VM&);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to