Ignore:
Timestamp:
Nov 19, 2018, 11:09:53 PM (7 years ago)
Author:
[email protected]
Message:

globalFuncImportModule() should return a promise when it clears exceptions.
https://bugs.webkit.org/show_bug.cgi?id=191792
<rdar://problem/46090763>

Reviewed by Michael Saboff.

JSTests:

  • stress/global-import-function-should-return-a-promise-when-clearing-exceptions.js: Added.

Source/JavaScriptCore:

If we're clearing the exceptions in a CatchScope, then it means that we've handled
the exception, and is able to proceed in a normal manner. Hence, we should not
return the empty JSValue in this case: instead, we should return a Promise as
expected by import's API.

The only time when we can't return a promise is when we fail to create a Promise.
In that case, we should be propagating the exception.

Hence, globalFuncImportModule() contains a ThrowScope (for propagating the
exception that arises from failure to create the Promise) wrapping a CatchScope
(for catching any exception that arises from failure to execute the import).

Also fixed similar issues, and some exception check issues in JSModuleLoader and
the jsc shell.

  • jsc.cpp:

(GlobalObject::moduleLoaderImportModule):
(GlobalObject::moduleLoaderFetch):

  • runtime/JSGlobalObjectFunctions.cpp:

(JSC::globalFuncImportModule):

  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::loadAndEvaluateModule):
(JSC::JSModuleLoader::loadModule):
(JSC::JSModuleLoader::requestImportModule):
(JSC::JSModuleLoader::importModule):
(JSC::JSModuleLoader::resolve):
(JSC::JSModuleLoader::fetch):
(JSC::moduleLoaderParseModule):
(JSC::moduleLoaderResolveSync):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/jsc.cpp

    r237823 r238391  
    802802{
    803803    VM& vm = globalObject->vm();
    804     auto scope = DECLARE_CATCH_SCOPE(vm);
    805 
    806     auto rejectPromise = [&] (JSValue error) {
    807         return JSInternalPromiseDeferred::create(exec, globalObject)->reject(exec, error);
     804    auto throwScope = DECLARE_THROW_SCOPE(vm);
     805
     806    auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     807    RETURN_IF_EXCEPTION(throwScope, nullptr);
     808
     809    auto catchScope = DECLARE_CATCH_SCOPE(vm);
     810    auto reject = [&] (JSValue rejectionReason) {
     811        catchScope.clearException();
     812        auto result = deferred->reject(exec, rejectionReason);
     813        catchScope.clearException();
     814        return result;
    808815    };
    809816
    810817    if (sourceOrigin.isNull())
    811         return rejectPromise(createError(exec, "Could not resolve the module specifier."_s));
     818        return reject(createError(exec, "Could not resolve the module specifier."_s));
    812819
    813820    auto referrer = sourceOrigin.string();
    814821    auto moduleName = moduleNameValue->value(exec);
    815     if (UNLIKELY(scope.exception())) {
    816         JSValue exception = scope.exception();
    817         scope.clearException();
    818         return rejectPromise(exception);
    819     }
     822    if (UNLIKELY(catchScope.exception()))
     823        return reject(catchScope.exception());
    820824
    821825    auto directoryName = extractDirectoryName(referrer.impl());
    822826    if (!directoryName)
    823         return rejectPromise(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
     827        return reject(createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
    824828
    825829    auto result = JSC::importModule(exec, Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(moduleName))), parameters, jsUndefined());
    826     scope.releaseAssertNoException();
     830    if (UNLIKELY(catchScope.exception()))
     831        return reject(catchScope.exception());
    827832    return result;
    828833}
     
    992997{
    993998    VM& vm = globalObject->vm();
    994     auto scope = DECLARE_CATCH_SCOPE(vm);
     999    auto throwScope = DECLARE_THROW_SCOPE(vm);
    9951000    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     1001    RETURN_IF_EXCEPTION(throwScope, nullptr);
     1002
     1003    auto catchScope = DECLARE_CATCH_SCOPE(vm);
     1004    auto reject = [&] (JSValue rejectionReason) {
     1005        catchScope.clearException();
     1006        auto result = deferred->reject(exec, rejectionReason);
     1007        catchScope.clearException();
     1008        return result;
     1009    };
     1010
    9961011    String moduleKey = key.toWTFString(exec);
    997     if (UNLIKELY(scope.exception())) {
    998         JSValue exception = scope.exception();
    999         scope.clearException();
    1000         return deferred->reject(exec, exception);
    1001     }
     1012    if (UNLIKELY(catchScope.exception()))
     1013        return reject(catchScope.exception());
    10021014
    10031015    // Here, now we consider moduleKey as the fileName.
    10041016    Vector<uint8_t> buffer;
    1005     if (!fetchModuleFromLocalFileSystem(moduleKey, buffer)) {
    1006         auto result = deferred->reject(exec, createError(exec, makeString("Could not open file '", moduleKey, "'.")));
    1007         scope.releaseAssertNoException();
    1008         return result;
    1009     }
     1017    if (!fetchModuleFromLocalFileSystem(moduleKey, buffer))
     1018        return reject(createError(exec, makeString("Could not open file '", moduleKey, "'.")));
    10101019
    10111020#if ENABLE(WEBASSEMBLY)
     
    10131022    if (buffer.size() >= 4) {
    10141023        if (buffer[0] == '\0' && buffer[1] == 'a' && buffer[2] == 's' && buffer[3] == 'm') {
    1015             auto result = deferred->resolve(exec, JSSourceCode::create(vm, SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleKey }, moduleKey))));
    1016             scope.releaseAssertNoException();
     1024            auto source = SourceCode(WebAssemblySourceProvider::create(WTFMove(buffer), SourceOrigin { moduleKey }, moduleKey));
     1025            catchScope.releaseAssertNoException();
     1026            auto sourceCode = JSSourceCode::create(vm, WTFMove(source));
     1027            catchScope.releaseAssertNoException();
     1028            auto result = deferred->resolve(exec, sourceCode);
     1029            catchScope.clearException();
    10171030            return result;
    10181031        }
     
    10201033#endif
    10211034
    1022     auto result = deferred->resolve(exec, JSSourceCode::create(vm, makeSource(stringFromUTF(buffer), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module)));
    1023     scope.releaseAssertNoException();
     1035    auto sourceCode = JSSourceCode::create(vm, makeSource(stringFromUTF(buffer), SourceOrigin { moduleKey }, moduleKey, TextPosition(), SourceProviderSourceType::Module));
     1036    catchScope.releaseAssertNoException();
     1037    auto result = deferred->resolve(exec, sourceCode);
     1038    catchScope.clearException();
    10241039    return result;
    10251040}
Note: See TracChangeset for help on using the changeset viewer.