Changeset 244620 in webkit


Ignore:
Timestamp:
Apr 24, 2019 3:42:38 PM (5 years ago)
Author:
sbarati@apple.com
Message:

Add SPI callbacks for before and after module execution
https://bugs.webkit.org/show_bug.cgi?id=197244
<rdar://problem/50180511>

Reviewed by Yusuke Suzuki.

This is helpful for clients that want to profile execution of modules
in some way. E.g, if they want to time module execution time.

  • API/JSAPIGlobalObject.h:
  • API/JSAPIGlobalObject.mm:

(JSC::JSAPIGlobalObject::moduleLoaderEvaluate):

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

(+[JSContextFetchDelegate contextWithBlockForFetch:]):
(-[JSContextFetchDelegate willEvaluateModule:]):
(-[JSContextFetchDelegate didEvaluateModule:]):
(testFetch):
(testFetchWithTwoCycle):
(testFetchWithThreeCycle):
(testLoaderResolvesAbsoluteScriptURL):
(testLoaderRejectsNilScriptURL):

  • runtime/JSModuleLoader.cpp:

(JSC::JSModuleLoader::evaluate):
(JSC::JSModuleLoader::evaluateNonVirtual):

  • runtime/JSModuleLoader.h:
Location:
trunk/Source/JavaScriptCore
Files:
7 edited

