Diff
Modified: trunk/Source/_javascript_Core/API/JSAPIGlobalObject.h (244619 => 244620)
--- trunk/Source/_javascript_Core/API/JSAPIGlobalObject.h 2019-04-24 22:26:45 UTC (rev 244619)
+++ trunk/Source/_javascript_Core/API/JSAPIGlobalObject.h 2019-04-24 22:42:38 UTC (rev 244620)
@@ -56,6 +56,7 @@
static Identifier moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue);
static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
static JSObject* moduleLoaderCreateImportMetaProperties(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSModuleRecord*, JSValue);
+ static JSValue moduleLoaderEvaluate(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
JSValue loadAndEvaluateJSScriptModule(const JSLockHolder&, JSScript *);
Modified: trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm (244619 => 244620)
--- trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm 2019-04-24 22:26:45 UTC (rev 244619)
+++ trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm 2019-04-24 22:42:38 UTC (rev 244620)
@@ -36,6 +36,7 @@
#import "JSContextInternal.h"
#import "JSInternalPromise.h"
#import "JSInternalPromiseDeferred.h"
+#import "JSModuleLoader.h"
#import "JSNativeStdFunction.h"
#import "JSPromiseDeferred.h"
#import "JSScriptInternal.h"
@@ -61,7 +62,7 @@
&moduleLoaderResolve, // moduleLoaderResolve
&moduleLoaderFetch, // moduleLoaderFetch
&moduleLoaderCreateImportMetaProperties, // moduleLoaderCreateImportMetaProperties
- nullptr, // moduleLoaderEvaluate
+ moduleLoaderEvaluate, // moduleLoaderEvaluate
nullptr, // promiseRejectionTracker
nullptr, // defaultLanguage
nullptr, // compileStreaming
@@ -234,6 +235,33 @@
return metaProperties;
}
+JSValue JSAPIGlobalObject::moduleLoaderEvaluate(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader* moduleLoader, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject->globalExec())];
+ id <JSModuleLoaderDelegate> moduleLoaderDelegate = [context moduleLoaderDelegate];
+ NSURL *url = ""
+
+ if ([moduleLoaderDelegate respondsToSelector:@selector(willEvaluateModule:)] || [moduleLoaderDelegate respondsToSelector:@selector(didEvaluateModule:)]) {
+ String moduleKey = key.toWTFString(exec);
+ RETURN_IF_EXCEPTION(scope, { });
+ url = "" URLWithString:static_cast<NSString *>(moduleKey)];
+ }
+
+ if ([moduleLoaderDelegate respondsToSelector:@selector(willEvaluateModule:)])
+ [moduleLoaderDelegate willEvaluateModule:url];
+
+ scope.release();
+ JSValue result = moduleLoader->evaluateNonVirtual(exec, key, moduleRecordValue, scriptFetcher);
+
+ if ([moduleLoaderDelegate respondsToSelector:@selector(didEvaluateModule:)])
+ [moduleLoaderDelegate didEvaluateModule:url];
+
+ return result;
+}
+
JSValue JSAPIGlobalObject::loadAndEvaluateJSScriptModule(const JSLockHolder&, JSScript *script)
{
ASSERT(script.type == kJSScriptTypeModule);
Modified: trunk/Source/_javascript_Core/API/JSContextPrivate.h (244619 => 244620)
--- trunk/Source/_javascript_Core/API/JSContextPrivate.h 2019-04-24 22:26:45 UTC (rev 244619)
+++ trunk/Source/_javascript_Core/API/JSContextPrivate.h 2019-04-24 22:42:38 UTC (rev 244620)
@@ -49,6 +49,18 @@
*/
- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject;
+@optional
+
+/*! @abstract This is called before the module with "key" is evaluated.
+ @param key The module key for the module that is about to be evaluated.
+ */
+- (void)willEvaluateModule:(NSURL *)key;
+
+/*! @abstract This is called after the module with "key" is evaluated.
+ @param key The module key for the module that was just evaluated.
+ */
+- (void)didEvaluateModule:(NSURL *)key;
+
@end
@interface JSContext(Private)
Modified: trunk/Source/_javascript_Core/API/tests/testapi.mm (244619 => 244620)
--- trunk/Source/_javascript_Core/API/tests/testapi.mm 2019-04-24 22:26:45 UTC (rev 244619)
+++ trunk/Source/_javascript_Core/API/tests/testapi.mm 2019-04-24 22:42:38 UTC (rev 244620)
@@ -1827,6 +1827,11 @@
+ (instancetype)contextWithBlockForFetch:(FetchBlock)block;
+@property unsigned willEvaluateModuleCallCount;
+@property unsigned didEvaluateModuleCallCount;
+@property BOOL sawBarJS;
+@property BOOL sawFooJS;
+
@end
@implementation JSContextFetchDelegate {
@@ -1836,6 +1841,10 @@
+ (instancetype)contextWithBlockForFetch:(FetchBlock)block
{
auto *result = [[JSContextFetchDelegate alloc] init];
+ result.willEvaluateModuleCallCount = 0;
+ result.didEvaluateModuleCallCount = 0;
+ result.sawBarJS = NO;
+ result.sawFooJS = NO;
result->m_fetchBlock = block;
return result;
}
@@ -1845,6 +1854,18 @@
m_fetchBlock(context, identifier, resolve, reject);
}
+- (void)willEvaluateModule:(NSURL *)url
+{
+ self.willEvaluateModuleCallCount += 1;
+ self.sawBarJS |= [url isEqual:[NSURL URLWithString:@"file:///directory/bar.js"]];
+}
+
+- (void)didEvaluateModule:(NSURL *)url
+{
+ self.didEvaluateModuleCallCount += 1;
+ self.sawFooJS |= [url isEqual:[NSURL URLWithString:@"file:///foo.js"]];
+}
+
@end
static void checkModuleCodeRan(JSContext *context, JSValue *promise, JSValue *expected)
@@ -1898,6 +1919,10 @@
JSValue *promise = [context evaluateScript:@"import('./bar.js');" withSourceURL:[NSURL fileURLWithPath:@"/directory" isDirectory:YES]];
JSValue *null = [JSValue valueWithNullInContext:context];
checkModuleCodeRan(context, promise, null);
+ checkResult(@"Context should call willEvaluateModule: twice", context.willEvaluateModuleCallCount == 2);
+ checkResult(@"Context should call didEvaluateModule: twice", context.didEvaluateModuleCallCount == 2);
+ checkResult(@"Context should see bar.js url", !!context.sawBarJS);
+ checkResult(@"Context should see foo.js url", !!context.sawFooJS);
}
}
@@ -1926,6 +1951,8 @@
JSValue *promise = [context evaluateScript:@"import('./bar.js');" withSourceURL:[NSURL fileURLWithPath:@"/directory" isDirectory:YES]];
JSValue *null = [JSValue valueWithNullInContext:context];
checkModuleCodeRan(context, promise, null);
+ checkResult(@"Context should call willEvaluateModule: twice", context.willEvaluateModuleCallCount == 2);
+ checkResult(@"Context should call didEvaluateModule: twice", context.didEvaluateModuleCallCount == 2);
}
}
@@ -1962,6 +1989,10 @@
JSValue *promise = [context evaluateScript:@"import('../otherDirectory/baz.js');" withSourceURL:[NSURL fileURLWithPath:@"/directory" isDirectory:YES]];
JSValue *null = [JSValue valueWithNullInContext:context];
checkModuleCodeRan(context, promise, null);
+ checkResult(@"Context should call willEvaluateModule: three times", context.willEvaluateModuleCallCount == 3);
+ checkResult(@"Context should call didEvaluateModule: three times", context.didEvaluateModuleCallCount == 3);
+ checkResult(@"Context should see bar.js url", !!context.sawBarJS);
+ checkResult(@"Context should see foo.js url", !!context.sawFooJS);
}
}
@@ -1983,6 +2014,10 @@
JSValue *promise = [context evaluateScript:@"import('/directory/bar.js');"];
JSValue *null = [JSValue valueWithNullInContext:context];
checkModuleCodeRan(context, promise, null);
+ checkResult(@"Context should call willEvaluateModule: once", context.willEvaluateModuleCallCount == 1);
+ checkResult(@"Context should call didEvaluateModule: once", context.didEvaluateModuleCallCount == 1);
+ checkResult(@"Context should see bar.js url", !!context.sawBarJS);
+ checkResult(@"Context should not see foo.js url", !context.sawFooJS);
}
}
@@ -1995,6 +2030,10 @@
context.moduleLoaderDelegate = context;
JSValue *promise = [context evaluateScript:@"import('../otherDirectory/baz.js');"];
checkModuleWasRejected(context, promise);
+ checkResult(@"Context should call willEvaluateModule: zero times", context.willEvaluateModuleCallCount == 0);
+ checkResult(@"Context should call didEvaluateModule: zero times", context.didEvaluateModuleCallCount == 0);
+ checkResult(@"Context should not see bar.js url", !context.sawBarJS);
+ checkResult(@"Context should not see foo.js url", !context.sawFooJS);
}
}
Modified: trunk/Source/_javascript_Core/ChangeLog (244619 => 244620)
--- trunk/Source/_javascript_Core/ChangeLog 2019-04-24 22:26:45 UTC (rev 244619)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-04-24 22:42:38 UTC (rev 244620)
@@ -1,3 +1,32 @@
+2019-04-24 Saam Barati <sbar...@apple.com>
+
+ 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:
+
2019-04-23 Yusuke Suzuki <ysuz...@apple.com>
[JSC] Shrink DFG::MinifiedNode
Modified: trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp (244619 => 244620)
--- trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp 2019-04-24 22:26:45 UTC (rev 244619)
+++ trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp 2019-04-24 22:42:38 UTC (rev 244620)
@@ -340,6 +340,11 @@
if (globalObject->globalObjectMethodTable()->moduleLoaderEvaluate)
return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, scriptFetcher);
+ return evaluateNonVirtual(exec, key, moduleRecordValue, scriptFetcher);
+}
+
+JSValue JSModuleLoader::evaluateNonVirtual(ExecState* exec, JSValue, JSValue moduleRecordValue, JSValue)
+{
if (auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(exec->vm(), moduleRecordValue))
return moduleRecord->evaluate(exec);
return jsUndefined();
Modified: trunk/Source/_javascript_Core/runtime/JSModuleLoader.h (244619 => 244620)
--- trunk/Source/_javascript_Core/runtime/JSModuleLoader.h 2019-04-24 22:26:45 UTC (rev 244619)
+++ trunk/Source/_javascript_Core/runtime/JSModuleLoader.h 2019-04-24 22:42:38 UTC (rev 244620)
@@ -80,6 +80,7 @@
// Additional platform dependent hooked APIs.
JSValue evaluate(ExecState*, JSValue key, JSValue moduleRecord, JSValue scriptFetcher);
+ JSValue evaluateNonVirtual(ExecState*, JSValue key, JSValue moduleRecord, JSValue scriptFetcher);
// Utility functions.
JSModuleNamespaceObject* getModuleNamespaceObject(ExecState*, JSValue moduleRecord);