Ignore:
Timestamp:
Oct 15, 2017, 6:55:16 PM (8 years ago)
Author:
Yusuke Suzuki
Message:

[JSC] Perform module specifier validation at parsing time
https://bugs.webkit.org/show_bug.cgi?id=178256

Reviewed by Darin Adler.

Source/JavaScriptCore:

This patch make module loader's resolve operation synchronous. And we validate
module's requested module names when instantiating the module instead of satisfying
module's dependencies. This change is not observable to users. But this is precise
to the spec and this optimizes & simplifies the current module loader a bit by
reducing object allocations.

Previously, we have an object called pair in the module loader. This is pair of
module's name and module's record. And we use it to link one module to dependent
modules. Now, it is replaced with module's registry entry.

We also change our loader functions to take a registry entry instead of a module key.
Previous design is due to the consideration that these APIs may be exposed to users
in whatwg/loader spec. However, this won't happen. This change removes unnecessary
repeatedly hash map lookups.

  • builtins/ModuleLoaderPrototype.js:

(globalPrivate.newRegistryEntry):
(requestFetch):
(requestInstantiate):
(requestSatisfy):
(link):
(moduleEvaluation):
(loadModule):

  • jsc.cpp:

(GlobalObject::moduleLoaderResolve):

  • runtime/AbstractModuleRecord.cpp:

(JSC::AbstractModuleRecord::finishCreation):
(JSC::AbstractModuleRecord::hostResolveImportedModule):

  • runtime/JSGlobalObject.h:
  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::resolveSync):
(JSC::JSModuleLoader::resolve):

  • runtime/JSModuleLoader.h:
  • runtime/ModuleLoaderPrototype.cpp:

(JSC::moduleLoaderPrototypeResolveSync):

Source/WebCore:

No behavior change in the current implementation.

  • bindings/js/JSDOMWindowBase.cpp:

(WebCore::JSDOMWindowBase::moduleLoaderResolve):

  • bindings/js/JSDOMWindowBase.h:
  • bindings/js/ScriptModuleLoader.cpp:

(WebCore::ScriptModuleLoader::resolve):

  • bindings/js/ScriptModuleLoader.h:
File:
1 edited

Legend:

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

    r223237 r223331  
    16591659
    16601660    static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, JSValue, const SourceOrigin&);
    1661     static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
     1661    static Identifier moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
    16621662    static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
    16631663    static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue);
     
    18411841}
    18421842
    1843 JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
     1843Identifier GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
    18441844{
    18451845    VM& vm = globalObject->vm();
    1846     auto scope = DECLARE_CATCH_SCOPE(vm);
    1847 
    1848     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
     1846    auto scope = DECLARE_THROW_SCOPE(vm);
     1847
    18491848    scope.releaseAssertNoException();
    18501849    const Identifier key = keyValue.toPropertyKey(exec);
    1851     if (UNLIKELY(scope.exception())) {
    1852         JSValue exception = scope.exception();
    1853         scope.clearException();
    1854         return deferred->reject(exec, exception);
    1855     }
    1856 
    1857     if (key.isSymbol()) {
    1858         auto result = deferred->resolve(exec, keyValue);
    1859         scope.releaseAssertNoException();
    1860         return result;
    1861     }
     1850    RETURN_IF_EXCEPTION(scope, { });
     1851
     1852    if (key.isSymbol())
     1853        return key;
     1854
    18621855    if (referrerValue.isUndefined()) {
    18631856        auto directoryName = currentWorkingDirectory();
    1864         if (!directoryName)
    1865             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
    1866         auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
    1867         scope.releaseAssertNoException();
    1868         return result;
     1857        if (!directoryName) {
     1858            throwException(exec, scope, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
     1859            return { };
     1860        }
     1861        return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
    18691862    }
    18701863
    18711864    const Identifier referrer = referrerValue.toPropertyKey(exec);
    1872     if (UNLIKELY(scope.exception())) {
    1873         JSValue exception = scope.exception();
    1874         scope.clearException();
    1875         return deferred->reject(exec, exception);
    1876     }
     1865    RETURN_IF_EXCEPTION(scope, { });
    18771866
    18781867    if (referrer.isSymbol()) {
    18791868        auto directoryName = currentWorkingDirectory();
    1880         if (!directoryName)
    1881             return deferred->reject(exec, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
    1882         auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
    1883         scope.releaseAssertNoException();
    1884         return result;
     1869        if (!directoryName) {
     1870            throwException(exec, scope, createError(exec, ASCIILiteral("Could not resolve the current working directory.")));
     1871            return { };
     1872        }
     1873        return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
    18851874    }
    18861875
    18871876    // If the referrer exists, we assume that the referrer is the correct absolute path.
    18881877    auto directoryName = extractDirectoryName(referrer.impl());
    1889     if (!directoryName)
    1890         return deferred->reject(exec, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
    1891     auto result = deferred->resolve(exec, jsString(exec, resolvePath(directoryName.value(), ModuleName(key.impl()))));
    1892     scope.releaseAssertNoException();
    1893     return result;
     1878    if (!directoryName) {
     1879        throwException(exec, scope, createError(exec, makeString("Could not resolve the referrer name '", String(referrer.impl()), "'.")));
     1880        return { };
     1881    }
     1882    return Identifier::fromString(&vm, resolvePath(directoryName.value(), ModuleName(key.impl())));
    18941883}
    18951884
Note: See TracChangeset for help on using the changeset viewer.