Legend:

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

    r241929 r244620  
    5757    static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
    5858    static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue);
     59    static JSValue moduleLoaderEvaluate(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
    5960
    6061    JSValue loadAndEvaluateJSScriptModule(const JSLockHolder&, JSScript *);
  • trunk/Source/JavaScriptCore/API/JSAPIGlobalObject.mm

    r244401 r244620  
    3737#import "JSInternalPromise.h"
    3838#import "JSInternalPromiseDeferred.h"
     39#import "JSModuleLoader.h"
    3940#import "JSNativeStdFunction.h"
    4041#import "JSPromiseDeferred.h"
     
    6263    &moduleLoaderFetch, // moduleLoaderFetch
    6364    &moduleLoaderCreateImportMetaProperties, // moduleLoaderCreateImportMetaProperties
    64     nullptr, // moduleLoaderEvaluate
     65    moduleLoaderEvaluate, // moduleLoaderEvaluate
    6566    nullptr, // promiseRejectionTracker
    6667    nullptr, // defaultLanguage
     
    235236}
    236237
     238JSValue JSAPIGlobalObject::moduleLoaderEvaluate(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader* moduleLoader, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher)
     239{
     240    VM& vm = exec->vm();
     241    auto scope = DECLARE_THROW_SCOPE(vm);
     242
     243    JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject->globalExec())];
     244    id <JSModuleLoaderDelegate> moduleLoaderDelegate = [context moduleLoaderDelegate];
     245    NSURL *url = nil;
     246
     247    if ([moduleLoaderDelegate respondsToSelector:@selector(willEvaluateModule:)] || [moduleLoaderDelegate respondsToSelector:@selector(didEvaluateModule:)]) {
     248        String moduleKey = key.toWTFString(exec);
     249        RETURN_IF_EXCEPTION(scope, { });
     250        url = [NSURL URLWithString:static_cast<NSString *>(moduleKey)];
     251    }
     252
     253    if ([moduleLoaderDelegate respondsToSelector:@selector(willEvaluateModule:)])
     254        [moduleLoaderDelegate willEvaluateModule:url];
     255
     256    scope.release();
     257    JSValue result = moduleLoader->evaluateNonVirtual(exec, key, moduleRecordValue, scriptFetcher);
     258
     259    if ([moduleLoaderDelegate respondsToSelector:@selector(didEvaluateModule:)])
     260        [moduleLoaderDelegate didEvaluateModule:url];
     261
     262    return result;
     263}
     264
    237265JSValue JSAPIGlobalObject::loadAndEvaluateJSScriptModule(const JSLockHolder&, JSScript *script)
    238266{
  • trunk/Source/JavaScriptCore/API/JSContextPrivate.h

    r243376 r244620  
    5050- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject;
    5151
     52@optional
     53
     54/*! @abstract This is called before the module with "key" is evaluated.
     55 @param key The module key for the module that is about to be evaluated.
     56 */
     57- (void)willEvaluateModule:(NSURL *)key;
     58
     59/*! @abstract This is called after the module with "key" is evaluated.
     60 @param key The module key for the module that was just evaluated.
     61 */
     62- (void)didEvaluateModule:(NSURL *)key;
     63
    5264@end
    5365
  • trunk/Source/JavaScriptCore/API/tests/testapi.mm

    r244401 r244620  
    18281828+ (instancetype)contextWithBlockForFetch:(FetchBlock)block;
    18291829
     1830@property unsigned willEvaluateModuleCallCount;
     1831@property unsigned didEvaluateModuleCallCount;
     1832@property BOOL sawBarJS;
     1833@property BOOL sawFooJS;
     1834
    18301835@end
    18311836
     
    18371842{
    18381843    auto *result = [[JSContextFetchDelegate alloc] init];
     1844    result.willEvaluateModuleCallCount = 0;
     1845    result.didEvaluateModuleCallCount = 0;
     1846    result.sawBarJS = NO;
     1847    result.sawFooJS = NO;
    18391848    result->m_fetchBlock = block;
    18401849    return result;
     
    18441853{
    18451854    m_fetchBlock(context, identifier, resolve, reject);
     1855}
     1856
     1857- (void)willEvaluateModule:(NSURL *)url
     1858{
     1859    self.willEvaluateModuleCallCount += 1;
     1860    self.sawBarJS |= [url isEqual:[NSURL URLWithString:@"file:///directory/bar.js"]];
     1861}
     1862
     1863- (void)didEvaluateModule:(NSURL *)url
     1864{
     1865    self.didEvaluateModuleCallCount += 1;
     1866    self.sawFooJS |= [url isEqual:[NSURL URLWithString:@"file:///foo.js"]];
    18461867}
    18471868
     
    18991920        JSValue *null = [JSValue valueWithNullInContext:context];
    19001921        checkModuleCodeRan(context, promise, null);
     1922        checkResult(@"Context should call willEvaluateModule: twice", context.willEvaluateModuleCallCount == 2);
     1923        checkResult(@"Context should call didEvaluateModule: twice", context.didEvaluateModuleCallCount == 2);
     1924        checkResult(@"Context should see bar.js url", !!context.sawBarJS);
     1925        checkResult(@"Context should see foo.js url", !!context.sawFooJS);
    19011926    }
    19021927}
     
    19271952        JSValue *null = [JSValue valueWithNullInContext:context];
    19281953        checkModuleCodeRan(context, promise, null);
     1954        checkResult(@"Context should call willEvaluateModule: twice", context.willEvaluateModuleCallCount == 2);
     1955        checkResult(@"Context should call didEvaluateModule: twice", context.didEvaluateModuleCallCount == 2);
    19291956    }
    19301957}
     
    19631990        JSValue *null = [JSValue valueWithNullInContext:context];
    19641991        checkModuleCodeRan(context, promise, null);
     1992        checkResult(@"Context should call willEvaluateModule: three times", context.willEvaluateModuleCallCount == 3);
     1993        checkResult(@"Context should call didEvaluateModule: three times", context.didEvaluateModuleCallCount == 3);
     1994        checkResult(@"Context should see bar.js url", !!context.sawBarJS);
     1995        checkResult(@"Context should see foo.js url", !!context.sawFooJS);
    19651996    }
    19661997}
     
    19842015        JSValue *null = [JSValue valueWithNullInContext:context];
    19852016        checkModuleCodeRan(context, promise, null);
     2017        checkResult(@"Context should call willEvaluateModule: once", context.willEvaluateModuleCallCount == 1);
     2018        checkResult(@"Context should call didEvaluateModule: once", context.didEvaluateModuleCallCount == 1);
     2019        checkResult(@"Context should see bar.js url", !!context.sawBarJS);
     2020        checkResult(@"Context should not see foo.js url", !context.sawFooJS);
    19862021    }
    19872022}
     
    19962031        JSValue *promise = [context evaluateScript:@"import('../otherDirectory/baz.js');"];
    19972032        checkModuleWasRejected(context, promise);
     2033        checkResult(@"Context should call willEvaluateModule: zero times", context.willEvaluateModuleCallCount == 0);
     2034        checkResult(@"Context should call didEvaluateModule: zero times", context.didEvaluateModuleCallCount == 0);
     2035        checkResult(@"Context should not see bar.js url", !context.sawBarJS);
     2036        checkResult(@"Context should not see foo.js url", !context.sawFooJS);
    19982037    }
    19992038}
  • trunk/Source/JavaScriptCore/ChangeLog

    r244580 r244620  
     12019-04-24  Saam Barati  <sbarati@apple.com>
     2
     3        Add SPI callbacks for before and after module execution
     4        https://bugs.webkit.org/show_bug.cgi?id=197244
     5        <rdar://problem/50180511>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        This is helpful for clients that want to profile execution of modules
     10        in some way. E.g, if they want to time module execution time.
     11
     12        * API/JSAPIGlobalObject.h:
     13        * API/JSAPIGlobalObject.mm:
     14        (JSC::JSAPIGlobalObject::moduleLoaderEvaluate):
     15        * API/JSContextPrivate.h:
     16        * API/tests/testapi.mm:
     17        (+[JSContextFetchDelegate contextWithBlockForFetch:]):
     18        (-[JSContextFetchDelegate willEvaluateModule:]):
     19        (-[JSContextFetchDelegate didEvaluateModule:]):
     20        (testFetch):
     21        (testFetchWithTwoCycle):
     22        (testFetchWithThreeCycle):
     23        (testLoaderResolvesAbsoluteScriptURL):
     24        (testLoaderRejectsNilScriptURL):
     25        * runtime/JSModuleLoader.cpp:
     26        (JSC::JSModuleLoader::evaluate):
     27        (JSC::JSModuleLoader::evaluateNonVirtual):
     28        * runtime/JSModuleLoader.h:
     29
    1302019-04-23  Yusuke Suzuki  <ysuzuki@apple.com>
    231
  • trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp

    r242991 r244620  
    341341        return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, scriptFetcher);
    342342
     343    return evaluateNonVirtual(exec, key, moduleRecordValue, scriptFetcher);
     344}
     345
     346JSValue JSModuleLoader::evaluateNonVirtual(ExecState* exec, JSValue, JSValue moduleRecordValue, JSValue)
     347{
    343348    if (auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(exec->vm(), moduleRecordValue))
    344349        return moduleRecord->evaluate(exec);
  • trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h

    r240023 r244620  
    8181    // Additional platform dependent hooked APIs.
    8282    JSValue evaluate(ExecState*, JSValue key, JSValue moduleRecord, JSValue scriptFetcher);
     83    JSValue evaluateNonVirtual(ExecState*, JSValue key, JSValue moduleRecord, JSValue scriptFetcher);
    8384
    8485    // Utility functions.
Note: See TracChangeset for help on using the changeset viewer.