Unreviewed, reland r230697, r230720, and r230724.
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Apr 2018 09:47:19 +0000 (09:47 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 18 Apr 2018 09:47:19 +0000 (09:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=184600

JSTests:

* wasm.yaml:
* wasm/modules/constant.wasm: Added.
* wasm/modules/constant.wat: Added.
* wasm/modules/default-import-star-error.js: Added.
(then):
* wasm/modules/default-import-star-error/entry.wasm: Added.
* wasm/modules/default-import-star-error/entry.wat: Added.
* wasm/modules/default-import-star-error/t0.js: Added.
* wasm/modules/default-import-star-error/t1.js: Added.
* wasm/modules/default-import-star-error/t2.js: Added.
(export.default.Cocoa):
* wasm/modules/js-wasm-cycle.js: Added.
* wasm/modules/js-wasm-cycle/entry.js: Added.
(from.string_appeared_here.export.return42):
* wasm/modules/js-wasm-cycle/sum.wasm: Added.
* wasm/modules/js-wasm-cycle/sum.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/run-from-wasm.wasm: Added.
* wasm/modules/run-from-wasm.wat: Added.
* wasm/modules/run-from-wasm/check.js: Added.
(export.check):
* 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.
* wasm/modules/wasm-imports-js-exports.js: Added.
* wasm/modules/wasm-imports-js-exports/imports.wasm: Added.
* wasm/modules/wasm-imports-js-exports/imports.wat: Added.
* wasm/modules/wasm-imports-js-exports/sum.js: Added.
(export.sum):
* wasm/modules/wasm-imports-js-re-exports-wasm-exports.js: Added.
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm: Added.
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat: Added.
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js: Added.
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm: Added.
* wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat: Added.
* wasm/modules/wasm-imports-wasm-exports.js: Added.
* wasm/modules/wasm-imports-wasm-exports/imports.wasm: Added.
* wasm/modules/wasm-imports-wasm-exports/imports.wat: Added.
* wasm/modules/wasm-imports-wasm-exports/sum.wasm: Added.
* wasm/modules/wasm-imports-wasm-exports/sum.wat: Added.
* wasm/modules/wasm-js-cycle.js: Added.
* wasm/modules/wasm-js-cycle/entry.wasm: Added.
* wasm/modules/wasm-js-cycle/entry.wat: Added.
* wasm/modules/wasm-js-cycle/sum.js: Added.
(from.string_appeared_here.export.sum):
* wasm/modules/wasm-wasm-cycle.js: Added.
* wasm/modules/wasm-wasm-cycle/entry.wasm: Added.
* wasm/modules/wasm-wasm-cycle/entry.wat: Added.
* wasm/modules/wasm-wasm-cycle/sum.wasm: Added.
* wasm/modules/wasm-wasm-cycle/sum.wat: Added.

Source/JavaScriptCore:

With CatchScope check.

* JavaScriptCore.xcodeproj/project.pbxproj:
* builtins/ModuleLoaderPrototype.js:
(globalPrivate.newRegistryEntry):
(requestInstantiate):
(link):
* jsc.cpp:
(convertShebangToJSComment):
(fillBufferWithContentsOfFile):
(fetchModuleFromLocalFileSystem):
(GlobalObject::moduleLoaderFetch):
(functionDollarAgentStart):
(checkException):
(runWithOptions):
* parser/NodesAnalyzeModule.cpp:
(JSC::ImportDeclarationNode::analyzeModule):
* parser/SourceProvider.h:
(JSC::WebAssemblySourceProvider::create):
(JSC::WebAssemblySourceProvider::WebAssemblySourceProvider):
* runtime/AbstractModuleRecord.cpp:
(JSC::AbstractModuleRecord::hostResolveImportedModule):
(JSC::AbstractModuleRecord::resolveImport):
(JSC::AbstractModuleRecord::link):
(JSC::AbstractModuleRecord::evaluate):
(JSC::identifierToJSValue): Deleted.
* runtime/AbstractModuleRecord.h:
(JSC::AbstractModuleRecord::moduleEnvironmentMayBeNull):
(JSC::AbstractModuleRecord::ImportEntry::isNamespace const): Deleted.
* runtime/JSModuleEnvironment.cpp:
(JSC::JSModuleEnvironment::getOwnNonIndexPropertyNames):
* 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/WasmCreationMode.h: Copied from Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.h.
* 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:

Tools:

* Scripts/run-jsc-stress-tests:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@230759 268f45cc-cd09-0410-ab3c-d52691b4dbfc

82 files changed:
JSTests/ChangeLog
JSTests/wasm.yaml
JSTests/wasm/modules/constant.wasm [new file with mode: 0644]
JSTests/wasm/modules/constant.wat [new file with mode: 0644]
JSTests/wasm/modules/default-import-star-error.js [new file with mode: 0644]
JSTests/wasm/modules/default-import-star-error/entry.wasm [new file with mode: 0644]
JSTests/wasm/modules/default-import-star-error/entry.wat [new file with mode: 0644]
JSTests/wasm/modules/default-import-star-error/t0.js [new file with mode: 0644]
JSTests/wasm/modules/default-import-star-error/t1.js [new file with mode: 0644]
JSTests/wasm/modules/default-import-star-error/t2.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-cycle.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-cycle/entry.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-cycle/sum.wasm [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-cycle/sum.wat [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-function-namespace.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-function.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-global-namespace.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-global.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-memory-namespace.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-memory.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-start.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-table-namespace.js [new file with mode: 0644]
JSTests/wasm/modules/js-wasm-table.js [new file with mode: 0644]
JSTests/wasm/modules/memory.wasm [new file with mode: 0644]
JSTests/wasm/modules/memory.wat [new file with mode: 0644]
JSTests/wasm/modules/run-from-wasm.wasm [new file with mode: 0644]
JSTests/wasm/modules/run-from-wasm.wat [new file with mode: 0644]
JSTests/wasm/modules/run-from-wasm/check.js [new file with mode: 0644]
JSTests/wasm/modules/start.wasm [new file with mode: 0644]
JSTests/wasm/modules/start.wat [new file with mode: 0644]
JSTests/wasm/modules/sum.wasm [new file with mode: 0644]
JSTests/wasm/modules/sum.wat [new file with mode: 0644]
JSTests/wasm/modules/table.wasm [new file with mode: 0644]
JSTests/wasm/modules/table.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-exports.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-exports/imports.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-exports/imports.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-exports/sum.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-js-cycle.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-js-cycle/entry.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-js-cycle/entry.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-js-cycle/sum.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-wasm-cycle.js [new file with mode: 0644]
JSTests/wasm/modules/wasm-wasm-cycle/entry.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-wasm-cycle/entry.wat [new file with mode: 0644]
JSTests/wasm/modules/wasm-wasm-cycle/sum.wasm [new file with mode: 0644]
JSTests/wasm/modules/wasm-wasm-cycle/sum.wat [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/parser/NodesAnalyzeModule.cpp
Source/JavaScriptCore/parser/SourceProvider.h
Source/JavaScriptCore/runtime/AbstractModuleRecord.cpp
Source/JavaScriptCore/runtime/AbstractModuleRecord.h
Source/JavaScriptCore/runtime/JSModuleEnvironment.cpp
Source/JavaScriptCore/runtime/JSModuleLoader.cpp
Source/JavaScriptCore/runtime/JSModuleRecord.cpp
Source/JavaScriptCore/runtime/JSModuleRecord.h
Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp
Source/JavaScriptCore/wasm/WasmCreationMode.h [new file with mode: 0644]
Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h
Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.h
Tools/ChangeLog
Tools/Scripts/run-jsc-stress-tests

index 49e79fb..4997909 100644 (file)
@@ -1,3 +1,81 @@
+2018-04-18  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Unreviewed, reland r230697, r230720, and r230724.
+        https://bugs.webkit.org/show_bug.cgi?id=184600
+
+        * wasm.yaml:
+        * wasm/modules/constant.wasm: Added.
+        * wasm/modules/constant.wat: Added.
+        * wasm/modules/default-import-star-error.js: Added.
+        (then):
+        * wasm/modules/default-import-star-error/entry.wasm: Added.
+        * wasm/modules/default-import-star-error/entry.wat: Added.
+        * wasm/modules/default-import-star-error/t0.js: Added.
+        * wasm/modules/default-import-star-error/t1.js: Added.
+        * wasm/modules/default-import-star-error/t2.js: Added.
+        (export.default.Cocoa):
+        * wasm/modules/js-wasm-cycle.js: Added.
+        * wasm/modules/js-wasm-cycle/entry.js: Added.
+        (from.string_appeared_here.export.return42):
+        * wasm/modules/js-wasm-cycle/sum.wasm: Added.
+        * wasm/modules/js-wasm-cycle/sum.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/run-from-wasm.wasm: Added.
+        * wasm/modules/run-from-wasm.wat: Added.
+        * wasm/modules/run-from-wasm/check.js: Added.
+        (export.check):
+        * 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.
+        * wasm/modules/wasm-imports-js-exports.js: Added.
+        * wasm/modules/wasm-imports-js-exports/imports.wasm: Added.
+        * wasm/modules/wasm-imports-js-exports/imports.wat: Added.
+        * wasm/modules/wasm-imports-js-exports/sum.js: Added.
+        (export.sum):
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports.js: Added.
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm: Added.
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat: Added.
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js: Added.
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm: Added.
+        * wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat: Added.
+        * wasm/modules/wasm-imports-wasm-exports.js: Added.
+        * wasm/modules/wasm-imports-wasm-exports/imports.wasm: Added.
+        * wasm/modules/wasm-imports-wasm-exports/imports.wat: Added.
+        * wasm/modules/wasm-imports-wasm-exports/sum.wasm: Added.
+        * wasm/modules/wasm-imports-wasm-exports/sum.wat: Added.
+        * wasm/modules/wasm-js-cycle.js: Added.
+        * wasm/modules/wasm-js-cycle/entry.wasm: Added.
+        * wasm/modules/wasm-js-cycle/entry.wat: Added.
+        * wasm/modules/wasm-js-cycle/sum.js: Added.
+        (from.string_appeared_here.export.sum):
+        * wasm/modules/wasm-wasm-cycle.js: Added.
+        * wasm/modules/wasm-wasm-cycle/entry.wasm: Added.
+        * wasm/modules/wasm-wasm-cycle/entry.wat: Added.
+        * wasm/modules/wasm-wasm-cycle/sum.wasm: Added.
+        * wasm/modules/wasm-wasm-cycle/sum.wat: Added.
+
 2018-04-17  Commit Queue  <commit-queue@webkit.org>
 
         Unreviewed, rolling out r230697, r230720, and r230724.
index f2124ef..02c5cb2 100644 (file)
 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 - path: wasm/self-test/
-  cmd: runWebAssembly unless parseRunCommands
+  cmd: runWebAssemblySuite unless parseRunCommands
 - path: wasm/js-api/
-  cmd: runWebAssembly unless parseRunCommands
+  cmd: runWebAssemblySuite unless parseRunCommands
 - path: wasm/noJIT/
   cmd: runNoJIT unless parseRunCommands
 - path: wasm/function-tests
-  cmd: runWebAssembly unless parseRunCommands
+  cmd: runWebAssemblySuite unless parseRunCommands
 - path: wasm/fuzz
-  cmd: runWebAssembly unless parseRunCommands
+  cmd: runWebAssemblySuite unless parseRunCommands
 - path: wasm/stress
-  cmd: runWebAssembly unless parseRunCommands
+  cmd: runWebAssemblySuite unless parseRunCommands
 - path: wasm/lowExecutableMemory
   cmd: runWebAssemblyLowExecutableMemory unless parseRunCommands
 - path: wasm/regress/
-  cmd: runWebAssembly unless parseRunCommands
+  cmd: runWebAssemblySuite unless parseRunCommands
+- path: wasm/modules/
+  cmd: runWebAssemblySuite unless parseRunCommands
 
 - path: wasm/spec-tests/address.wast.js
   cmd: runWebAssemblySpecTest :normal
   cmd: runWebAssemblySpecTest :normal
 - path: wasm/spec-tests/utf8-import-module.wast.js
   cmd: runWebAssemblySpecTest :normal
+
+- path: wasm/modules/run-from-wasm.wasm
+  cmd: runWebAssembly
diff --git a/JSTests/wasm/modules/constant.wasm b/JSTests/wasm/modules/constant.wasm
new file mode 100644 (file)
index 0000000..106abdf
Binary files /dev/null and b/JSTests/wasm/modules/constant.wasm differ
diff --git a/JSTests/wasm/modules/constant.wat b/JSTests/wasm/modules/constant.wat
new file mode 100644 (file)
index 0000000..d639245
--- /dev/null
@@ -0,0 +1,2 @@
+(module
+    (global $constant (export "constant") i32 i32.const 42))
diff --git a/JSTests/wasm/modules/default-import-star-error.js b/JSTests/wasm/modules/default-import-star-error.js
new file mode 100644 (file)
index 0000000..f6c6461
--- /dev/null
@@ -0,0 +1,4 @@
+import * as assert from '../assert.js';
+import("./default-import-star-error/entry.wasm").then($vm.abort, function (error) {
+    assert.eq(String(error), `SyntaxError: Importing binding name 'default' cannot be resolved by star export entries.`);
+}).then(function () { }, $vm.abort);
diff --git a/JSTests/wasm/modules/default-import-star-error/entry.wasm b/JSTests/wasm/modules/default-import-star-error/entry.wasm
new file mode 100644 (file)
index 0000000..08cf69f
Binary files /dev/null and b/JSTests/wasm/modules/default-import-star-error/entry.wasm differ
diff --git a/JSTests/wasm/modules/default-import-star-error/entry.wat b/JSTests/wasm/modules/default-import-star-error/entry.wat
new file mode 100644 (file)
index 0000000..407fe7f
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./t1.js" "default" (func $log))
+    (type $t0 (func))
+    (func $main (type $t0)
+    )
+    (start $main)
+)
diff --git a/JSTests/wasm/modules/default-import-star-error/t0.js b/JSTests/wasm/modules/default-import-star-error/t0.js
new file mode 100644 (file)
index 0000000..5cd8030
--- /dev/null
@@ -0,0 +1 @@
+import A from "./t1.js"
diff --git a/JSTests/wasm/modules/default-import-star-error/t1.js b/JSTests/wasm/modules/default-import-star-error/t1.js
new file mode 100644 (file)
index 0000000..1c91124
--- /dev/null
@@ -0,0 +1 @@
+export * from "./t2.js"
diff --git a/JSTests/wasm/modules/default-import-star-error/t2.js b/JSTests/wasm/modules/default-import-star-error/t2.js
new file mode 100644 (file)
index 0000000..e01f0a0
--- /dev/null
@@ -0,0 +1 @@
+export default function Cocoa() { }
diff --git a/JSTests/wasm/modules/js-wasm-cycle.js b/JSTests/wasm/modules/js-wasm-cycle.js
new file mode 100644 (file)
index 0000000..94f0f86
--- /dev/null
@@ -0,0 +1,4 @@
+import * as assert from '../assert.js';
+import("./js-wasm-cycle/entry.js").then($vm.abort, function (error) {
+    assert.eq(String(error), `Error: import function ./entry.js:return42 must be callable`);
+}).then(function () { }, $vm.abort);
diff --git a/JSTests/wasm/modules/js-wasm-cycle/entry.js b/JSTests/wasm/modules/js-wasm-cycle/entry.js
new file mode 100644 (file)
index 0000000..2014364
--- /dev/null
@@ -0,0 +1,4 @@
+import { sum } from "./sum.wasm"
+export function return42() {
+    return 42;
+}
diff --git a/JSTests/wasm/modules/js-wasm-cycle/sum.wasm b/JSTests/wasm/modules/js-wasm-cycle/sum.wasm
new file mode 100644 (file)
index 0000000..f8c16e5
Binary files /dev/null and b/JSTests/wasm/modules/js-wasm-cycle/sum.wasm differ
diff --git a/JSTests/wasm/modules/js-wasm-cycle/sum.wat b/JSTests/wasm/modules/js-wasm-cycle/sum.wat
new file mode 100644 (file)
index 0000000..3e223f7
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./entry.js" "return42" (func $return42 (result i32)))
+    (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))
diff --git a/JSTests/wasm/modules/js-wasm-function-namespace.js b/JSTests/wasm/modules/js-wasm-function-namespace.js
new file mode 100644 (file)
index 0000000..054db03
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/js-wasm-function.js b/JSTests/wasm/modules/js-wasm-function.js
new file mode 100644 (file)
index 0000000..0be5b81
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/js-wasm-global-namespace.js b/JSTests/wasm/modules/js-wasm-global-namespace.js
new file mode 100644 (file)
index 0000000..52a4dfa
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/js-wasm-global.js b/JSTests/wasm/modules/js-wasm-global.js
new file mode 100644 (file)
index 0000000..5ae7929
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/js-wasm-memory-namespace.js b/JSTests/wasm/modules/js-wasm-memory-namespace.js
new file mode 100644 (file)
index 0000000..bd32e3a
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/js-wasm-memory.js b/JSTests/wasm/modules/js-wasm-memory.js
new file mode 100644 (file)
index 0000000..ed5eccf
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/js-wasm-start.js b/JSTests/wasm/modules/js-wasm-start.js
new file mode 100644 (file)
index 0000000..c2274c0
--- /dev/null
@@ -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);
diff --git a/JSTests/wasm/modules/js-wasm-table-namespace.js b/JSTests/wasm/modules/js-wasm-table-namespace.js
new file mode 100644 (file)
index 0000000..a9cc3ba
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/js-wasm-table.js b/JSTests/wasm/modules/js-wasm-table.js
new file mode 100644 (file)
index 0000000..a27f51c
--- /dev/null
@@ -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.`);
diff --git a/JSTests/wasm/modules/memory.wasm b/JSTests/wasm/modules/memory.wasm
new file mode 100644 (file)
index 0000000..fb69610
Binary files /dev/null and b/JSTests/wasm/modules/memory.wasm differ
diff --git a/JSTests/wasm/modules/memory.wat b/JSTests/wasm/modules/memory.wat
new file mode 100644 (file)
index 0000000..27a3b11
--- /dev/null
@@ -0,0 +1,3 @@
+(module
+    (memory $memory (export "memory") 17)
+    (data (i32.const 4) "\10\00\10\00"))
diff --git a/JSTests/wasm/modules/run-from-wasm.wasm b/JSTests/wasm/modules/run-from-wasm.wasm
new file mode 100644 (file)
index 0000000..87345e6
Binary files /dev/null and b/JSTests/wasm/modules/run-from-wasm.wasm differ
diff --git a/JSTests/wasm/modules/run-from-wasm.wat b/JSTests/wasm/modules/run-from-wasm.wat
new file mode 100644 (file)
index 0000000..4e51e50
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./run-from-wasm/check.js" "check" (func $check (param i32)))
+    (type $t0 (func))
+    (func $main (type $t0)
+        i32.const 42
+        call $check)
+    (start $main))
diff --git a/JSTests/wasm/modules/run-from-wasm/check.js b/JSTests/wasm/modules/run-from-wasm/check.js
new file mode 100644 (file)
index 0000000..51a3535
--- /dev/null
@@ -0,0 +1,6 @@
+import * as assert from '../../assert.js';
+
+export function check(value)
+{
+    assert.eq(value, 42);
+}
diff --git a/JSTests/wasm/modules/start.wasm b/JSTests/wasm/modules/start.wasm
new file mode 100644 (file)
index 0000000..771660f
Binary files /dev/null and b/JSTests/wasm/modules/start.wasm differ
diff --git a/JSTests/wasm/modules/start.wat b/JSTests/wasm/modules/start.wat
new file mode 100644 (file)
index 0000000..7744e42
--- /dev/null
@@ -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))
diff --git a/JSTests/wasm/modules/sum.wasm b/JSTests/wasm/modules/sum.wasm
new file mode 100644 (file)
index 0000000..4c722a7
Binary files /dev/null and b/JSTests/wasm/modules/sum.wasm differ
diff --git a/JSTests/wasm/modules/sum.wat b/JSTests/wasm/modules/sum.wat
new file mode 100644 (file)
index 0000000..ba3f2a3
--- /dev/null
@@ -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))
diff --git a/JSTests/wasm/modules/table.wasm b/JSTests/wasm/modules/table.wasm
new file mode 100644 (file)
index 0000000..7408c46
Binary files /dev/null and b/JSTests/wasm/modules/table.wasm differ
diff --git a/JSTests/wasm/modules/table.wat b/JSTests/wasm/modules/table.wat
new file mode 100644 (file)
index 0000000..6a6b699
--- /dev/null
@@ -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))
diff --git a/JSTests/wasm/modules/wasm-imports-js-exports.js b/JSTests/wasm/modules/wasm-imports-js-exports.js
new file mode 100644 (file)
index 0000000..709d0bc
--- /dev/null
@@ -0,0 +1,7 @@
+import { addOne } from "./wasm-imports-js-exports/imports.wasm"
+import * as assert from '../assert.js';
+
+assert.isFunction(addOne);
+assert.eq(addOne(32), 33);
+assert.eq(addOne(-2), -1);
+assert.eq(addOne(0x7fffffff), -2147483648);
diff --git a/JSTests/wasm/modules/wasm-imports-js-exports/imports.wasm b/JSTests/wasm/modules/wasm-imports-js-exports/imports.wasm
new file mode 100644 (file)
index 0000000..55d87e6
Binary files /dev/null and b/JSTests/wasm/modules/wasm-imports-js-exports/imports.wasm differ
diff --git a/JSTests/wasm/modules/wasm-imports-js-exports/imports.wat b/JSTests/wasm/modules/wasm-imports-js-exports/imports.wat
new file mode 100644 (file)
index 0000000..75112e0
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./sum.js" "sum" (func $sum (param i32 i32) (result i32)))
+    (type $t0 (func (param i32) (result i32)))
+    (func $addOne (export "addOne") (type $t0) (param $p0 i32) (result i32)
+        i32.const 1
+        get_local $p0
+        call $sum))
diff --git a/JSTests/wasm/modules/wasm-imports-js-exports/sum.js b/JSTests/wasm/modules/wasm-imports-js-exports/sum.js
new file mode 100644 (file)
index 0000000..ad83b67
--- /dev/null
@@ -0,0 +1,4 @@
+export function sum(arg0, arg1)
+{
+    return arg0 + arg1;
+}
diff --git a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports.js b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports.js
new file mode 100644 (file)
index 0000000..939c234
--- /dev/null
@@ -0,0 +1,7 @@
+import { addOne } from "./wasm-imports-js-re-exports-wasm-exports/imports.wasm"
+import * as assert from '../assert.js';
+
+assert.isFunction(addOne);
+assert.eq(addOne(32), 33);
+assert.eq(addOne(-2), -1);
+assert.eq(addOne(0x7fffffff), -2147483648);
diff --git a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm
new file mode 100644 (file)
index 0000000..35b6522
Binary files /dev/null and b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wasm differ
diff --git a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/imports.wat
new file mode 100644 (file)
index 0000000..54e967d
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./re-export.js" "sum" (func $sum (param i32 i32) (result i32)))
+    (type $t0 (func (param i32) (result i32)))
+    (func $addOne (export "addOne") (type $t0) (param $p0 i32) (result i32)
+        i32.const 1
+        get_local $p0
+        call $sum))
diff --git a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/re-export.js
new file mode 100644 (file)
index 0000000..e16ba1c
--- /dev/null
@@ -0,0 +1 @@
+export { sum } from "./sum.wasm"
diff --git a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm
new file mode 100644 (file)
index 0000000..4c722a7
Binary files /dev/null and b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wasm differ
diff --git a/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat b/JSTests/wasm/modules/wasm-imports-js-re-exports-wasm-exports/sum.wat
new file mode 100644 (file)
index 0000000..ba3f2a3
--- /dev/null
@@ -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))
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports.js b/JSTests/wasm/modules/wasm-imports-wasm-exports.js
new file mode 100644 (file)
index 0000000..709d0bc
--- /dev/null
@@ -0,0 +1,7 @@
+import { addOne } from "./wasm-imports-js-exports/imports.wasm"
+import * as assert from '../assert.js';
+
+assert.isFunction(addOne);
+assert.eq(addOne(32), 33);
+assert.eq(addOne(-2), -1);
+assert.eq(addOne(0x7fffffff), -2147483648);
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wasm b/JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wasm
new file mode 100644 (file)
index 0000000..0fe79e3
Binary files /dev/null and b/JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wasm differ
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wat b/JSTests/wasm/modules/wasm-imports-wasm-exports/imports.wat
new file mode 100644 (file)
index 0000000..a6029e7
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./sum.wasm" "sum" (func $sum (param i32 i32) (result i32)))
+    (type $t0 (func (param i32) (result i32)))
+    (func $addOne (export "addOne") (type $t0) (param $p0 i32) (result i32)
+        i32.const 1
+        get_local $p0
+        call $sum))
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wasm b/JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wasm
new file mode 100644 (file)
index 0000000..4c722a7
Binary files /dev/null and b/JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wasm differ
diff --git a/JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wat b/JSTests/wasm/modules/wasm-imports-wasm-exports/sum.wat
new file mode 100644 (file)
index 0000000..ba3f2a3
--- /dev/null
@@ -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))
diff --git a/JSTests/wasm/modules/wasm-js-cycle.js b/JSTests/wasm/modules/wasm-js-cycle.js
new file mode 100644 (file)
index 0000000..3ccdbd3
--- /dev/null
@@ -0,0 +1,4 @@
+import * as assert from '../assert.js'
+import { return42 } from "./wasm-js-cycle/entry.wasm"
+
+assert.eq(return42(), 42);
diff --git a/JSTests/wasm/modules/wasm-js-cycle/entry.wasm b/JSTests/wasm/modules/wasm-js-cycle/entry.wasm
new file mode 100644 (file)
index 0000000..0649bd5
Binary files /dev/null and b/JSTests/wasm/modules/wasm-js-cycle/entry.wasm differ
diff --git a/JSTests/wasm/modules/wasm-js-cycle/entry.wat b/JSTests/wasm/modules/wasm-js-cycle/entry.wat
new file mode 100644 (file)
index 0000000..99cc11c
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./sum.js" "sum" (func $sum (param i32) (param i32) (result i32)))
+    (type $t0 (func (result i32)))
+    (func $return42 (export "return42") (type $t0) (result i32)
+        i32.const 1
+        i32.const 41
+        call $sum))
diff --git a/JSTests/wasm/modules/wasm-js-cycle/sum.js b/JSTests/wasm/modules/wasm-js-cycle/sum.js
new file mode 100644 (file)
index 0000000..23f7537
--- /dev/null
@@ -0,0 +1,4 @@
+import { return42 } from "./entry.wasm"
+export function sum(a, b) {
+    return a + b;
+}
diff --git a/JSTests/wasm/modules/wasm-wasm-cycle.js b/JSTests/wasm/modules/wasm-wasm-cycle.js
new file mode 100644 (file)
index 0000000..b1a504e
--- /dev/null
@@ -0,0 +1,4 @@
+import * as assert from '../assert.js';
+import("./wasm-wasm-cycle/entry.wasm").then($vm.abort, function (error) {
+    assert.eq(String(error), `Error: import function ./entry.wasm:return42 must be callable`);
+}).then(function () { }, $vm.abort);
diff --git a/JSTests/wasm/modules/wasm-wasm-cycle/entry.wasm b/JSTests/wasm/modules/wasm-wasm-cycle/entry.wasm
new file mode 100644 (file)
index 0000000..3df7c92
Binary files /dev/null and b/JSTests/wasm/modules/wasm-wasm-cycle/entry.wasm differ
diff --git a/JSTests/wasm/modules/wasm-wasm-cycle/entry.wat b/JSTests/wasm/modules/wasm-wasm-cycle/entry.wat
new file mode 100644 (file)
index 0000000..812b037
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./sum.wasm" "sum" (func $sum (param i32) (param i32) (result i32)))
+    (type $t0 (func (result i32)))
+    (func $return42 (export "return42") (type $t0) (result i32)
+        i32.const 1
+        i32.const 41
+        call $sum))
diff --git a/JSTests/wasm/modules/wasm-wasm-cycle/sum.wasm b/JSTests/wasm/modules/wasm-wasm-cycle/sum.wasm
new file mode 100644 (file)
index 0000000..9dee051
Binary files /dev/null and b/JSTests/wasm/modules/wasm-wasm-cycle/sum.wasm differ
diff --git a/JSTests/wasm/modules/wasm-wasm-cycle/sum.wat b/JSTests/wasm/modules/wasm-wasm-cycle/sum.wat
new file mode 100644 (file)
index 0000000..91d8da9
--- /dev/null
@@ -0,0 +1,7 @@
+(module
+    (import "./entry.wasm" "return42" (func $return42 (result i32)))
+    (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))
index e3e00ed..f90718c 100644 (file)
@@ -1,3 +1,73 @@
+2018-04-18  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Unreviewed, reland r230697, r230720, and r230724.
+        https://bugs.webkit.org/show_bug.cgi?id=184600
+
+        With CatchScope check.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * builtins/ModuleLoaderPrototype.js:
+        (globalPrivate.newRegistryEntry):
+        (requestInstantiate):
+        (link):
+        * jsc.cpp:
+        (convertShebangToJSComment):
+        (fillBufferWithContentsOfFile):
+        (fetchModuleFromLocalFileSystem):
+        (GlobalObject::moduleLoaderFetch):
+        (functionDollarAgentStart):
+        (checkException):
+        (runWithOptions):
+        * parser/NodesAnalyzeModule.cpp:
+        (JSC::ImportDeclarationNode::analyzeModule):
+        * parser/SourceProvider.h:
+        (JSC::WebAssemblySourceProvider::create):
+        (JSC::WebAssemblySourceProvider::WebAssemblySourceProvider):
+        * runtime/AbstractModuleRecord.cpp:
+        (JSC::AbstractModuleRecord::hostResolveImportedModule):
+        (JSC::AbstractModuleRecord::resolveImport):
+        (JSC::AbstractModuleRecord::link):
+        (JSC::AbstractModuleRecord::evaluate):
+        (JSC::identifierToJSValue): Deleted.
+        * runtime/AbstractModuleRecord.h:
+        (JSC::AbstractModuleRecord::moduleEnvironmentMayBeNull):
+        (JSC::AbstractModuleRecord::ImportEntry::isNamespace const): Deleted.
+        * runtime/JSModuleEnvironment.cpp:
+        (JSC::JSModuleEnvironment::getOwnNonIndexPropertyNames):
+        * 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/WasmCreationMode.h: Copied from Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.h.
+        * 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-17  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GLIB] Make it possible to handle JSCClass external properties not added to the prototype
index 02a6d7d..be593e2 100644 (file)
                E35CA1541DBC3A5C00F83516 /* DOMJITHeapRange.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1521DBC3A5600F83516 /* DOMJITHeapRange.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35CA1561DBC3A5F00F83516 /* DOMJITAbstractHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = E35CA1501DBC3A5600F83516 /* DOMJITAbstractHeap.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35E03601B7AB43E0073AD2A /* InspectorInstrumentationObject.h in Headers */ = {isa = PBXBuildFile; fileRef = E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               E36CC9472086314F0051FFD6 /* WasmCreationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = E36CC9462086314F0051FFD6 /* WasmCreationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E3794E761B77EB97005543AE /* ModuleAnalyzer.h in Headers */ = {isa = PBXBuildFile; fileRef = E3794E741B77EB97005543AE /* ModuleAnalyzer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E393ADD81FE702D00022D681 /* WeakMapImplInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E393ADD71FE702CC0022D681 /* WeakMapImplInlines.h */; };
                E39D45F51D39005600B3B377 /* InterpreterInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = E39D9D841D39000600667282 /* InterpreterInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E35E035D1B7AB43E0073AD2A /* InspectorInstrumentationObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorInstrumentationObject.cpp; sourceTree = "<group>"; };
                E35E035E1B7AB43E0073AD2A /* InspectorInstrumentationObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorInstrumentationObject.h; sourceTree = "<group>"; };
                E35E03611B7AB4850073AD2A /* InspectorInstrumentationObject.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = InspectorInstrumentationObject.js; sourceTree = "<group>"; };
+               E36CC9462086314F0051FFD6 /* WasmCreationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCreationMode.h; sourceTree = "<group>"; };
                E3794E731B77EB97005543AE /* ModuleAnalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModuleAnalyzer.cpp; sourceTree = "<group>"; };
                E3794E741B77EB97005543AE /* ModuleAnalyzer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModuleAnalyzer.h; sourceTree = "<group>"; };
                E380A76B1DCD7195000F89E6 /* MacroAssemblerHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerHelpers.h; sourceTree = "<group>"; };
                                526AC4B51E977C5D003500E1 /* WasmCodeBlock.h */,
                                AD412B311E7B2E8A008AF157 /* WasmContext.cpp */,
                                AD412B321E7B2E8A008AF157 /* WasmContext.h */,
+                               E36CC9462086314F0051FFD6 /* WasmCreationMode.h */,
                                AD5C36DC1F688B5F000BCAAF /* WasmEmbedder.h */,
                                79DAE2791E03C82200B526AA /* WasmExceptionType.h */,
                                5381B9361E60E9660090F794 /* WasmFaultSignalHandler.cpp */,
                                0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */,
                                E322E5A71DA644A8006E7709 /* FTLSnippetParams.h in Headers */,
                                0F235BD717178E1C00690C7F /* FTLStackmapArgumentList.h in Headers */,
-                               FE476FF4207E85D50093CA2D /* JITCodeMap.h in Headers */,
                                0FEA0A12170513DB00BB722C /* FTLState.h in Headers */,
                                A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */,
                                0F235BE217178E1C00690C7F /* FTLThunks.h in Headers */,
                                FE3A06A61C10B72D00390FDD /* JITBitOrGenerator.h in Headers */,
                                FE3A06B41C10CB9300390FDD /* JITBitXorGenerator.h in Headers */,
                                86CCEFDE0F413F8900FD7F9E /* JITCode.h in Headers */,
+                               FE476FF4207E85D50093CA2D /* JITCodeMap.h in Headers */,
                                0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */,
                                0FAF7EFE165BA91F000C8455 /* JITDisassembler.h in Headers */,
                                FE187A0D1C030D5C0038BBCA /* JITDivGenerator.h in Headers */,
                                53FD04D41D7AB291003287D3 /* WasmCallingConvention.h in Headers */,
                                526AC4B71E977C5D003500E1 /* WasmCodeBlock.h in Headers */,
                                AD412B341E7B2E9E008AF157 /* WasmContext.h in Headers */,
+                               E36CC9472086314F0051FFD6 /* WasmCreationMode.h in Headers */,
                                AD5C36DD1F688B65000BCAAF /* WasmEmbedder.h in Headers */,
                                79DAE27A1E03C82200B526AA /* WasmExceptionType.h in Headers */,
                                5381B9391E60E97D0090F794 /* WasmFaultSignalHandler.h in Headers */,
index 93f2225..eef91eb 100644 (file)
@@ -95,7 +95,6 @@ function newRegistryEntry(key)
         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 @@ function requestInstantiate(entry, parameters, fetcher)
         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 @@ function link(entry, fetcher)
         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;
index 40c7edc..744de30 100644 (file)
@@ -186,7 +186,8 @@ static unsigned asyncTestExpectedPasses { 0 };
 
 }
 
-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;
@@ -195,7 +196,7 @@ class Workers;
 
 template<typename Func>
 int runJSC(CommandLine, bool isWorker, const Func&);
-static void checkException(GlobalObject*, bool isLastFile, bool hasException, JSValue, CommandLine&, bool& success);
+static void checkException(ExecState*, GlobalObject*, bool isLastFile, bool hasException, JSValue, CommandLine&, bool& success);
 
 class Message : public ThreadSafeRefCounted<Message> {
 public:
@@ -844,7 +845,8 @@ Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecS
     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 @@ static RefPtr<Uint8Array> fillBufferWithContentsOfFile(const String& fileName)
     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 @@ static bool fetchScriptFromLocalFileSystem(const String& fileName, Vector<char>&
     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 @@ JSInternalPromise* GlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject,
     }
 
     // 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;
 }
@@ -1617,7 +1632,7 @@ EncodedJSValue JSC_HOST_CALL functionDollarAgentStart(ExecState* exec)
                     result = evaluate(globalObject->globalExec(), makeSource(sourceCode, SourceOrigin(ASCIILiteral("worker"))), JSValue(), evaluationException);
                     if (evaluationException)
                         result = evaluationException->value();
-                    checkException(globalObject, true, evaluationException, result, commandLine, success);
+                    checkException(globalObject->globalExec(), globalObject, true, evaluationException, result, commandLine, success);
                     if (!success)
                         exit(1);
                     return success;
@@ -2244,7 +2259,7 @@ static bool checkUncaughtException(VM& vm, GlobalObject* globalObject, JSValue e
     return false;
 }
 
-static void checkException(GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, CommandLine& options, bool& success)
+static void checkException(ExecState* exec, GlobalObject* globalObject, bool isLastFile, bool hasException, JSValue value, CommandLine& options, bool& success)
 {
     VM& vm = globalObject->vm();
 
@@ -2256,7 +2271,7 @@ static void checkException(GlobalObject* globalObject, bool isLastFile, bool has
     if (!options.m_uncaughtExceptionName || !isLastFile) {
         success = success && !hasException;
         if (options.m_dump && !hasException)
-            printf("End: %s\n", value.toWTFString(globalObject->globalExec()).utf8().data());
+            printf("End: %s\n", value.toWTFString(exec).utf8().data());
         if (hasException)
             dumpException(globalObject, value);
     } else
@@ -2309,12 +2324,12 @@ static bool runWithOptions(GlobalObject* globalObject, CommandLine& options)
             scope.clearException();
 
             JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
-                checkException(globalObject, isLastFile, false, exec->argument(0), options, success);
+                checkException(exec, globalObject, isLastFile, false, exec->argument(0), options, success);
                 return JSValue::encode(jsUndefined());
             });
 
             JSFunction* rejectHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&, isLastFile](ExecState* exec) {
-                checkException(globalObject, isLastFile, true, exec->argument(0), options, success);
+                checkException(exec, globalObject, isLastFile, true, exec->argument(0), options, success);
                 return JSValue::encode(jsUndefined());
             });
 
@@ -2327,7 +2342,7 @@ static bool runWithOptions(GlobalObject* globalObject, CommandLine& options)
             scope.assertNoException();
             if (evaluationException)
                 returnValue = evaluationException->value();
-            checkException(globalObject, isLastFile, evaluationException, returnValue, options, success);
+            checkException(globalObject->globalExec(), globalObject, isLastFile, evaluationException, returnValue, options, success);
         }
 
         scriptBuffer.clear();
index 426e53b..6d9960f 100644 (file)
@@ -52,9 +52,11 @@ void ImportDeclarationNode::analyzeModule(ModuleAnalyzer& analyzer)
     analyzer.moduleRecord()->appendRequestedModule(m_moduleName->moduleName());
     for (auto* specifier : m_specifierList->specifiers()) {
         analyzer.moduleRecord()->addImportEntry(JSModuleRecord::ImportEntry {
+            specifier->importedName() == analyzer.vm().propertyNames->timesIdentifier
+                ? JSModuleRecord::ImportEntryType::Namespace : JSModuleRecord::ImportEntryType::Single,
             m_moduleName->moduleName(),
             specifier->importedName(),
-            specifier->localName()
+            specifier->localName(),
         });
     }
 }
index 2e68e82..0d0c2fc 100644 (file)
@@ -120,9 +120,9 @@ namespace JSC {
 #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 @@ namespace JSC {
         }
 
     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))
         {
         }
 
index 33253df..c06099f 100644 (file)
@@ -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 @@ auto AbstractModuleRecord::Resolution::ambiguous() -> Resolution
     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();
@@ -166,7 +160,7 @@ auto AbstractModuleRecord::resolveImport(ExecState* exec, const Identifier& loca
         return Resolution::notFound();
 
     const ImportEntry& importEntry = *optionalImportEntry;
-    if (importEntry.isNamespace(exec->vm()))
+    if (importEntry.type == AbstractModuleRecord::ImportEntryType::Namespace)
         return Resolution::notFound();
 
     AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
@@ -775,6 +769,31 @@ JSModuleNamespaceObject* AbstractModuleRecord::getModuleNamespace(ExecState* exe
     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, nullptr, Wasm::CreationMode::FromModuleLoader);
+#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())
index 592995b..5bb5b16 100644 (file)
@@ -61,15 +61,12 @@ public:
         Identifier localName;
     };
 
+    enum class ImportEntryType { Single, Namespace };
     struct ImportEntry {
+        ImportEntryType type;
         Identifier moduleRequest;
         Identifier importName;
         Identifier localName;
-
-        bool isNamespace(VM& vm) const
-        {
-            return importName == vm.propertyNames->timesIdentifier;
-        }
     };
 
     typedef WTF::ListHashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> OrderedIdentifierSet;
@@ -119,6 +116,14 @@ public:
         return m_moduleEnvironment.get();
     }
 
+    JSModuleEnvironment* moduleEnvironmentMayBeNull()
+    {
+        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&);
index c617314..a9eb84a 100644 (file)
@@ -103,10 +103,9 @@ void JSModuleEnvironment::getOwnNonIndexPropertyNames(JSObject* cell, ExecState*
 {
     JSModuleEnvironment* thisObject = jsCast<JSModuleEnvironment*>(cell);
     if (propertyNamesArray.includeStringProperties()) {
-        VM& vm = exec->vm();
         for (const auto& pair : thisObject->moduleRecord()->importEntries()) {
             const AbstractModuleRecord::ImportEntry& importEntry = pair.value;
-            if (!importEntry.isNamespace(vm))
+            if (importEntry.type == AbstractModuleRecord::ImportEntryType::Single)
                 propertyNamesArray.add(importEntry.localName);
         }
     }
index 1be3c7a..908591d 100644 (file)
@@ -275,10 +275,9 @@ JSValue JSModuleLoader::evaluate(ExecState* exec, JSValue key, JSValue moduleRec
     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)
index 6fa2f72..c55d0d1 100644 (file)
@@ -78,7 +78,7 @@ void JSModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
     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 @@ void JSModuleRecord::link(ExecState* exec, JSValue key, JSValue scriptFetcher)
         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);
@@ -141,7 +141,7 @@ void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecu
         const ImportEntry& importEntry = pair.value;
         AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
         RETURN_IF_EXCEPTION(scope, void());
-        if (importEntry.isNamespace(vm)) {
+        if (importEntry.type == AbstractModuleRecord::ImportEntryType::Namespace) {
             JSModuleNamespaceObject* namespaceObject = importedModule->getModuleNamespace(exec);
             RETURN_IF_EXCEPTION(scope, void());
             bool putResult = false;
@@ -208,7 +208,7 @@ void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecu
     }
 
     {
-        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);
index cdfcc40..ac2dcfa 100644 (file)
@@ -45,7 +45,7 @@ public:
     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 @@ private:
     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;
index 3d4f44a..b8bdc9f 100644 (file)
@@ -45,6 +45,7 @@
 #include "Nodes.h"
 #include "Parser.h"
 #include "ParserError.h"
+#include "WebAssemblyPrototype.h"
 
 namespace JSC {
 
@@ -76,7 +77,7 @@ const ClassInfo ModuleLoaderPrototype::s_info = { "ModuleLoader", &Base::s_info,
     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,41 +104,59 @@ ModuleLoaderPrototype::ModuleLoaderPrototype(VM& vm, Structure* structure)
 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();
+        auto result = deferred->reject(exec, exception);
+        scope.releaseAssertNoException();
+        return JSValue::encode(result);
+    };
 
     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;
     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());
+        auto result = deferred->reject(exec, error.toErrorObject(exec->lexicalGlobalObject(), sourceCode));
+        scope.releaseAssertNoException();
+        return JSValue::encode(result);
     }
     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);
+    auto result = deferred->resolve(exec, moduleAnalyzer.analyze(*moduleProgramNode));
+    scope.releaseAssertNoException();
+    return JSValue::encode(result);
 }
 
 EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeRequestedModules(ExecState* exec)
 {
     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,14 +176,14 @@ EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeModuleDeclarationInstantiation
 {
     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());
 
     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());
diff --git a/Source/JavaScriptCore/wasm/WasmCreationMode.h b/Source/JavaScriptCore/wasm/WasmCreationMode.h
new file mode 100644 (file)
index 0000000..12fe8cc
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBASSEMBLY)
+
+namespace JSC { namespace Wasm {
+
+enum class CreationMode {
+    FromJS,
+    FromModuleLoader
+};
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
index bd06d3c..c51286b 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "JSArrayBuffer.h"
 #include "JSCJSValue.h"
+#include "JSSourceCode.h"
 #include "WebAssemblyFunction.h"
 #include "WebAssemblyWrapperFunction.h"
 
@@ -49,10 +50,16 @@ ALWAYS_INLINE uint32_t toNonWrappingUint32(ExecState* exec, JSValue value)
     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 std::pair<uint8_t*, size_t> getWasmBufferFromValue(ExecState* exec
 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>());
index 771a640..9e58f74 100644 (file)
@@ -91,7 +91,7 @@ void JSWebAssemblyInstance::visitChildren(JSCell* cell, SlotVisitor& visitor)
         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, JSObject* importObject, Wasm::CreationMode creationMode)
 {
     m_instance->finalizeCreation(this, wasmCodeBlock.copyRef());
 
@@ -127,15 +127,24 @@ void JSWebAssemblyInstance::finalizeCreation(VM& vm, ExecState* exec, Ref<Wasm::
     }
 
     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 (creationMode == Wasm::CreationMode::FromJS) {
+        moduleRecord->link(exec, jsNull(), importObject, creationMode);
+        RETURN_IF_EXCEPTION(scope, void());
+
+        JSValue startResult = moduleRecord->evaluate(exec);
+        UNUSED_PARAM(startResult);
+        RETURN_IF_EXCEPTION(scope, void());
+    }
+}
+
+Identifier JSWebAssemblyInstance::createPrivateModuleKey()
+{
+    return Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyInstance"));
 }
 
-JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure, Ref<Wasm::Module>&& module)
+JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, const Identifier& moduleKey, JSWebAssemblyModule* jsModule, JSObject* importObject, Structure* instanceStructure, Ref<Wasm::Module>&& module, Wasm::CreationMode creationMode)
 {
     auto throwScope = DECLARE_THROW_SCOPE(vm);
     auto* globalObject = exec->lexicalGlobalObject();
@@ -154,11 +163,6 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JS
         return makeString(before, " ", String::fromUTF8(import.module), ":", String::fromUTF8(import.field), " ", after);
     };
 
-    // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown.
-    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);
 
@@ -176,69 +180,59 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JS
 
     // Let funcs, memories and tables be initially-empty lists of callable JavaScript objects, WebAssembly.Memory objects and WebAssembly.Table objects, respectively.
     // Let imports be an initially-empty list of external values.
-    unsigned numImportFunctions = 0;
     unsigned numImportGlobals = 0;
 
     bool hasMemoryImport = false;
     bool hasTableImport = false;
+
+    if (creationMode == Wasm::CreationMode::FromJS) {
+        // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown.
+        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")));
+    }
+
     // For each import i in module.imports:
     for (auto& import : moduleInformation.imports) {
-        // 1. Let o be the resultant value of performing Get(importObject, i.module_name).
-        JSValue importModuleValue = importObject->get(exec, Identifier::fromString(&vm, String::fromUTF8(import.module)));
-        RETURN_IF_EXCEPTION(throwScope, nullptr);
-        // 2. If Type(o) is not Object, throw a TypeError.
-        if (!importModuleValue.isObject())
-            return exception(createTypeError(exec, importFailMessage(import, "import", "must be an object"), defaultSourceAppender, runtimeTypeForValue(importModuleValue)));
+        Identifier moduleName = Identifier::fromString(&vm, String::fromUTF8(import.module));
+        Identifier fieldName = Identifier::fromString(&vm, String::fromUTF8(import.field));
+        moduleRecord->appendRequestedModule(moduleName);
+        moduleRecord->addImportEntry(WebAssemblyModuleRecord::ImportEntry {
+            WebAssemblyModuleRecord::ImportEntryType::Single,
+            moduleName,
+            fieldName,
+            Identifier::fromUid(PrivateName(PrivateName::Description, "WebAssemblyImportName")),
+        });
+
+        // Skip Wasm::ExternalKind::Function validation here. It will be done in WebAssemblyModuleRecord::link.
+        // Eventually we will move all the linking code here to WebAssemblyModuleRecord::link.
+        switch (import.kind) {
+        case Wasm::ExternalKind::Function:
+            continue;
+        case Wasm::ExternalKind::Table:
+        case Wasm::ExternalKind::Memory:
+        case Wasm::ExternalKind::Global:
+            break;
+        }
 
-        // 3. Let v be the value of performing Get(o, i.item_name)
-        JSObject* object = jsCast<JSObject*>(importModuleValue);
-        JSValue value = object->get(exec, Identifier::fromString(&vm, String::fromUTF8(import.field)));
-        RETURN_IF_EXCEPTION(throwScope, nullptr);
+        JSValue value;
+        if (creationMode == Wasm::CreationMode::FromJS) {
+            // 1. Let o be the resultant value of performing Get(importObject, i.module_name).
+            JSValue importModuleValue = importObject->get(exec, moduleName);
+            RETURN_IF_EXCEPTION(throwScope, nullptr);
+            // 2. If Type(o) is not Object, throw a TypeError.
+            if (!importModuleValue.isObject())
+                return exception(createTypeError(exec, importFailMessage(import, "import", "must be an object"), defaultSourceAppender, runtimeTypeForValue(importModuleValue)));
+
+            // 3. Let v be the value of performing Get(o, i.item_name)
+            JSObject* object = jsCast<JSObject*>(importModuleValue);
+            value = object->get(exec, fieldName);
+            RETURN_IF_EXCEPTION(throwScope, nullptr);
+        }
+        if (!value)
+            value = jsUndefined();
 
         switch (import.kind) {
         case Wasm::ExternalKind::Function: {
-            // 4. If i is a function import:
-            // i. If IsCallable(v) is false, throw a WebAssembly.LinkError.
-            if (!value.isFunction())
-                return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "import function", "must be callable")));
-
-            Wasm::Instance* calleeInstance = nullptr;
-            WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = nullptr;
-            JSObject* function = jsCast<JSObject*>(value);
-
-            // ii. If v is an Exported Function Exotic Object:
-            WebAssemblyFunction* wasmFunction;
-            WebAssemblyWrapperFunction* wasmWrapperFunction;
-            if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) {
-                // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
-                Wasm::SignatureIndex importedSignatureIndex;
-                if (wasmFunction) {
-                    importedSignatureIndex = wasmFunction->signatureIndex();
-                    calleeInstance = &wasmFunction->instance()->instance();
-                    entrypointLoadLocation = wasmFunction->entrypointLoadLocation();
-                }
-                else {
-                    importedSignatureIndex = wasmWrapperFunction->signatureIndex();
-                    // b. Let closure be v.[[Closure]].
-                    function = wasmWrapperFunction->function();
-                }
-                Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
-                if (importedSignatureIndex != expectedSignatureIndex)
-                    return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported function", "signature doesn't match the provided WebAssembly function's signature")));
-            }
-            // iii. Otherwise:
-            // a. Let closure be a new host function of the given signature which calls v by coercing WebAssembly arguments to JavaScript arguments via ToJSValue and returns the result, if any, by coercing via ToWebAssemblyValue.
-            // Note: done as part of Plan compilation.
-            // iv. Append v to funcs.
-            // Note: adding the JSCell to the instance list fulfills closure requirements b. above (the WebAssembly.Instance wil be kept alive) and v. below (the JSFunction).
-
-            ASSERT(numImportFunctions == import.kindIndex);
-            auto* info = jsInstance->instance().importFunctionInfo(numImportFunctions);
-            info->targetInstance = calleeInstance;
-            info->wasmEntrypointLoadLocation = entrypointLoadLocation;
-            jsInstance->instance().importFunction<PoisonedBarrier<JSObject>>(numImportFunctions)->set(vm, jsInstance, function);
-            ++numImportFunctions;
-            // v. Append closure to imports.
             break;
         }
         case Wasm::ExternalKind::Table: {
@@ -329,6 +323,7 @@ JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, ExecState* exec, JS
         }
         }
     }
+    ASSERT(moduleRecord->importEntries().size() == moduleInformation.imports.size());
 
     {
         if (!!moduleInformation.memory && moduleInformation.memory.isImport()) {
index ed9b2b1..3ca46d6 100644 (file)
@@ -33,6 +33,7 @@
 #include "JSWebAssemblyCodeBlock.h"
 #include "JSWebAssemblyMemory.h"
 #include "JSWebAssemblyTable.h"
+#include "WasmCreationMode.h"
 #include "WasmInstance.h"
 #include <wtf/Ref.h>
 
@@ -50,12 +51,14 @@ class JSWebAssemblyInstance final : public JSDestructibleObject {
 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>&&, Wasm::CreationMode);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_EXPORT_INFO;
 
-    void finalizeCreation(VM&, ExecState*, Ref<Wasm::CodeBlock>&&);
+    void finalizeCreation(VM&, ExecState*, Ref<Wasm::CodeBlock>&&, JSObject* importObject, Wasm::CreationMode);
     
     Wasm::Instance& instance() { return m_instance.get(); }
     JSModuleNamespaceObject* moduleNamespaceObject() { return m_moduleNamespaceObject.get(); }
@@ -76,6 +79,8 @@ public:
         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 @@ protected:
     static void visitChildren(JSCell*, SlotVisitor&);
 
 private:
-    JSWebAssemblyModule* module() const { return m_module.get(); }
-
     PoisonedRef<JSWebAssemblyInstancePoison, Wasm::Instance> m_instance;
 
     PoisonedBarrier<JSWebAssemblyModule> m_module;
index b6788fa..2089e4f 100644 (file)
@@ -77,10 +77,10 @@ static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* ex
     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()), Wasm::CreationMode::FromJS);
     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), importObject, Wasm::CreationMode::FromJS);
     RETURN_IF_EXCEPTION(scope, { });
     return JSValue::encode(instance);
 }
index e34646c..178d9a5 100644 (file)
@@ -86,16 +86,152 @@ void WebAssemblyModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
     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, JSObject* importObject, Wasm::CreationMode creationMode)
 {
     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();
 
+    auto exception = [&] (JSObject* error) {
+        throwException(exec, scope, error);
+    };
+
+    auto importFailMessage = [&] (const Wasm::Import& import, const char* before, const char* after) {
+        return makeString(before, " ", String::fromUTF8(import.module), ":", String::fromUTF8(import.field), " ", after);
+    };
+
+    for (const auto& import : moduleInformation.imports) {
+        // Validation and linking other than Wasm::ExternalKind::Function is already done in JSWebAssemblyInstance.
+        // Eventually we will move all the linking code in JSWebAssemblyInstance here and remove this switch statement.
+        switch (import.kind) {
+        case Wasm::ExternalKind::Function:
+            break;
+        case Wasm::ExternalKind::Table:
+        case Wasm::ExternalKind::Memory:
+        case Wasm::ExternalKind::Global:
+            continue;
+        }
+
+        Identifier moduleName = Identifier::fromString(&vm, String::fromUTF8(import.module));
+        Identifier fieldName = Identifier::fromString(&vm, String::fromUTF8(import.field));
+        JSValue value;
+        if (creationMode == Wasm::CreationMode::FromJS) {
+            // 1. Let o be the resultant value of performing Get(importObject, i.module_name).
+            JSValue importModuleValue = importObject->get(exec, moduleName);
+            RETURN_IF_EXCEPTION(scope, void());
+            // 2. If Type(o) is not Object, throw a TypeError.
+            if (!importModuleValue.isObject())
+                return exception(createTypeError(exec, importFailMessage(import, "import", "must be an object"), defaultSourceAppender, runtimeTypeForValue(importModuleValue)));
+
+            // 3. Let v be the value of performing Get(o, i.item_name)
+            JSObject* object = jsCast<JSObject*>(importModuleValue);
+            value = object->get(exec, fieldName);
+            RETURN_IF_EXCEPTION(scope, void());
+        } else {
+            AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, moduleName);
+            RETURN_IF_EXCEPTION(scope, void());
+            Resolution resolution = importedModule->resolveExport(exec, fieldName);
+            RETURN_IF_EXCEPTION(scope, void());
+            switch (resolution.type) {
+            case Resolution::Type::NotFound:
+                throwSyntaxError(exec, scope, makeString("Importing binding name '", String(fieldName.impl()), "' is not found."));
+                return;
+
+            case Resolution::Type::Ambiguous:
+                throwSyntaxError(exec, scope, makeString("Importing binding name '", String(fieldName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));
+                return;
+
+            case Resolution::Type::Error:
+                throwSyntaxError(exec, scope, makeString("Importing binding name 'default' cannot be resolved by star export entries."));
+                return;
+
+            case Resolution::Type::Resolved:
+                break;
+            }
+
+            AbstractModuleRecord* importedRecord = resolution.moduleRecord;
+            JSModuleEnvironment* importedEnvironment = importedRecord->moduleEnvironmentMayBeNull();
+            // It means that target module is not linked yet. In wasm loading, we allow this since we do not solve cyclic resolution as if JS's bindings.
+            // At that time, error occurs since |value| is an empty, and later |value| becomes an undefined.
+            // https://github.com/WebAssembly/esm-integration/tree/master/proposals/esm-integration#js---wasm-cycle-where-js-is-higher-in-the-module-graph
+            if (importedEnvironment) {
+                SymbolTable* symbolTable = importedEnvironment->symbolTable();
+                ConcurrentJSLocker locker(symbolTable->m_lock);
+                auto iter = symbolTable->find(locker, resolution.localName.impl());
+                ASSERT(iter != symbolTable->end(locker));
+                SymbolTableEntry& entry = iter->value;
+                ASSERT(!entry.isNull());
+                ASSERT(importedEnvironment->isValidScopeOffset(entry.scopeOffset()));
+
+                // Snapshotting a value.
+                value = importedEnvironment->variableAt(entry.scopeOffset()).get();
+            }
+        }
+        if (!value)
+            value = jsUndefined();
+
+        switch (import.kind) {
+        case Wasm::ExternalKind::Function: {
+            // 4. If i is a function import:
+            // i. If IsCallable(v) is false, throw a WebAssembly.LinkError.
+            if (!value.isFunction())
+                return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "import function", "must be callable")));
+
+            Wasm::Instance* calleeInstance = nullptr;
+            WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = nullptr;
+            JSObject* function = jsCast<JSObject*>(value);
+
+            // ii. If v is an Exported Function Exotic Object:
+            WebAssemblyFunction* wasmFunction;
+            WebAssemblyWrapperFunction* wasmWrapperFunction;
+            if (isWebAssemblyHostFunction(vm, function, wasmFunction, wasmWrapperFunction)) {
+                // a. If the signature of v does not match the signature of i, throw a WebAssembly.LinkError.
+                Wasm::SignatureIndex importedSignatureIndex;
+                if (wasmFunction) {
+                    importedSignatureIndex = wasmFunction->signatureIndex();
+                    calleeInstance = &wasmFunction->instance()->instance();
+                    entrypointLoadLocation = wasmFunction->entrypointLoadLocation();
+                } else {
+                    importedSignatureIndex = wasmWrapperFunction->signatureIndex();
+                    // b. Let closure be v.[[Closure]].
+                    function = wasmWrapperFunction->function();
+                }
+                Wasm::SignatureIndex expectedSignatureIndex = moduleInformation.importFunctionSignatureIndices[import.kindIndex];
+                if (importedSignatureIndex != expectedSignatureIndex)
+                    return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "imported function", "signature doesn't match the provided WebAssembly function's signature")));
+            }
+            // iii. Otherwise:
+            // a. Let closure be a new host function of the given signature which calls v by coercing WebAssembly arguments to JavaScript arguments via ToJSValue and returns the result, if any, by coercing via ToWebAssemblyValue.
+            // Note: done as part of Plan compilation.
+            // iv. Append v to funcs.
+            // Note: adding the JSCell to the instance list fulfills closure requirements b. above (the WebAssembly.Instance wil be kept alive) and v. below (the JSFunction).
+
+            auto* info = m_instance->instance().importFunctionInfo(import.kindIndex);
+            info->targetInstance = calleeInstance;
+            info->wasmEntrypointLoadLocation = entrypointLoadLocation;
+            m_instance->instance().importFunction<JSWebAssemblyInstance::PoisonedBarrier<JSObject>>(import.kindIndex)->set(vm, m_instance.get(), function);
+            break;
+        }
+        case Wasm::ExternalKind::Table:
+        case Wasm::ExternalKind::Memory:
+        case Wasm::ExternalKind::Global:
+            break;
+        }
+    }
+
     SymbolTable* exportSymbolTable = module->exportSymbolTable();
     unsigned functionImportCount = codeBlock->functionImportCount();
 
@@ -110,12 +246,12 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
             //   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,23 +262,23 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
                 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;
         }
         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 +288,7 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
             // 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 +296,11 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
                 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 +327,15 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
         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);
 }
 
index fce1d64..316f337 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(WEBASSEMBLY)
 
 #include "AbstractModuleRecord.h"
+#include "WasmCreationMode.h"
 #include "WasmModuleInformation.h"
 
 namespace JSC {
@@ -48,7 +49,8 @@ public:
     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, JSObject* importObject, Wasm::CreationMode);
     JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
 
 private:
index 46441d3..c7ad0e3 100644 (file)
@@ -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 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
     }
 }
 
-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, JSObject* importObject, Ref<Wasm::CodeBlock>&& codeBlock, Resolve resolveKind, Wasm::CreationMode creationMode)
 {
     auto scope = DECLARE_CATCH_SCOPE(vm);
-    instance->finalizeCreation(vm, exec, WTFMove(codeBlock));
+    instance->finalizeCreation(vm, exec, WTFMove(codeBlock), importObject, creationMode);
     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,53 +144,67 @@ static void resolve(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSWebAs
     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, Wasm::CreationMode creationMode)
 {
     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()), creationMode);
     RETURN_IF_EXCEPTION(scope, reject(exec, scope, promise));
 
     Vector<Strong<JSCell>> dependencies;
     // The instance keeps the module alive.
     dependencies.append(Strong<JSCell>(vm, instance));
+    dependencies.append(Strong<JSCell>(vm, importObject));
     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, importObject, resolveKind, creationMode, &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, importObject, resolveKind, creationMode, &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, importObject, codeBlock.releaseNonNull(), resolveKind, creationMode);
         });
     }), &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, Wasm::CreationMode creationMode)
 {
     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, creationMode, &vm] (Wasm::Module::ValidationResult&& result) mutable {
+        vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, importObject, moduleKeyCell, globalObject, result = WTFMove(result), resolveKind, creationMode, &vm] () mutable {
             auto scope = DECLARE_CATCH_SCOPE(vm);
             ExecState* exec = globalObject->globalExec();
             JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(result));
             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, creationMode);
         });
     }));
 }
 
+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, Wasm::CreationMode::FromModuleLoader);
+    return promise->promise();
+}
+
 static EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec)
 {
     VM& vm = exec->vm();
@@ -206,9 +226,9 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec)
         } 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, Wasm::CreationMode::FromJS);
             else
-                compileAndInstantiate(vm, exec, promise, firstArgument, importObject);
+                compileAndInstantiate(vm, exec, promise, JSWebAssemblyInstance::createPrivateModuleKey(), firstArgument, importObject, Resolve::WithModuleAndInstance, Wasm::CreationMode::FromJS);
         }
 
         return JSValue::encode(promise->promise());
@@ -220,7 +240,7 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyValidateFunc(ExecState* exec)
     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());
index d5d0d6c..bbb226d 100644 (file)
@@ -42,6 +42,8 @@ public:
 
     DECLARE_INFO;
 
+    static JSValue instantiate(ExecState*, JSPromiseDeferred*, const Identifier&, JSValue);
+
 protected:
     void finishCreation(VM&);
 
index 38da50b..c1c65df 100644 (file)
@@ -1,3 +1,10 @@
+2018-04-18  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        Unreviewed, reland r230697, r230720, and r230724.
+        https://bugs.webkit.org/show_bug.cgi?id=184600
+
+        * Scripts/run-jsc-stress-tests:
+
 2018-04-17  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GLIB] Make it possible to handle JSCClass external properties not added to the prototype
index a186c09..e9c1bb0 100755 (executable)
@@ -1001,6 +1001,19 @@ end
 def runWebAssembly
     return if !$jitTests
     return if !$isFTLPlatform
+    run("default-wasm", "-m", *FTL_OPTIONS)
+    if $mode != "quick"
+        run("wasm-no-cjit-yes-tls-context", "-m", "--useFastTLSForWasmContext=true", *(FTL_OPTIONS + NO_CJIT_OPTIONS))
+        run("wasm-eager-jettison", "-m", "--forceCodeBlockToJettisonDueToOldAge=true", *FTL_OPTIONS)
+        run("wasm-no-call-ic", "-m", "--useCallICsForWebAssemblyToJSCalls=false", *FTL_OPTIONS)
+        run("wasm-no-tls-context", "-m", "--useFastTLSForWasmContext=false", *FTL_OPTIONS)
+        run("wasm-slow-memory", "-m", "--useWebAssemblyFastMemory=false", *FTL_OPTIONS)
+    end
+end
+
+def runWebAssemblySuite
+    return if !$jitTests
+    return if !$isFTLPlatform
     modules = Dir[WASMTESTS_PATH + "*.js"].map { |f| File.basename(f) }
     prepareExtraAbsoluteFiles(WASMTESTS_PATH, ["wasm.json"])
     prepareExtraRelativeFiles(modules.map { |f| "../" + f }, $collection)