Log Message
WebAssembly JS API: throw when a promise can't be created https://bugs.webkit.org/show_bug.cgi?id=179826 <rdar://problem/35455813>
Reviewed by Mark Lam.
JSTests:
Test WebAssembly.{compile,instantiate} where promise creation
fails because of a stack overflow.
* wasm/js-api/promise-stack-overflow.js: Added.
(const.runNearStackLimit.f.const.t):
(async.testCompile):
(async.testInstantiate):
Source/_javascript_Core:
Failure *in* a promise causes rejection, but failure to create a
promise (because of stack overflow) isn't really spec'd (as all
stack things JS). This applies to WebAssembly.compile and
WebAssembly.instantiate.
Dan's current proposal says:
https://littledan.github.io/spec/document/js-api/index.html#stack-overflow
Whenever a stack overflow occurs in WebAssembly code, the same
class of exception is thrown as for a stack overflow in
_javascript_. The particular exception here is
implementation-defined in both cases.
Note: ECMAScript doesn’t specify any sort of behavior on stack
overflow; implementations have been observed to throw RangeError,
InternalError or Error. Any is valid here.
This is for general stack overflow within WebAssembly, not
specifically for promise creation within _javascript_, but it seems
like a stack overflow in promise creation should follow the same
rule instead of, say, swallowing the overflow and returning
undefined.
* wasm/js/WebAssemblyPrototype.cpp:
(JSC::webAssemblyCompileFunc):
(JSC::webAssemblyInstantiateFunc):
Modified Paths
- trunk/JSTests/ChangeLog
- trunk/Source/_javascript_Core/ChangeLog
- trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp
Added Paths
Diff
Modified: trunk/JSTests/ChangeLog (224984 => 224985)
--- trunk/JSTests/ChangeLog 2017-11-17 21:38:11 UTC (rev 224984)
+++ trunk/JSTests/ChangeLog 2017-11-17 21:57:09 UTC (rev 224985)
@@ -1,3 +1,19 @@
+2017-11-17 JF Bastien <[email protected]>
+
+ WebAssembly JS API: throw when a promise can't be created
+ https://bugs.webkit.org/show_bug.cgi?id=179826
+ <rdar://problem/35455813>
+
+ Reviewed by Mark Lam.
+
+ Test WebAssembly.{compile,instantiate} where promise creation
+ fails because of a stack overflow.
+
+ * wasm/js-api/promise-stack-overflow.js: Added.
+ (const.runNearStackLimit.f.const.t):
+ (async.testCompile):
+ (async.testInstantiate):
+
2017-11-16 Yusuke Suzuki <[email protected]>
Unreviewed, mark regress-178385.js as memory exhausting
Added: trunk/JSTests/wasm/js-api/promise-stack-overflow.js (0 => 224985)
--- trunk/JSTests/wasm/js-api/promise-stack-overflow.js (rev 0)
+++ trunk/JSTests/wasm/js-api/promise-stack-overflow.js 2017-11-17 21:57:09 UTC (rev 224985)
@@ -0,0 +1,37 @@
+import * as assert from '../assert.js';
+
+const module = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x1, 0x00, 0x00, 0x00);
+
+let promises = [];
+
+const runNearStackLimit = f => {
+ const t = () => {
+ try {
+ return t();
+ } catch (e) {
+ return f();
+ }
+ };
+ return t();
+};
+
+const touchArgument = arg => promises.push(arg);
+
+const compileMe = () => touchArgument(WebAssembly.compile(module));
+
+async function testCompile() {
+ await touchArgument(async function() {
+ runNearStackLimit(compileMe);
+ }());
+}
+
+const instantiateMe = () => touchArgument(WebAssembly.instantiate(module));
+
+async function testInstantiate() {
+ await touchArgument(async function() {
+ runNearStackLimit(instantiateMe);
+ }());
+}
+
+assert.asyncTest(testCompile());
+assert.asyncTest(testInstantiate());
Modified: trunk/Source/_javascript_Core/ChangeLog (224984 => 224985)
--- trunk/Source/_javascript_Core/ChangeLog 2017-11-17 21:38:11 UTC (rev 224984)
+++ trunk/Source/_javascript_Core/ChangeLog 2017-11-17 21:57:09 UTC (rev 224985)
@@ -1,3 +1,39 @@
+2017-11-17 JF Bastien <[email protected]>
+
+ WebAssembly JS API: throw when a promise can't be created
+ https://bugs.webkit.org/show_bug.cgi?id=179826
+ <rdar://problem/35455813>
+
+ Reviewed by Mark Lam.
+
+ Failure *in* a promise causes rejection, but failure to create a
+ promise (because of stack overflow) isn't really spec'd (as all
+ stack things JS). This applies to WebAssembly.compile and
+ WebAssembly.instantiate.
+
+ Dan's current proposal says:
+
+ https://littledan.github.io/spec/document/js-api/index.html#stack-overflow
+
+ Whenever a stack overflow occurs in WebAssembly code, the same
+ class of exception is thrown as for a stack overflow in
+ _javascript_. The particular exception here is
+ implementation-defined in both cases.
+
+ Note: ECMAScript doesn’t specify any sort of behavior on stack
+ overflow; implementations have been observed to throw RangeError,
+ InternalError or Error. Any is valid here.
+
+ This is for general stack overflow within WebAssembly, not
+ specifically for promise creation within _javascript_, but it seems
+ like a stack overflow in promise creation should follow the same
+ rule instead of, say, swallowing the overflow and returning
+ undefined.
+
+ * wasm/js/WebAssemblyPrototype.cpp:
+ (JSC::webAssemblyCompileFunc):
+ (JSC::webAssemblyInstantiateFunc):
+
2017-11-16 Daniel Bates <[email protected]>
Add feature define for alternative presentation button element
Modified: trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp (224984 => 224985)
--- trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp 2017-11-17 21:38:11 UTC (rev 224984)
+++ trunk/Source/_javascript_Core/wasm/js/WebAssemblyPrototype.cpp 2017-11-17 21:57:09 UTC (rev 224985)
@@ -40,6 +40,7 @@
#include "ObjectConstructor.h"
#include "PromiseDeferredTimer.h"
#include "StrongInlines.h"
+#include "ThrowScope.h"
#include "WasmBBQPlan.h"
#include "WasmToJS.h"
#include "WasmWorklist.h"
@@ -81,38 +82,42 @@
static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
{
VM& vm = exec->vm();
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
auto* globalObject = exec->lexicalGlobalObject();
JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
- CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- Vector<Strong<JSCell>> dependencies;
- dependencies.append(Strong<JSCell>(vm, globalObject));
- vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies));
+ {
+ auto catchScope = DECLARE_CATCH_SCOPE(vm);
- Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, exec->argument(0));
+ Vector<Strong<JSCell>> dependencies;
+ dependencies.append(Strong<JSCell>(vm, globalObject));
+ vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies));
- if (UNLIKELY(scope.exception()))
- reject(exec, scope, promise);
- else {
- Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable {
- vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, globalObject, result = WTFMove(result), &vm] () mutable {
- auto scope = DECLARE_CATCH_SCOPE(vm);
- ExecState* exec = globalObject->globalExec();
- JSValue module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(result));
- if (UNLIKELY(scope.exception())) {
- reject(exec, scope, promise);
- return;
- }
+ Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, exec->argument(0));
- promise->resolve(exec, module);
- CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
- });
- }));
+ if (UNLIKELY(catchScope.exception()))
+ reject(exec, catchScope, promise);
+ else {
+ Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable {
+ vm.promiseDeferredTimer->scheduleWorkSoon(promise, [promise, globalObject, result = WTFMove(result), &vm] () mutable {
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ ExecState* exec = globalObject->globalExec();
+ JSValue module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(result));
+ if (UNLIKELY(scope.exception())) {
+ reject(exec, scope, promise);
+ return;
+ }
+
+ promise->resolve(exec, module);
+ CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
+ });
+ }));
+ }
+
+ return JSValue::encode(promise->promise());
}
-
- return JSValue::encode(promise->promise());
}
enum class Resolve { WithInstance, WithModuleAndInstance };
@@ -172,7 +177,7 @@
auto scope = DECLARE_CATCH_SCOPE(vm);
ExecState* exec = globalObject->globalExec();
JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(result));
- if (scope.exception())
+ if (UNLIKELY(scope.exception()))
return reject(exec, scope, promise);
instantiate(vm, exec, promise, module, importObject, Resolve::WithModuleAndInstance);
@@ -183,27 +188,31 @@
static EncodedJSValue JSC_HOST_CALL webAssemblyInstantiateFunc(ExecState* exec)
{
VM& vm = exec->vm();
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto* globalObject = exec->lexicalGlobalObject();
- JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, exec->lexicalGlobalObject());
- CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
+ RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
- JSValue importArgument = exec->argument(1);
- JSObject* importObject = importArgument.getObject();
- if (!importArgument.isUndefined() && !importObject) {
- promise->reject(exec, createTypeError(exec,
- ASCIILiteral("second argument to WebAssembly.instantiate must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument)));
- CLEAR_AND_RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ {
+ auto catchScope = DECLARE_CATCH_SCOPE(vm);
+
+ JSValue importArgument = exec->argument(1);
+ JSObject* importObject = importArgument.getObject();
+ if (UNLIKELY(!importArgument.isUndefined() && !importObject)) {
+ promise->reject(exec, createTypeError(exec,
+ ASCIILiteral("second argument to WebAssembly.instantiate must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument)));
+ CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, JSValue::encode(promise->promise()));
+ } else {
+ JSValue firstArgument = exec->argument(0);
+ if (auto* module = jsDynamicCast<JSWebAssemblyModule*>(vm, firstArgument))
+ instantiate(vm, exec, promise, module, importObject, Resolve::WithInstance);
+ else
+ compileAndInstantiate(vm, exec, promise, firstArgument, importObject);
+ }
+
return JSValue::encode(promise->promise());
}
-
- JSValue firstArgument = exec->argument(0);
- if (auto* module = jsDynamicCast<JSWebAssemblyModule*>(vm, firstArgument))
- instantiate(vm, exec, promise, module, importObject, Resolve::WithInstance);
- else
- compileAndInstantiate(vm, exec, promise, firstArgument, importObject);
-
- return JSValue::encode(promise->promise());
}
static EncodedJSValue JSC_HOST_CALL webAssemblyValidateFunc(ExecState* exec)
_______________________________________________ webkit-changes mailing list [email protected] https://lists.webkit.org/mailman/listinfo/webkit-changes
