Diff
Modified: trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm (271765 => 271766)
--- trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm 2021-01-23 00:07:28 UTC (rev 271766)
@@ -134,33 +134,25 @@
JSInternalPromise* JSAPIGlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, JSModuleLoader*, JSString* specifierValue, JSValue, const SourceOrigin& sourceOrigin)
{
VM& vm = globalObject->vm();
- auto scope = DECLARE_CATCH_SCOPE(vm);
- auto reject = [&] (Exception* exception) -> JSInternalPromise* {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ auto reject = [&] (ThrowScope& scope) -> JSInternalPromise* {
auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
- if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
- return promise;
- JSValue error = exception->value();
- scope.clearException();
- // FIXME: We could have error since any JS call can throw stack-overflow errors.
- // https://bugs.webkit.org/show_bug.cgi?id=203402
- promise->reject(globalObject, error);
- return promise;
+ return promise->rejectWithCaughtException(globalObject, scope);
};
auto import = [&] (URL& url) {
auto result = importModule(globalObject, Identifier::fromString(vm, url.string()), jsUndefined(), jsUndefined());
- if (UNLIKELY(scope.exception()))
- return reject(scope.exception());
+ RETURN_IF_EXCEPTION(scope, reject(scope));
return result;
};
auto specifier = specifierValue->value(globalObject);
- if (UNLIKELY(scope.exception()))
- return reject(scope.exception());
+ RETURN_IF_EXCEPTION(scope, reject(scope));
auto result = computeValidImportSpecifier(sourceOrigin.url(), specifier);
if (result)
return import(result.value());
+ scope.release();
auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
// FIXME: We could have error since any JS call can throw stack-overflow errors.
// https://bugs.webkit.org/show_bug.cgi?id=203402
@@ -171,7 +163,7 @@
JSInternalPromise* JSAPIGlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, JSModuleLoader*, JSValue key, JSValue, JSValue)
{
VM& vm = globalObject->vm();
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
ASSERT(globalObject == globalObject);
JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject)];
@@ -179,16 +171,10 @@
JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
Identifier moduleKey = key.toPropertyKey(globalObject);
- if (UNLIKELY(scope.exception())) {
- Exception* exception = scope.exception();
- if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
- return promise;
- scope.clearException();
- promise->reject(globalObject, exception->value());
- return promise;
- }
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
if (UNLIKELY(![context moduleLoaderDelegate])) {
+ scope.release();
promise->reject(globalObject, createError(globalObject, "No module loader provided."));
return promise;
}
@@ -232,6 +218,7 @@
[[context moduleLoaderDelegate] context:context fetchModuleForIdentifier:[::JSValue valueWithJSValueRef:toRef(globalObject, key) inContext:context] withResolveHandler:[::JSValue valueWithJSValueRef:toRef(globalObject, resolve) inContext:context] andRejectHandler:[::JSValue valueWithJSValueRef:toRef(globalObject, reject) inContext:context]];
if (context.exception) {
+ scope.release();
promise->reject(globalObject, toJS(globalObject, [context.exception JSValueRef]));
context.exception = nil;
}
Modified: trunk/Source/_javascript_Core/ChangeLog (271765 => 271766)
--- trunk/Source/_javascript_Core/ChangeLog 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/ChangeLog 2021-01-23 00:07:28 UTC (rev 271766)
@@ -1,3 +1,51 @@
+2021-01-22 Yusuke Suzuki <[email protected]>
+
+ REGRESSION (r271731): Unchecked JS exception under GlobalObject::moduleLoaderFetch
+ https://bugs.webkit.org/show_bug.cgi?id=220868
+
+ Reviewed by Mark Lam.
+
+ Because TerminatedExecutionError needs to be uncaught, CatchScope's semantics does not work well.
+ So, we extend ThrowScope to implement CatchScope's feature, and use ThrowScope etc.
+ We also add JSPromise::rejectWithCaughtException since this pattern is common enough.
+
+ * API/JSAPIGlobalObject.mm:
+ (JSC::JSAPIGlobalObject::moduleLoaderImportModule):
+ (JSC::JSAPIGlobalObject::moduleLoaderFetch):
+ * jsc.cpp:
+ (GlobalObject::moduleLoaderImportModule):
+ (GlobalObject::moduleLoaderFetch):
+ * runtime/Completion.cpp:
+ (JSC::rejectPromise):
+ (JSC::loadAndEvaluateModule):
+ (JSC::loadModule):
+ * runtime/JSGlobalObjectFunctions.cpp:
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ * runtime/JSInternalPromise.cpp:
+ (JSC::JSInternalPromise::rejectWithCaughtException):
+ * runtime/JSInternalPromise.h:
+ * runtime/JSModuleLoader.cpp:
+ (JSC::JSModuleLoader::importModule):
+ (JSC::JSModuleLoader::resolve):
+ (JSC::JSModuleLoader::fetch):
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ (JSC::reject): Deleted.
+ * runtime/JSPromise.cpp:
+ (JSC::JSPromise::rejectWithCaughtException):
+ * runtime/JSPromise.h:
+ * runtime/ThrowScope.h:
+ (JSC::ThrowScope::clearException):
+ * wasm/js/JSWebAssembly.cpp:
+ (JSC::JSC_DEFINE_HOST_FUNCTION):
+ (JSC::resolve):
+ (JSC::JSWebAssembly::webAssemblyModuleValidateAsync):
+ (JSC::instantiate):
+ (JSC::compileAndInstantiate):
+ (JSC::JSWebAssembly::webAssemblyModuleInstantinateAsync):
+ (JSC::reject): Deleted.
+ (JSC::webAssemblyModuleValidateAsyncInternal): Deleted.
+ (JSC::webAssemblyModuleInstantinateAsyncInternal): Deleted.
+
2021-01-22 Mark Lam <[email protected]>
Disable Options:useAtMethod because of compatibility issue.
Modified: trunk/Source/_javascript_Core/jsc.cpp (271765 => 271766)
--- trunk/Source/_javascript_Core/jsc.cpp 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/jsc.cpp 2021-01-23 00:07:28 UTC (rev 271766)
@@ -826,44 +826,32 @@
JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin& sourceOrigin)
{
VM& vm = globalObject->vm();
- auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
-
auto rejectWithError = [&](JSValue error) {
promise->reject(globalObject, error);
return promise;
};
- auto reject = [&](Exception* exception) {
- if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
- return promise;
- JSValue error = exception->value();
- catchScope.clearException();
- return rejectWithError(error);
- };
-
auto referrer = sourceOrigin.url();
auto specifier = moduleNameValue->value(globalObject);
- RETURN_IF_EXCEPTION(throwScope, nullptr);
- if (UNLIKELY(catchScope.exception()))
- return reject(catchScope.exception());
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
if (!referrer.isLocalFile())
- return rejectWithError(createError(globalObject, makeString("Could not resolve the referrer's path '", referrer.string(), "', while trying to resolve module '", specifier, "'.")));
+ RELEASE_AND_RETURN(scope, rejectWithError(createError(globalObject, makeString("Could not resolve the referrer's path '", referrer.string(), "', while trying to resolve module '", specifier, "'."))));
if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
- return rejectWithError(createTypeError(globalObject, makeString("Module specifier, '"_s, specifier, "' does not start with \"/\", \"./\", or \"../\". Referenced from: "_s, referrer.fileSystemPath())));
+ RELEASE_AND_RETURN(scope, rejectWithError(createTypeError(globalObject, makeString("Module specifier, '"_s, specifier, "' does not start with \"/\", \"./\", or \"../\". Referenced from: "_s, referrer.fileSystemPath()))));
URL moduleURL(referrer, specifier);
if (!moduleURL.isLocalFile())
- return rejectWithError(createError(globalObject, makeString("Module url, '", moduleURL.string(), "' does not map to a local file.")));
+ RELEASE_AND_RETURN(scope, rejectWithError(createError(globalObject, makeString("Module url, '", moduleURL.string(), "' does not map to a local file."))));
auto result = JSC::importModule(globalObject, Identifier::fromString(vm, moduleURL.string()), parameters, jsUndefined());
- if (UNLIKELY(catchScope.exception()))
- return reject(catchScope.exception());
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+
return result;
}
@@ -1181,7 +1169,7 @@
VM& vm = globalObject->vm();
JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
auto rejectWithError = [&](JSValue error) {
promise->reject(globalObject, error);
@@ -1188,17 +1176,8 @@
return promise;
};
- auto reject = [&](Exception* exception) {
- if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
- return promise;
- JSValue error = exception->value();
- catchScope.clearException();
- return rejectWithError(error);
- };
-
String moduleKey = key.toWTFString(globalObject);
- if (UNLIKELY(catchScope.exception()))
- return reject(catchScope.exception());
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
URL moduleURL({ }, moduleKey);
ASSERT(moduleURL.isLocalFile());
@@ -1207,7 +1186,7 @@
Vector<uint8_t> buffer;
if (!fetchModuleFromLocalFileSystem(moduleURL, buffer))
- return rejectWithError(createError(globalObject, makeString("Could not open file '", moduleKey, "'.")));
+ RELEASE_AND_RETURN(scope, rejectWithError(createError(globalObject, makeString("Could not open file '", moduleKey, "'."))));
#if ENABLE(WEBASSEMBLY)
// FileSystem does not have mime-type header. The JSC shell recognizes WebAssembly's magic header.
@@ -1214,9 +1193,9 @@
if (buffer.size() >= 4) {
if (buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' && buffer[3] == 'm') {
auto source = SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleURL }, WTFMove(moduleKey)));
- catchScope.releaseAssertNoException();
+ scope.releaseAssertNoException();
auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
- catchScope.releaseAssertNoException();
+ scope.release();
promise->resolve(globalObject, sourceCode);
return promise;
}
@@ -1224,7 +1203,7 @@
#endif
auto sourceCode = JSSourceCode::create(vm, jscSource(stringFromUTF(buffer), SourceOrigin { moduleURL }, WTFMove(moduleKey), TextPosition(), SourceProviderSourceType::Module));
- catchScope.releaseAssertNoException();
+ scope.release();
promise->resolve(globalObject, sourceCode);
return promise;
}
Modified: trunk/Source/_javascript_Core/runtime/Completion.cpp (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/Completion.cpp 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/Completion.cpp 2021-01-23 00:07:28 UTC (rev 271766)
@@ -176,16 +176,11 @@
return Symbol::create(vm, privateName.uid());
}
-static JSInternalPromise* rejectPromise(CatchScope& scope, JSGlobalObject* globalObject)
+static JSInternalPromise* rejectPromise(ThrowScope& scope, JSGlobalObject* globalObject)
{
VM& vm = globalObject->vm();
JSInternalPromise* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
- if (UNLIKELY(isTerminatedExecutionException(vm, scope.exception())))
- return promise;
- JSValue error = scope.exception()->value();
- scope.clearException();
- promise->reject(globalObject, error);
- return promise;
+ return promise->rejectWithCaughtException(globalObject, scope);
}
JSInternalPromise* loadAndEvaluateModule(JSGlobalObject* globalObject, Symbol* moduleId, JSValue parameters, JSValue scriptFetcher)
@@ -212,7 +207,7 @@
{
VM& vm = globalObject->vm();
JSLockHolder lock(vm);
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
RELEASE_ASSERT(vm.atomStringTable() == Thread::current().atomStringTable());
RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread());
@@ -221,7 +216,7 @@
// Insert the given source code to the ModuleLoader registry as the fetched registry entry.
globalObject->moduleLoader()->provideFetch(globalObject, key, source);
RETURN_IF_EXCEPTION(scope, rejectPromise(scope, globalObject));
- return globalObject->moduleLoader()->loadAndEvaluateModule(globalObject, key, jsUndefined(), scriptFetcher);
+ RELEASE_AND_RETURN(scope, globalObject->moduleLoader()->loadAndEvaluateModule(globalObject, key, jsUndefined(), scriptFetcher));
}
JSInternalPromise* loadModule(JSGlobalObject* globalObject, const String& moduleName, JSValue parameters, JSValue scriptFetcher)
@@ -238,7 +233,7 @@
{
VM& vm = globalObject->vm();
JSLockHolder lock(vm);
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
RELEASE_ASSERT(vm.atomStringTable() == Thread::current().atomStringTable());
RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread());
@@ -248,7 +243,7 @@
// FIXME: Introduce JSSourceCode object to wrap around this source.
globalObject->moduleLoader()->provideFetch(globalObject, key, source);
RETURN_IF_EXCEPTION(scope, rejectPromise(scope, globalObject));
- return globalObject->moduleLoader()->loadModule(globalObject, key, jsUndefined(), scriptFetcher);
+ RELEASE_AND_RETURN(scope, globalObject->moduleLoader()->loadModule(globalObject, key, jsUndefined(), scriptFetcher));
}
JSValue linkAndEvaluateModule(JSGlobalObject* globalObject, const Identifier& moduleKey, JSValue scriptFetcher)
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp 2021-01-23 00:07:28 UTC (rev 271766)
@@ -26,7 +26,6 @@
#include "JSGlobalObjectFunctions.h"
#include "CallFrame.h"
-#include "CatchScope.h"
#include "IndirectEvalExecutable.h"
#include "Interpreter.h"
#include "IntlDateTimeFormat.h"
@@ -798,30 +797,20 @@
auto* promise = JSPromise::create(vm, globalObject->promiseStructure());
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
- auto reject = [&](Exception* exception) {
- if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
- return promise;
- JSValue error = exception->value();
- catchScope.clearException();
- promise->reject(globalObject, error);
- return promise;
- };
-
auto sourceOrigin = callFrame->callerSourceOrigin(vm);
RELEASE_ASSERT(callFrame->argumentCount() == 1);
auto* specifier = callFrame->uncheckedArgument(0).toString(globalObject);
- if (Exception* exception = catchScope.exception())
- return JSValue::encode(reject(exception));
+ RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(globalObject, scope)));
// We always specify parameters as undefined. Once dynamic import() starts accepting fetching parameters,
// we should retrieve this from the arguments.
JSValue parameters = jsUndefined();
auto* internalPromise = globalObject->moduleLoader()->importModule(globalObject, specifier, parameters, sourceOrigin);
- if (Exception* exception = catchScope.exception())
- return JSValue::encode(reject(exception));
+ RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(globalObject, scope)));
+ scope.release();
promise->resolve(globalObject, internalPromise);
return JSValue::encode(promise);
}
Modified: trunk/Source/_javascript_Core/runtime/JSInternalPromise.cpp (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/JSInternalPromise.cpp 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/JSInternalPromise.cpp 2021-01-23 00:07:28 UTC (rev 271766)
@@ -73,4 +73,9 @@
RELEASE_AND_RETURN(scope, jsCast<JSInternalPromise*>(call(globalObject, function, callData, this, arguments)));
}
+JSInternalPromise* JSInternalPromise::rejectWithCaughtException(JSGlobalObject* globalObject, ThrowScope& scope)
+{
+ return jsCast<JSInternalPromise*>(JSPromise::rejectWithCaughtException(globalObject, scope));
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSInternalPromise.h (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/JSInternalPromise.h 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/JSInternalPromise.h 2021-01-23 00:07:28 UTC (rev 271766)
@@ -51,6 +51,8 @@
JS_EXPORT_PRIVATE JSInternalPromise* then(JSGlobalObject*, JSFunction* = nullptr, JSFunction* = nullptr);
+ JS_EXPORT_PRIVATE JSInternalPromise* rejectWithCaughtException(JSGlobalObject*, ThrowScope&);
+
private:
JSInternalPromise(VM&, Structure*);
};
Modified: trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp 2021-01-23 00:07:28 UTC (rev 271766)
@@ -120,18 +120,6 @@
return vm.propertyNames->emptyIdentifier.impl();
}
-static JSInternalPromise* reject(JSGlobalObject* globalObject, CatchScope& catchScope, JSInternalPromise* promise)
-{
- VM& vm = globalObject->vm();
- Exception* exception = catchScope.exception();
- ASSERT(exception);
- if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
- return promise;
- catchScope.clearException();
- promise->reject(globalObject, exception->value());
- return promise;
-}
-
JSArray* JSModuleLoader::dependencyKeysIfEvaluated(JSGlobalObject* globalObject, JSValue key)
{
VM& vm = globalObject->vm();
@@ -256,15 +244,16 @@
dataLogLnIf(Options::dumpModuleLoadingState(), "Loader [import] ", printableModuleKey(globalObject, moduleName));
VM& vm = globalObject->vm();
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
if (globalObject->globalObjectMethodTable()->moduleLoaderImportModule)
- return globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, this, moduleName, parameters, referrer);
+ RELEASE_AND_RETURN(scope, globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, this, moduleName, parameters, referrer));
auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
String moduleNameString = moduleName->value(globalObject);
- if (UNLIKELY(catchScope.exception()))
- return reject(globalObject, catchScope, promise);
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+
+ scope.release();
promise->reject(globalObject, createError(globalObject, makeString("Could not import the module '", moduleNameString, "'.")));
return promise;
}
@@ -281,12 +270,13 @@
JSInternalPromise* JSModuleLoader::resolve(JSGlobalObject* globalObject, JSValue name, JSValue referrer, JSValue scriptFetcher)
{
VM& vm = globalObject->vm();
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
const Identifier moduleKey = resolveSync(globalObject, name, referrer, scriptFetcher);
- if (UNLIKELY(catchScope.exception()))
- return reject(globalObject, catchScope, promise);
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+
+ scope.release();
promise->resolve(globalObject, identifierToJSValue(vm, moduleKey));
return promise;
}
@@ -296,15 +286,16 @@
dataLogLnIf(Options::dumpModuleLoadingState(), "Loader [fetch] ", printableModuleKey(globalObject, key));
VM& vm = globalObject->vm();
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
if (globalObject->globalObjectMethodTable()->moduleLoaderFetch)
- return globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, this, key, parameters, scriptFetcher);
+ RELEASE_AND_RETURN(scope, globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, this, key, parameters, scriptFetcher));
auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
String moduleKey = key.toWTFString(globalObject);
- if (UNLIKELY(catchScope.exception()))
- return reject(globalObject, catchScope, promise);
+ RETURN_IF_EXCEPTION(scope, promise->rejectWithCaughtException(globalObject, scope));
+
+ scope.release();
promise->reject(globalObject, createError(globalObject, makeString("Could not open the module '", moduleKey, "'.")));
return promise;
}
@@ -355,7 +346,7 @@
auto* promise = JSInternalPromise::create(vm, globalObject->internalPromiseStructure());
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
auto rejectWithError = [&](JSValue error) {
promise->reject(globalObject, error);
@@ -363,8 +354,7 @@
};
const Identifier moduleKey = callFrame->argument(0).toPropertyKey(globalObject);
- if (UNLIKELY(catchScope.exception()))
- return JSValue::encode(reject(globalObject, catchScope, promise));
+ RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(globalObject, scope)));
JSValue source = callFrame->argument(1);
auto* jsSourceCode = jsCast<JSSourceCode*>(source);
@@ -372,7 +362,7 @@
#if ENABLE(WEBASSEMBLY)
if (sourceCode.provider()->sourceType() == SourceProviderSourceType::WebAssembly)
- return JSValue::encode(JSWebAssembly::instantiate(globalObject, promise, moduleKey, jsSourceCode));
+ RELEASE_AND_RETURN(scope, JSValue::encode(JSWebAssembly::instantiate(globalObject, promise, moduleKey, jsSourceCode)));
#endif
ParserError error;
@@ -380,15 +370,14 @@
vm, sourceCode, Identifier(), JSParserBuiltinMode::NotBuiltin,
JSParserStrictMode::Strict, JSParserScriptMode::Module, SourceParseMode::ModuleAnalyzeMode, SuperBinding::NotNeeded, error);
if (error.isValid())
- return JSValue::encode(rejectWithError(error.toErrorObject(globalObject, sourceCode)));
+ RELEASE_AND_RETURN(scope, JSValue::encode(rejectWithError(error.toErrorObject(globalObject, sourceCode))));
ASSERT(moduleProgramNode);
ModuleAnalyzer moduleAnalyzer(globalObject, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
- if (UNLIKELY(catchScope.exception()))
- return JSValue::encode(reject(globalObject, catchScope, promise));
+ RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(globalObject, scope)));
+ scope.release();
promise->resolve(globalObject, moduleAnalyzer.analyze(*moduleProgramNode));
- catchScope.clearException();
return JSValue::encode(promise);
}
Modified: trunk/Source/_javascript_Core/runtime/JSPromise.cpp (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/JSPromise.cpp 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/JSPromise.cpp 2021-01-23 00:07:28 UTC (rev 271766)
@@ -206,4 +206,19 @@
rejectAsHandled(lexicalGlobalObject, reason->value());
}
+JSPromise* JSPromise::rejectWithCaughtException(JSGlobalObject* globalObject, ThrowScope& scope)
+{
+ VM& vm = globalObject->vm();
+ Exception* exception = scope.exception();
+ ASSERT(exception);
+ if (UNLIKELY(isTerminatedExecutionException(vm, exception))) {
+ scope.release();
+ return this;
+ }
+ scope.clearException();
+ scope.release();
+ reject(globalObject, exception->value());
+ return this;
+}
+
} // namespace JSC
Modified: trunk/Source/_javascript_Core/runtime/JSPromise.h (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/JSPromise.h 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/JSPromise.h 2021-01-23 00:07:28 UTC (rev 271766)
@@ -84,6 +84,8 @@
JS_EXPORT_PRIVATE void reject(JSGlobalObject*, Exception*);
JS_EXPORT_PRIVATE void rejectAsHandled(JSGlobalObject*, Exception*);
+ JS_EXPORT_PRIVATE JSPromise* rejectWithCaughtException(JSGlobalObject*, ThrowScope&);
+
struct DeferredData {
WTF_FORBID_HEAP_ALLOCATION;
public:
Modified: trunk/Source/_javascript_Core/runtime/ThrowScope.h (271765 => 271766)
--- trunk/Source/_javascript_Core/runtime/ThrowScope.h 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/runtime/ThrowScope.h 2021-01-23 00:07:28 UTC (rev 271766)
@@ -52,6 +52,8 @@
void release() { m_isReleased = true; }
+ void clearException() { m_vm.clearException(); }
+
JS_EXPORT_PRIVATE void printIfNeedCheck(const char* functionName, const char* file, unsigned line);
private:
@@ -80,6 +82,8 @@
ALWAYS_INLINE Exception* throwException(JSGlobalObject* globalObject, JSValue value) { return m_vm.throwException(globalObject, value); }
ALWAYS_INLINE void release() { }
+
+ ALWAYS_INLINE void clearException() { m_vm.clearException(); }
};
#define DECLARE_THROW_SCOPE(vm__) \
Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssembly.cpp (271765 => 271766)
--- trunk/Source/_javascript_Core/wasm/js/JSWebAssembly.cpp 2021-01-23 00:04:44 UTC (rev 271765)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssembly.cpp 2021-01-23 00:07:28 UTC (rev 271766)
@@ -119,69 +119,33 @@
{
}
-static void reject(JSGlobalObject* globalObject, CatchScope& catchScope, JSPromise* promise)
-{
- VM& vm = globalObject->vm();
- Exception* exception = catchScope.exception();
- ASSERT(exception);
- if (UNLIKELY(isTerminatedExecutionException(vm, exception)))
- return;
- catchScope.clearException();
- promise->reject(globalObject, exception->value());
-}
-
-static void webAssemblyModuleValidateAsyncInternal(JSGlobalObject* globalObject, JSPromise* promise, Vector<uint8_t>&& source)
-{
- VM& vm = globalObject->vm();
-
- Vector<Strong<JSCell>> dependencies;
- dependencies.append(Strong<JSCell>(vm, globalObject));
-
- vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies));
-
- Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable {
- vm.deferredWorkTimer->scheduleWorkSoon(promise, [promise, globalObject, result = WTFMove(result), &vm] () mutable {
- auto scope = DECLARE_CATCH_SCOPE(vm);
- JSValue module = JSWebAssemblyModule::createStub(vm, globalObject, globalObject->webAssemblyModuleStructure(), WTFMove(result));
- if (UNLIKELY(scope.exception())) {
- reject(globalObject, scope, promise);
- return;
- }
-
- promise->resolve(globalObject, module);
- CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
- });
- }));
-}
-
JSC_DEFINE_HOST_FUNCTION(webAssemblyCompileFunc, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
- auto throwScope = DECLARE_THROW_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
auto* promise = JSPromise::create(vm, globalObject->promiseStructure());
- RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
+ RETURN_IF_EXCEPTION(scope, { });
- {
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
- Vector<uint8_t> source = createSourceBufferFromValue(vm, globalObject, callFrame->argument(0));
+ Vector<uint8_t> source = createSourceBufferFromValue(vm, globalObject, callFrame->argument(0));
+ RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(globalObject, scope)));
- if (UNLIKELY(catchScope.exception()))
- reject(globalObject, catchScope, promise);
- else
- webAssemblyModuleValidateAsyncInternal(globalObject, promise, WTFMove(source));
-
- return JSValue::encode(promise);
- }
+ scope.release();
+ JSWebAssembly::webAssemblyModuleValidateAsync(globalObject, promise, WTFMove(source));
+ return JSValue::encode(promise);
}
enum class Resolve { WithInstance, WithModuleRecord, WithModuleAndInstance };
static void resolve(VM& vm, JSGlobalObject* globalObject, JSPromise* promise, JSWebAssemblyInstance* instance, JSWebAssemblyModule* module, JSObject* importObject, Ref<Wasm::CodeBlock>&& codeBlock, Resolve resolveKind, Wasm::CreationMode creationMode)
{
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
instance->finalizeCreation(vm, globalObject, WTFMove(codeBlock), importObject, creationMode);
- RETURN_IF_EXCEPTION(scope, reject(globalObject, scope, promise));
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
+ scope.release();
if (resolveKind == Resolve::WithInstance)
promise->resolve(globalObject, instance);
else if (resolveKind == Resolve::WithModuleRecord) {
@@ -195,23 +159,41 @@
result->putDirect(vm, Identifier::fromString(vm, "instance"_s), instance);
promise->resolve(globalObject, result);
}
- CLEAR_AND_RETURN_IF_EXCEPTION(scope, void());
}
void JSWebAssembly::webAssemblyModuleValidateAsync(JSGlobalObject* globalObject, JSPromise* promise, Vector<uint8_t>&& source)
{
VM& vm = globalObject->vm();
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
- webAssemblyModuleValidateAsyncInternal(globalObject, promise, WTFMove(source));
- CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, void());
+
+ Vector<Strong<JSCell>> dependencies;
+ dependencies.append(Strong<JSCell>(vm, globalObject));
+
+ vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies));
+
+ Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable {
+ vm.deferredWorkTimer->scheduleWorkSoon(promise, [promise, globalObject, result = WTFMove(result), &vm] () mutable {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSValue module = JSWebAssemblyModule::createStub(vm, globalObject, globalObject->webAssemblyModuleStructure(), WTFMove(result));
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
+
+ scope.release();
+ promise->resolve(globalObject, module);
+ });
+ }));
}
static void instantiate(VM& vm, JSGlobalObject* globalObject, JSPromise* promise, JSWebAssemblyModule* module, JSObject* importObject, const Identifier& moduleKey, Resolve resolveKind, Wasm::CreationMode creationMode)
{
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_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::tryCreate(vm, globalObject, moduleKey, module, importObject, globalObject->webAssemblyInstanceStructure(), Ref<Wasm::Module>(module->module()), creationMode);
- RETURN_IF_EXCEPTION(scope, reject(globalObject, scope, promise));
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
Vector<Strong<JSCell>> dependencies;
// The instance keeps the module alive.
@@ -230,7 +212,7 @@
static void compileAndInstantiate(VM& vm, JSGlobalObject* globalObject, JSPromise* promise, const Identifier& moduleKey, JSValue buffer, JSObject* importObject, Resolve resolveKind, Wasm::CreationMode creationMode)
{
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSCell* moduleKeyCell = identifierToJSValue(vm, moduleKey).asCell();
Vector<Strong<JSCell>> dependencies;
@@ -239,20 +221,31 @@
vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies));
Vector<uint8_t> source = createSourceBufferFromValue(vm, globalObject, buffer);
- RETURN_IF_EXCEPTION(scope, reject(globalObject, scope, promise));
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, importObject, moduleKeyCell, globalObject, resolveKind, creationMode, &vm] (Wasm::Module::ValidationResult&& result) mutable {
vm.deferredWorkTimer->scheduleWorkSoon(promise, [promise, importObject, moduleKeyCell, globalObject, result = WTFMove(result), resolveKind, creationMode, &vm] () mutable {
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, globalObject, globalObject->webAssemblyModuleStructure(), WTFMove(result));
- if (UNLIKELY(scope.exception()))
- return reject(globalObject, scope, promise);
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
const Identifier moduleKey = JSValue(moduleKeyCell).toPropertyKey(globalObject);
- if (UNLIKELY(scope.exception()))
- return reject(globalObject, scope, promise);
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
instantiate(vm, globalObject, promise, module, importObject, moduleKey, resolveKind, creationMode);
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
});
}));
}
@@ -264,7 +257,7 @@
return promise;
}
-static void webAssemblyModuleInstantinateAsyncInternal(JSGlobalObject* globalObject, JSPromise* promise, Vector<uint8_t>&& source, JSObject* importObject)
+void JSWebAssembly::webAssemblyModuleInstantinateAsync(JSGlobalObject* globalObject, JSPromise* promise, Vector<uint8_t>&& source, JSObject* importObject)
{
VM& vm = globalObject->vm();
@@ -275,49 +268,42 @@
Wasm::Module::validateAsync(&vm.wasmContext, WTFMove(source), createSharedTask<Wasm::Module::CallbackType>([promise, importObject, globalObject, &vm] (Wasm::Module::ValidationResult&& result) mutable {
vm.deferredWorkTimer->scheduleWorkSoon(promise, [promise, importObject, globalObject, result = WTFMove(result), &vm] () mutable {
- auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, globalObject, globalObject->webAssemblyModuleStructure(), WTFMove(result));
- if (UNLIKELY(scope.exception()))
- return reject(globalObject, scope, promise);
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
- instantiate(vm, globalObject, promise, module, importObject, JSWebAssemblyInstance::createPrivateModuleKey(), Resolve::WithModuleAndInstance, Wasm::CreationMode::FromJS);
- CLEAR_AND_RETURN_IF_EXCEPTION(scope, reject(globalObject, scope, promise));
+ JSC::instantiate(vm, globalObject, promise, module, importObject, JSWebAssemblyInstance::createPrivateModuleKey(), Resolve::WithModuleAndInstance, Wasm::CreationMode::FromJS);
+ if (UNLIKELY(scope.exception())) {
+ promise->rejectWithCaughtException(globalObject, scope);
+ return;
+ }
});
}));
}
-void JSWebAssembly::webAssemblyModuleInstantinateAsync(JSGlobalObject* globalObject, JSPromise* promise, Vector<uint8_t>&& source, JSObject* importedObject)
-{
- VM& vm = globalObject->vm();
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
- webAssemblyModuleInstantinateAsyncInternal(globalObject, promise, WTFMove(source), importedObject);
- CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, void());
-}
-
JSC_DEFINE_HOST_FUNCTION(webAssemblyInstantiateFunc, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
auto* promise = JSPromise::create(vm, globalObject->promiseStructure());
- {
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ JSValue importArgument = callFrame->argument(1);
+ JSObject* importObject = importArgument.getObject();
+ if (UNLIKELY(!importArgument.isUndefined() && !importObject)) {
+ promise->reject(globalObject, createTypeError(globalObject,
+ "second argument to WebAssembly.instantiate must be undefined or an Object"_s, defaultSourceAppender, runtimeTypeForValue(vm, importArgument)));
+ return JSValue::encode(promise);
+ }
- JSValue importArgument = callFrame->argument(1);
- JSObject* importObject = importArgument.getObject();
- if (UNLIKELY(!importArgument.isUndefined() && !importObject)) {
- promise->reject(globalObject, createTypeError(globalObject,
- "second argument to WebAssembly.instantiate must be undefined or an Object"_s, defaultSourceAppender, runtimeTypeForValue(vm, importArgument)));
- CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, JSValue::encode(promise));
- } else {
- JSValue firstArgument = callFrame->argument(0);
- if (auto* module = jsDynamicCast<JSWebAssemblyModule*>(vm, firstArgument))
- instantiate(vm, globalObject, promise, module, importObject, JSWebAssemblyInstance::createPrivateModuleKey(), Resolve::WithInstance, Wasm::CreationMode::FromJS);
- else
- compileAndInstantiate(vm, globalObject, promise, JSWebAssemblyInstance::createPrivateModuleKey(), firstArgument, importObject, Resolve::WithModuleAndInstance, Wasm::CreationMode::FromJS);
- }
+ JSValue firstArgument = callFrame->argument(0);
+ if (auto* module = jsDynamicCast<JSWebAssemblyModule*>(vm, firstArgument))
+ instantiate(vm, globalObject, promise, module, importObject, JSWebAssemblyInstance::createPrivateModuleKey(), Resolve::WithInstance, Wasm::CreationMode::FromJS);
+ else
+ compileAndInstantiate(vm, globalObject, promise, JSWebAssemblyInstance::createPrivateModuleKey(), firstArgument, importObject, Resolve::WithModuleAndInstance, Wasm::CreationMode::FromJS);
- return JSValue::encode(promise);
- }
+ return JSValue::encode(promise);
}
JSC_DEFINE_HOST_FUNCTION(webAssemblyValidateFunc, (JSGlobalObject* globalObject, CallFrame* callFrame))
@@ -336,7 +322,6 @@
JSC_DEFINE_HOST_FUNCTION(webAssemblyCompileStreamingInternal, (JSGlobalObject* globalObject, CallFrame* callFrame))
{
VM& vm = globalObject->vm();
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
auto* promise = JSPromise::create(vm, globalObject->promiseStructure());
@@ -344,15 +329,12 @@
dependencies.append(Strong<JSCell>(vm, globalObject));
vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies));
- if (globalObject->globalObjectMethodTable()->compileStreaming)
- globalObject->globalObjectMethodTable()->compileStreaming(globalObject, promise, callFrame->argument(0));
- else {
+ if (!globalObject->globalObjectMethodTable()->compileStreaming) {
// CompileStreaming is not supported in jsc, only in browser environment
ASSERT_NOT_REACHED();
}
- CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, JSValue::encode(promise));
-
+ globalObject->globalObjectMethodTable()->compileStreaming(globalObject, promise, callFrame->argument(0));
return JSValue::encode(promise);
}
@@ -361,33 +343,27 @@
VM& vm = globalObject->vm();
auto* promise = JSPromise::create(vm, globalObject->promiseStructure());
- {
- auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ JSValue importArgument = callFrame->argument(1);
+ JSObject* importObject = importArgument.getObject();
+ if (UNLIKELY(!importArgument.isUndefined() && !importObject)) {
+ promise->reject(globalObject, createTypeError(globalObject,
+ "second argument to WebAssembly.instantiateStreaming must be undefined or an Object"_s, defaultSourceAppender, runtimeTypeForValue(vm, importArgument)));
+ return JSValue::encode(promise);
+ }
- JSValue importArgument = callFrame->argument(1);
- JSObject* importObject = importArgument.getObject();
- if (UNLIKELY(!importArgument.isUndefined() && !importObject)) {
- promise->reject(globalObject, createTypeError(globalObject,
- "second argument to WebAssembly.instantiateStreaming must be undefined or an Object"_s, defaultSourceAppender, runtimeTypeForValue(vm, importArgument)));
- CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, JSValue::encode(promise));
- } else {
- if (globalObject->globalObjectMethodTable()->instantiateStreaming) {
- Vector<Strong<JSCell>> dependencies;
- dependencies.append(Strong<JSCell>(vm, globalObject));
- dependencies.append(Strong<JSCell>(vm, importObject));
- vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies));
+ if (!globalObject->globalObjectMethodTable()->instantiateStreaming) {
+ // InstantiateStreaming is not supported in jsc, only in browser environment.
+ ASSERT_NOT_REACHED();
+ }
- // FIXME: <http://webkit.org/b/184888> if there's an importObject and it contains a Memory, then we can compile the module with the right memory type (fast or not) by looking at the memory's type.
- globalObject->globalObjectMethodTable()->instantiateStreaming(globalObject, promise, callFrame->argument(0), importObject);
- } else {
- // InstantiateStreaming is not supported in jsc, only in browser environment.
- ASSERT_NOT_REACHED();
- }
- }
- CLEAR_AND_RETURN_IF_EXCEPTION(catchScope, JSValue::encode(promise));
+ Vector<Strong<JSCell>> dependencies;
+ dependencies.append(Strong<JSCell>(vm, globalObject));
+ dependencies.append(Strong<JSCell>(vm, importObject));
+ vm.deferredWorkTimer->addPendingWork(vm, promise, WTFMove(dependencies));
- return JSValue::encode(promise);
- }
+ // FIXME: <http://webkit.org/b/184888> if there's an importObject and it contains a Memory, then we can compile the module with the right memory type (fast or not) by looking at the memory's type.
+ globalObject->globalObjectMethodTable()->instantiateStreaming(globalObject, promise, callFrame->argument(0), importObject);
+ return JSValue::encode(promise);
}
} // namespace JSC