Changeset 247403 in webkit


Ignore:
Timestamp:
Jul 12, 2019 3:15:55 PM (5 years ago)
Author:
keith_miller@apple.com
Message:

Add API to get all the dependencies of a given JSScript
https://bugs.webkit.org/show_bug.cgi?id=199746

Reviewed by Saam Barati.

The method only returns the dependencies if the module was
actually evaluated. Technically, we know what the dependencies are
at the satisfy phase but for API simplicity we only provide that
information if the module graph was complete enough to at least
run.

This patch also fixes an issue where we would allow import
specifiers that didn't start "./" or "/". For reference, We have
this restriction to be consistent with the web/node. The
restriction exists in order to preserve namespace for
builtin-modules.

Lastly, this patch makes it so that we copy all scripts in the
API/tests/testapiScripts directory so they don't have to be
individually added to the xcode project.

  • API/JSAPIGlobalObject.mm:

(JSC::computeValidImportSpecifier):
(JSC::JSAPIGlobalObject::moduleLoaderResolve):
(JSC::JSAPIGlobalObject::moduleLoaderImportModule):

  • API/JSContext.mm:

(-[JSContext dependencyIdentifiersForModuleJSScript:]):

  • API/JSContextPrivate.h:
  • API/JSScript.h:
  • API/tests/testapi.mm:

(testFetchWithTwoCycle):
(testFetchWithThreeCycle):
(testModuleBytecodeCache):
(+[JSContextFileLoaderDelegate newContext]):
(-[JSContextFileLoaderDelegate fetchModuleScript:]):
(-[JSContextFileLoaderDelegate findScriptForKey:]):
(-[JSContextFileLoaderDelegate context:fetchModuleForIdentifier:withResolveHandler:andRejectHandler:]):
(testDependenciesArray):
(testDependenciesEvaluationError):
(testDependenciesSyntaxError):
(testDependenciesBadImportId):
(testDependenciesMissingImport):
(testObjectiveCAPI):

  • API/tests/testapiScripts/dependencyListTests/badModuleImportId.js: Added.
  • API/tests/testapiScripts/dependencyListTests/bar.js: Added.
  • API/tests/testapiScripts/dependencyListTests/dependenciesEntry.js: Added.
  • API/tests/testapiScripts/dependencyListTests/foo.js: Added.
  • API/tests/testapiScripts/dependencyListTests/missingImport.js: Added.
  • API/tests/testapiScripts/dependencyListTests/referenceError.js: Added.
  • API/tests/testapiScripts/dependencyListTests/syntaxError.js: Added.
  • API/tests/testapiScripts/testapi-function-overrides.js: Renamed from Source/JavaScriptCore/API/tests/testapi-function-overrides.js.
  • API/tests/testapiScripts/testapi.js: Renamed from Source/JavaScriptCore/API/tests/testapi.js.
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • builtins/ModuleLoader.js:

(dependencyKeysIfEvaluated):

  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::dependencyKeysIfEvaluated):

  • runtime/JSModuleLoader.h:
  • shell/CMakeLists.txt:
Location:
trunk/Source/JavaScriptCore
Files:
8 added
11 edited
2 moved

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/API/JSAPIGlobalObject.mm

    r244620 r247403  
    7070};
    7171
     72static Expected<URL, String> computeValidImportSpecifier(const URL& base, const String& specifier)
     73{
     74    URL absoluteURL(URL(), specifier);
     75    if (absoluteURL.isValid())
     76        return absoluteURL;
     77
     78    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
     79        return makeUnexpected(makeString("Module specifier: "_s, specifier, " does not start with \"/\", \"./\", or \"../\"."_s));
     80
     81    if (specifier.startsWith('/')) {
     82        absoluteURL = URL(URL({ }, "file://"), specifier);
     83        if (absoluteURL.isValid())
     84            return absoluteURL;
     85    }
     86
     87    if (base == URL())
     88        return makeUnexpected("Could not determine the base URL for loading."_s);
     89
     90    if (!base.isValid())
     91        return makeUnexpected(makeString("Referrering script's url is not valid: "_s, base.string()));
     92
     93    absoluteURL = URL(base, specifier);
     94    if (absoluteURL.isValid())
     95        return absoluteURL;
     96    return makeUnexpected(makeString("Could not form valid URL from identifier and base. Tried:"_s, absoluteURL.string()));
     97}
     98
    7299Identifier JSAPIGlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue referrer, JSValue)
    73100{
     
    77104    ASSERT(key.isString() || key.isSymbol());
    78105    String name =  key.toWTFString(exec);
    79 
     106    RETURN_IF_EXCEPTION(scope, { });
     107
     108    URL base;
    80109    if (JSString* referrerString = jsDynamicCast<JSString*>(vm, referrer)) {
    81110        String value = referrerString->value(exec);
     111        RETURN_IF_EXCEPTION(scope, { });
    82112        URL referrerURL({ }, value);
    83         RETURN_IF_EXCEPTION(scope, { });
    84113        RELEASE_ASSERT(referrerURL.isValid());
    85 
    86         URL url = URL(referrerURL, name);
    87         if (url.isValid())
    88             return Identifier::fromString(exec, url);
    89     } else {
    90         URL url = URL({ }, name);
    91         if (url.isValid())
    92             return Identifier::fromString(exec, url);
    93     }
    94 
    95     throwVMError(exec, scope, "Could not form valid URL from identifier and base"_s);
     114        base = WTFMove(referrerURL);
     115    }
     116
     117    auto result = computeValidImportSpecifier(base, name);
     118    if (result)
     119        return Identifier::fromString(&vm, result.value());
     120
     121    throwVMError(exec, scope, createError(exec, result.error()));
    96122    return { };
    97123}
     
    122148    }
    123149
    124     URL absoluteURL(URL(), specifier);
    125     if (absoluteURL.isValid())
    126         return import(absoluteURL);
    127 
    128     if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
    129         return reject(createError(exec, makeString("Module specifier: ", specifier, " does not start with \"/\", \"./\", or \"../\"."_s)));
    130 
    131     if (specifier.startsWith('/')) {
    132         absoluteURL = URL(URL({ }, "file://"), specifier);
    133         if (absoluteURL.isValid())
    134             return import(absoluteURL);
    135     }
    136 
    137     auto noBaseErrorMessage = "Could not determine the base URL for loading."_s;
    138     if (sourceOrigin.isNull())
    139         return reject(createError(exec, makeString(noBaseErrorMessage, " Referring script has no URL."_s)));
    140 
    141     auto referrer = sourceOrigin.string();
     150    String referrer = !sourceOrigin.isNull() ? sourceOrigin.string() : String();
    142151    URL baseURL(URL(), referrer);
    143     if (!baseURL.isValid())
    144         return reject(createError(exec, makeString(noBaseErrorMessage, " Referring script's URL is not valid: "_s, baseURL.string())));
    145 
    146     URL url(baseURL, specifier);
    147     if (!url.isValid())
    148         return reject(createError(exec, makeString("could not determine a valid URL for module specifier. Tried: "_s, url.string())));
    149 
    150     return import(url);
     152    auto result = computeValidImportSpecifier(baseURL, specifier);
     153    if (result)
     154        return import(result.value());
     155    return reject(createError(exec, result.error()));
    151156}
    152157
  • trunk/Source/JavaScriptCore/API/JSContext.mm

    r247346 r247403  
    147147}
    148148
     149- (JSValue *)dependencyIdentifiersForModuleJSScript:(JSScript *)script
     150{
     151    JSC::ExecState* exec = toJS(m_context);
     152    JSC::VM& vm = exec->vm();
     153    JSC::JSLockHolder locker(vm);
     154
     155    if (script.type != kJSScriptTypeModule) {
     156        self.exceptionHandler(self, [JSValue valueWithNewErrorFromMessage:@"script is not a module" inContext:self]);
     157        return [JSValue valueWithUndefinedInContext:self];
     158    }
     159
     160    auto scope = DECLARE_CATCH_SCOPE(vm);
     161    JSC::JSArray* result = exec->lexicalGlobalObject()->moduleLoader()->dependencyKeysIfEvaluated(exec, JSC::jsString(&vm, [[script sourceURL] absoluteString]));
     162    if (scope.exception()) {
     163        JSValueRef exceptionValue = toRef(exec, scope.exception()->value());
     164        scope.clearException();
     165        return [self valueFromNotifyException:exceptionValue];
     166    }
     167
     168    if (!result) {
     169        self.exceptionHandler(self, [JSValue valueWithNewErrorFromMessage:@"script has not run in context or was not evaluated successfully" inContext:self]);
     170        return [JSValue valueWithUndefinedInContext:self];
     171    }
     172    return [JSValue valueWithJSValueRef:toRef(vm, result) inContext:self];
     173}
     174
    149175- (void)setException:(JSValue *)value
    150176{
  • trunk/Source/JavaScriptCore/API/JSContextPrivate.h

    r244620 r247403  
    8585
    8686/*! @abstract The delegate the context will use when trying to load a module. Note, this delegate will be ignored for contexts returned by UIWebView. */
    87 @property (nonatomic, weak) id <JSModuleLoaderDelegate> moduleLoaderDelegate JSC_API_AVAILABLE(macos(JSC_MAC_TBA), ios(JSC_IOS_TBA));
     87@property (nonatomic, weak) id <JSModuleLoaderDelegate> moduleLoaderDelegate JSC_API_AVAILABLE(macos(10.15), ios(13.0));
    8888
    8989/*!
     
    9595 Otherwise, if the script was created with kJSScriptTypeModule, the module will be run asynchronously and will return a promise resolved when the module and any transitive dependencies are loaded. The module loader will treat the script as if it had been returned from a delegate call to moduleLoaderDelegate. This mirrors the JavaScript dynamic import operation.
    9696 */
    97 - (JSValue *)evaluateJSScript:(JSScript *)script;
     97// FIXME: Before making this public need to fix: https://bugs.webkit.org/show_bug.cgi?id=199714
     98- (JSValue *)evaluateJSScript:(JSScript *)script JSC_API_AVAILABLE(macos(10.15), ios(13.0));
     99
     100/*!
     101 @method
     102 @abstract Get the identifiers of the modules a JSScript depends on in this context.
     103 @param script the JSScript to determine the dependencies of.
     104 @result An Array containing all the identifiers of modules script depends on.
     105 @discussion If the provided JSScript was not created with kJSScriptTypeModule, an exception will be thrown. Also, if the script has not already been evaluated in this context an error will be throw.
     106 */
     107- (JSValue *)dependencyIdentifiersForModuleJSScript:(JSScript *)script JSC_API_AVAILABLE(macos(10.15), ios(13.0));
    98108
    99109@end
  • trunk/Source/JavaScriptCore/API/JSScript.h

    r244401 r247403  
    4444
    4545
    46 JSC_CLASS_AVAILABLE(macos(JSC_MAC_TBA), ios(JSC_IOS_TBA))
     46JSC_CLASS_AVAILABLE(macos(10.15), ios(13.0))
    4747@interface JSScript : NSObject
    4848
  • trunk/Source/JavaScriptCore/API/tests/testapi.mm

    r246265 r247403  
    19471947            } else if ([identifier isEqualToObject:@"file:///foo.js"]) {
    19481948                [resolve callWithArguments:@[[JSScript scriptOfType:kJSScriptTypeModule
    1949                     withSource:@"import \"directory/bar.js\"; globalThis.ran = null; export let n = null;"
     1949                    withSource:@"import \"./directory/bar.js\"; globalThis.ran = null; export let n = null;"
    19501950                    andSourceURL:[NSURL fileURLWithPath:@"/foo.js"]
    19511951                    andBytecodeCache:nil
     
    19781978            } else if ([identifier isEqualToObject:@"file:///foo.js"]) {
    19791979                [resolve callWithArguments:@[[JSScript scriptOfType:kJSScriptTypeModule
    1980                     withSource:@"import \"otherDirectory/baz.js\"; export let n = null;"
     1980                    withSource:@"import \"./otherDirectory/baz.js\"; export let n = null;"
    19811981                    andSourceURL:[NSURL fileURLWithPath:@"/foo.js"]
    19821982                    andBytecodeCache:nil
     
    21082108{
    21092109    @autoreleasepool {
    2110         NSString *fooSource = @"import 'otherDirectory/baz.js'; export let n = null;";
     2110        NSString *fooSource = @"import './otherDirectory/baz.js'; export let n = null;";
    21112111        NSString *barSource = @"import { n } from '../foo.js'; export let foo = () => n;";
    21122112        NSString *bazSource = @"import { foo } from '../directory/bar.js'; globalThis.ran = null; export let exp = foo();";
     
    24292429
    24302430+ (instancetype)newContext;
     2431- (JSScript *)fetchModuleScript:(NSString *)relativePath;
    24312432
    24322433@end
    24332434
    24342435@implementation JSContextFileLoaderDelegate {
     2436    NSMutableDictionary<NSString *, JSScript *> *m_keyToScript;
    24352437}
    24362438
     
    24382440{
    24392441    auto *result = [[JSContextFileLoaderDelegate alloc] init];
     2442    result.moduleLoaderDelegate = result;
     2443    result->m_keyToScript = [[NSMutableDictionary<NSString *, JSScript *> alloc] init];
    24402444    return result;
    24412445}
     
    24602464}
    24612465
     2466- (JSScript *)fetchModuleScript:(NSString *)relativePath
     2467{
     2468    auto *filePath = [NSURL URLWithString:relativePath relativeToURL:resolvePathToScripts()];
     2469    if (auto *script = [self findScriptForKey:[filePath absoluteString]])
     2470        return script;
     2471    NSError *error;
     2472    auto *result = [JSScript scriptOfType:kJSScriptTypeModule memoryMappedFromASCIIFile:filePath withSourceURL:filePath andBytecodeCache:nil inVirtualMachine:[self virtualMachine] error:&error];
     2473    if (!result) {
     2474        NSLog(@"%@\n", error);
     2475        CRASH();
     2476    }
     2477    [m_keyToScript setObject:result forKey:[filePath absoluteString]];
     2478    return result;
     2479}
     2480
     2481- (JSScript *)findScriptForKey:(NSString *)key
     2482{
     2483    return [m_keyToScript objectForKey:key];
     2484}
     2485
    24622486- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject
    24632487{
    24642488    NSURL *filePath = [NSURL URLWithString:[identifier toString]];
     2489    // FIXME: We should fix this: https://bugs.webkit.org/show_bug.cgi?id=199714
     2490    if (auto *script = [self findScriptForKey:[identifier toString]]) {
     2491        [resolve callWithArguments:@[script]];
     2492        return;
     2493    }
     2494
    24652495    auto* script = [JSScript scriptOfType:kJSScriptTypeModule
    24662496        memoryMappedFromASCIIFile:filePath
     
    24692499        inVirtualMachine:context.virtualMachine
    24702500        error:nil];
    2471     if (script)
     2501    if (script) {
     2502        [m_keyToScript setObject:script forKey:[identifier toString]];
    24722503        [resolve callWithArguments:@[script]];
    2473     else
     2504    } else
    24742505        [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Unable to create Script" inContext:context]]];
    24752506}
     
    26052636}
    26062637
     2638static void testDependenciesArray()
     2639{
     2640    @autoreleasepool {
     2641        auto *context = [JSContextFileLoaderDelegate newContext];
     2642
     2643        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/dependenciesEntry.js"];
     2644
     2645        JSValue *promise = [context evaluateJSScript:entryScript];
     2646        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
     2647            checkResult(@"module ran successfully", true);
     2648        }, ^(JSValue *) {
     2649            checkResult(@"module ran successfully", false);
     2650        }]];
     2651
     2652        checkResult(@"looking up the entry script should find the same script again.", [context findScriptForKey:[entryScript.sourceURL absoluteString]] == entryScript);
     2653
     2654        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
     2655
     2656        checkResult(@"deps should be an array", [deps isArray]);
     2657        checkResult(@"deps should have two entries", [deps[@"length"] isEqualToObject:@(2)]);
     2658
     2659        checkResult(@"first dependency should be foo.js", [[[[context fetchModuleScript:@"./dependencyListTests/foo.js"] sourceURL] absoluteString] isEqual:[deps[@(0)] toString]]);
     2660        checkResult(@"second dependency should be bar.js", [[[[context fetchModuleScript:@"./dependencyListTests/bar.js"] sourceURL] absoluteString] isEqual:[deps[@(1)] toString]]);
     2661    }
     2662}
     2663
     2664static void testDependenciesEvaluationError()
     2665{
     2666    @autoreleasepool {
     2667        auto *context = [JSContextFileLoaderDelegate newContext];
     2668
     2669        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/referenceError.js"];
     2670
     2671        JSValue *promise = [context evaluateJSScript:entryScript];
     2672        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
     2673            checkResult(@"module failed successfully", false);
     2674        }, ^(JSValue *) {
     2675            checkResult(@"module failed successfully", true);
     2676        }]];
     2677
     2678        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
     2679        checkResult(@"deps should be an Array", [deps isArray]);
     2680        checkResult(@"first dependency should be foo.js", [[[[context fetchModuleScript:@"./dependencyListTests/foo.js"] sourceURL] absoluteString] isEqual:[deps[@(0)] toString]]);
     2681    }
     2682}
     2683
     2684static void testDependenciesSyntaxError()
     2685{
     2686    @autoreleasepool {
     2687        auto *context = [JSContextFileLoaderDelegate newContext];
     2688
     2689        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/syntaxError.js"];
     2690
     2691        JSValue *promise = [context evaluateJSScript:entryScript];
     2692        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
     2693            checkResult(@"module failed successfully", false);
     2694        }, ^(JSValue *) {
     2695            checkResult(@"module failed successfully", true);
     2696        }]];
     2697
     2698        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
     2699        checkResult(@"deps should be undefined", [deps isUndefined]);
     2700        checkResult(@"there should be a pending exception on the context", context.exception);
     2701    }
     2702}
     2703
     2704static void testDependenciesBadImportId()
     2705{
     2706    @autoreleasepool {
     2707        auto *context = [JSContextFileLoaderDelegate newContext];
     2708
     2709        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/badModuleImportId.js"];
     2710
     2711        JSValue *promise = [context evaluateJSScript:entryScript];
     2712        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
     2713            checkResult(@"module failed successfully", false);
     2714        }, ^(JSValue *) {
     2715            checkResult(@"module failed successfully", true);
     2716        }]];
     2717
     2718        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
     2719        checkResult(@"deps should be undefined", [deps isUndefined]);
     2720        checkResult(@"there should be a pending exception on the context", context.exception);
     2721    }
     2722}
     2723
     2724static void testDependenciesMissingImport()
     2725{
     2726    @autoreleasepool {
     2727        auto *context = [JSContextFileLoaderDelegate newContext];
     2728
     2729        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/missingImport.js"];
     2730
     2731        JSValue *promise = [context evaluateJSScript:entryScript];
     2732        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
     2733            checkResult(@"module failed successfully", false);
     2734        }, ^(JSValue *) {
     2735            checkResult(@"module failed successfully", true);
     2736        }]];
     2737
     2738        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
     2739        checkResult(@"deps should be undefined", [deps isUndefined]);
     2740        checkResult(@"there should be a pending exception on the context", context.exception);
     2741    }
     2742}
    26072743
    26082744@protocol ToString <JSExport>
     
    27092845    RUN(testLoadBasicFile());
    27102846
     2847    RUN(testDependenciesArray());
     2848    RUN(testDependenciesSyntaxError());
     2849    RUN(testDependenciesEvaluationError());
     2850    RUN(testDependenciesBadImportId());
     2851    RUN(testDependenciesMissingImport());
     2852
    27112853    RUN(promiseWithExecutor(Resolution::ResolveEager));
    27122854    RUN(promiseWithExecutor(Resolution::RejectEager));
  • trunk/Source/JavaScriptCore/ChangeLog

    r247390 r247403  
     12019-07-12  Keith Miller  <keith_miller@apple.com>
     2
     3        Add API to get all the dependencies of a given JSScript
     4        https://bugs.webkit.org/show_bug.cgi?id=199746
     5
     6        Reviewed by Saam Barati.
     7
     8        The method only returns the dependencies if the module was
     9        actually evaluated. Technically, we know what the dependencies are
     10        at the satisfy phase but for API simplicity we only provide that
     11        information if the module graph was complete enough to at least
     12        run.
     13
     14        This patch also fixes an issue where we would allow import
     15        specifiers that didn't start "./" or "/". For reference, We have
     16        this restriction to be consistent with the web/node. The
     17        restriction exists in order to preserve namespace for
     18        builtin-modules.
     19
     20        Lastly, this patch makes it so that we copy all scripts in the
     21        API/tests/testapiScripts directory so they don't have to be
     22        individually added to the xcode project.
     23
     24        * API/JSAPIGlobalObject.mm:
     25        (JSC::computeValidImportSpecifier):
     26        (JSC::JSAPIGlobalObject::moduleLoaderResolve):
     27        (JSC::JSAPIGlobalObject::moduleLoaderImportModule):
     28        * API/JSContext.mm:
     29        (-[JSContext dependencyIdentifiersForModuleJSScript:]):
     30        * API/JSContextPrivate.h:
     31        * API/JSScript.h:
     32        * API/tests/testapi.mm:
     33        (testFetchWithTwoCycle):
     34        (testFetchWithThreeCycle):
     35        (testModuleBytecodeCache):
     36        (+[JSContextFileLoaderDelegate newContext]):
     37        (-[JSContextFileLoaderDelegate fetchModuleScript:]):
     38        (-[JSContextFileLoaderDelegate findScriptForKey:]):
     39        (-[JSContextFileLoaderDelegate context:fetchModuleForIdentifier:withResolveHandler:andRejectHandler:]):
     40        (testDependenciesArray):
     41        (testDependenciesEvaluationError):
     42        (testDependenciesSyntaxError):
     43        (testDependenciesBadImportId):
     44        (testDependenciesMissingImport):
     45        (testObjectiveCAPI):
     46        * API/tests/testapiScripts/dependencyListTests/badModuleImportId.js: Added.
     47        * API/tests/testapiScripts/dependencyListTests/bar.js: Added.
     48        * API/tests/testapiScripts/dependencyListTests/dependenciesEntry.js: Added.
     49        * API/tests/testapiScripts/dependencyListTests/foo.js: Added.
     50        * API/tests/testapiScripts/dependencyListTests/missingImport.js: Added.
     51        * API/tests/testapiScripts/dependencyListTests/referenceError.js: Added.
     52        * API/tests/testapiScripts/dependencyListTests/syntaxError.js: Added.
     53        * API/tests/testapiScripts/testapi-function-overrides.js: Renamed from Source/JavaScriptCore/API/tests/testapi-function-overrides.js.
     54        * API/tests/testapiScripts/testapi.js: Renamed from Source/JavaScriptCore/API/tests/testapi.js.
     55        * JavaScriptCore.xcodeproj/project.pbxproj:
     56        * builtins/ModuleLoader.js:
     57        (dependencyKeysIfEvaluated):
     58        * runtime/JSModuleLoader.cpp:
     59        (JSC::JSModuleLoader::dependencyKeysIfEvaluated):
     60        * runtime/JSModuleLoader.h:
     61        * shell/CMakeLists.txt:
     62
    1632019-07-12  Justin Michaud  <justin_michaud@apple.com>
    264
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r247164 r247403  
    899899                52CD0F5E2242F569004A18A5 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* JavaScriptCore.framework */; };
    900900                52CD0F682242F71C004A18A5 /* testdfg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52CD0F672242F71C004A18A5 /* testdfg.cpp */; };
    901                 52D13091221CE176009C836C /* foo.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 52D1308F221CE03A009C836C /* foo.js */; };
    902901                52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; };
    903902                530A66B91FA3E78B0026A545 /* UnifiedSource3-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 530A66B11FA3E77A0026A545 /* UnifiedSource3-mm.mm */; };
     
    10831082                53B4BD121F68B32500D2BEA3 /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };
    10841083                53B601EC2034B8C5006BE667 /* JSCast.h in Headers */ = {isa = PBXBuildFile; fileRef = 53B601EB2034B8C5006BE667 /* JSCast.h */; settings = {ATTRIBUTES = (Private, ); }; };
    1085                 53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 53C3D5E421ECE6CE0087FDFC /* basic.js */; };
    10861084                53C4F66B21B1A409002FD009 /* JSAPIGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 53C4F66A21B1A409002FD009 /* JSAPIGlobalObject.h */; };
    10871085                53C6FEEF1E8ADFA900B18425 /* WasmOpcodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 53C6FEEE1E8ADFA900B18425 /* WasmOpcodeOrigin.h */; };
     
    11121110                5C4E8E961DBEBE620036F1FC /* JSONParseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */; };
    11131111                5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
    1114                 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; };
    11151112                5DBB1525131D0BD70056AD36 /* minidom.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 1412110D0A48788700480255 /* minidom.js */; };
    11161113                5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (); }; };
     
    12881285                960097A60EBABB58007A7297 /* LabelScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 960097A50EBABB58007A7297 /* LabelScope.h */; };
    12891286                9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
    1290                 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12911287                9688CB160ED12B4E001D6491 /* X86Registers.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D6491 /* X86Registers.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12921288                9688CB160ED12B4E001D6492 /* X86_64Registers.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D6492 /* X86_64Registers.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12931289                9688CB160ED12B4E001D6499 /* RegisterInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D6499 /* RegisterInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1290                9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
    12941291                969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */; };
    12951292                969A072A0ED1CE6900F1F681 /* Label.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07270ED1CE6900F1F681 /* Label.h */; };
     
    18861883                FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
    18871884                FECB8B271D25BB85006F2463 /* FunctionOverridesTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FECB8B251D25BB6E006F2463 /* FunctionOverridesTest.cpp */; };
    1888                 FECB8B2A1D25CB5A006F2463 /* testapi-function-overrides.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = FECB8B291D25CABB006F2463 /* testapi-function-overrides.js */; };
    18891885                FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = FED287B115EC9A5700DA8161 /* LLIntOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
    18901886                FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    20802076
    20812077/* Begin PBXCopyFilesBuildPhase section */
    2082                 5DBB1511131D0B130056AD36 /* Copy Support Script */ = {
    2083                         isa = PBXCopyFilesBuildPhase;
    2084                         buildActionMask = 12;
    2085                         dstPath = testapiScripts;
    2086                         dstSubfolderSpec = 16;
    2087                         files = (
    2088                                 53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */,
    2089                                 52D13091221CE176009C836C /* foo.js in Copy Support Script */,
    2090                                 FECB8B2A1D25CB5A006F2463 /* testapi-function-overrides.js in Copy Support Script */,
    2091                                 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */,
    2092                         );
    2093                         name = "Copy Support Script";
    2094                         runOnlyForDeploymentPostprocessing = 0;
    2095                 };
    20962078                5DBB1524131D0BA10056AD36 /* Copy Support Script */ = {
    20972079                        isa = PBXCopyFilesBuildPhase;
     
    40834065                960097A50EBABB58007A7297 /* LabelScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelScope.h; sourceTree = "<group>"; };
    40844066                9688CB130ED12B4E001D649F /* AssemblerBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssemblerBuffer.h; sourceTree = "<group>"; };
    4085                 9688CB140ED12B4E001D649F /* X86Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Assembler.h; sourceTree = "<group>"; };
    40864067                9688CB140ED12B4E001D6491 /* X86Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Registers.h; sourceTree = "<group>"; };
    40874068                9688CB140ED12B4E001D6492 /* X86_64Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86_64Registers.h; sourceTree = "<group>"; };
    40884069                9688CB140ED12B4E001D6499 /* RegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterInfo.h; sourceTree = "<group>"; };
     4070                9688CB140ED12B4E001D649F /* X86Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Assembler.h; sourceTree = "<group>"; };
    40894071                969A07200ED1CE3300F1F681 /* BytecodeGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeGenerator.cpp; sourceTree = "<group>"; };
    40904072                969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeGenerator.h; sourceTree = "<group>"; };
     
    79117893                                9688CB140ED12B4E001D6499 /* RegisterInfo.h */,
    79127894                                FE533CA01F217C310016A1FE /* testmasm.cpp */,
     7895                                9688CB140ED12B4E001D6492 /* X86_64Registers.h */,
    79137896                                9688CB140ED12B4E001D649F /* X86Assembler.h */,
    79147897                                9688CB140ED12B4E001D6491 /* X86Registers.h */,
    7915                                 9688CB140ED12B4E001D6492 /* X86_64Registers.h */,
    79167898                        );
    79177899                        path = assembler;
     
    86578639                                A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
    86588640                                FE1E2C402240DD6200F6B729 /* ARM64EAssembler.h in Headers */,
    8659                                 A1A009C11831A26E00CF8722 /* ARM64Registers.h */,
     8641                                A1A009C11831A26E00CF8722 /* ARM64Registers.h in Headers */,
    86608642                                86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
    86618643                                86ADD1450FDDEA980006FFCC /* ARMv7Registers.h in Headers */,
     
    1009910081                                C2B6D75318A33793004A9301 /* WriteBarrierInlines.h in Headers */,
    1010010082                                0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */,
     10083                                9688CB160ED12B4E001D6492 /* X86_64Registers.h in Headers */,
    1010110084                                9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */,
    1010210085                                9688CB160ED12B4E001D6491 /* X86Registers.h in Headers */,
    10103                                 9688CB160ED12B4E001D6492 /* X86_64Registers.h in Headers */,
    1010410086                                9959E92E1BD17FA4001AA413 /* xxd.pl in Headers */,
    1010510087                                451539B912DC994500EF7AC4 /* Yarr.h in Headers */,
     
    1020910191                                14BD59BC0A3E8F9000BAF59C /* Sources */,
    1021010192                                14BD59BD0A3E8F9000BAF59C /* Frameworks */,
    10211                                 5DBB1511131D0B130056AD36 /* Copy Support Script */,
     10193                                5366FDB222D5485B00BF94AF /* Copy Support Scripts */,
    1021210194                                5DAFD6CD146B6B6E00FBEFB4 /* Install Support Script */,
    1021310195                        );
     
    1053910521                        shellPath = /bin/sh;
    1054010522                        shellScript = "Scripts/check-xcfilelists.sh\n";
     10523                };
     10524                5366FDB222D5485B00BF94AF /* Copy Support Scripts */ = {
     10525                        isa = PBXShellScriptBuildPhase;
     10526                        buildActionMask = 2147483647;
     10527                        files = (
     10528                        );
     10529                        inputFileListPaths = (
     10530                        );
     10531                        inputPaths = (
     10532                        );
     10533                        name = "Copy Support Scripts";
     10534                        outputFileListPaths = (
     10535                        );
     10536                        outputPaths = (
     10537                        );
     10538                        runOnlyForDeploymentPostprocessing = 0;
     10539                        shellPath = /bin/sh;
     10540                        shellScript = "rsync -r ${SRCROOT}/API/tests/testapiScripts ${BUILT_PRODUCTS_DIR}\n";
    1054110541                };
    1054210542                53B4BD091F68AF8900D2BEA3 /* Generate Unified Sources */ = {
  • trunk/Source/JavaScriptCore/builtins/ModuleLoader.js

    r239774 r247403  
    370370    return this.getModuleNamespaceObject(entry.module);
    371371}
     372
     373function dependencyKeysIfEvaluated(key)
     374{
     375    "use strict";
     376
     377    let entry = this.registry.@get(key);
     378    if (!entry || !entry.evaluated)
     379        return null;
     380
     381    let dependencies = entry.dependencies;
     382    let length = dependencies.length;
     383    let result = new @Array(length);
     384    for (let i = 0; i < length; ++i)
     385        result[i] = dependencies[i].key;
     386
     387    return result;
     388}
  • trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp

    r244620 r247403  
    8787    linkAndEvaluateModule          JSBuiltin                                  DontEnum|Function 2
    8888    requestImportModule            JSBuiltin                                  DontEnum|Function 3
     89    dependencyKeysIfEvaluated      JSBuiltin                                  DontEnum|Function 1
    8990    getModuleNamespaceObject       moduleLoaderGetModuleNamespaceObject       DontEnum|Function 1
    9091    parseModule                    moduleLoaderParseModule                    DontEnum|Function 2
     
    124125    }
    125126    return vm.propertyNames->emptyIdentifier.impl();
     127}
     128
     129JSArray* JSModuleLoader::dependencyKeysIfEvaluated(ExecState* exec, JSValue key)
     130{
     131    VM& vm = exec->vm();
     132    auto scope = DECLARE_THROW_SCOPE(vm);
     133
     134    JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().dependencyKeysIfEvaluatedPublicName()));
     135    RETURN_IF_EXCEPTION(scope, nullptr);
     136    CallData callData;
     137    CallType callType = JSC::getCallData(vm, function, callData);
     138    ASSERT(callType != CallType::None);
     139
     140    MarkedArgumentBuffer arguments;
     141    arguments.append(key);
     142
     143    JSValue result = call(exec, function, callType, callData, this, arguments);
     144    RETURN_IF_EXCEPTION(scope, nullptr);
     145
     146    return jsDynamicCast<JSArray*>(vm, result);
    126147}
    127148
  • trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h

    r244620 r247403  
    8585    // Utility functions.
    8686    JSModuleNamespaceObject* getModuleNamespaceObject(ExecState*, JSValue moduleRecord);
     87    JSArray* dependencyKeysIfEvaluated(ExecState*, JSValue key);
    8788
    8889protected:
  • trunk/Source/JavaScriptCore/shell/CMakeLists.txt

    r246039 r247403  
    9393
    9494    file(COPY
    95         "${JAVASCRIPTCORE_DIR}/API/tests/testapi.js"
    96         DESTINATION
    97         ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/testapiScripts
    98     )
    99     file(COPY
    100         "${JAVASCRIPTCORE_DIR}/API/tests/testapi-function-overrides.js"
     95        "${JAVASCRIPTCORE_DIR}/API/tests/testapiScripts"
    10196        DESTINATION
    10297        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/testapiScripts
Note: See TracChangeset for help on using the changeset viewer.