Title: [247403] trunk/Source/_javascript_Core
Revision
247403
Author
keith_mil...@apple.com
Date
2019-07-12 15:15:55 -0700 (Fri, 12 Jul 2019)

Log 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/_javascript_Core/API/tests/testapi-function-overrides.js.
* API/tests/testapiScripts/testapi.js: Renamed from Source/_javascript_Core/API/tests/testapi.js.
* _javascript_Core.xcodeproj/project.pbxproj:
* builtins/ModuleLoader.js:
(dependencyKeysIfEvaluated):
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::dependencyKeysIfEvaluated):
* runtime/JSModuleLoader.h:
* shell/CMakeLists.txt:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm (247402 => 247403)


--- trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm	2019-07-12 22:15:55 UTC (rev 247403)
@@ -69,6 +69,33 @@
     nullptr, // instantiateStreaming
 };
 
+static Expected<URL, String> computeValidImportSpecifier(const URL& base, const String& specifier)
+{
+    URL absoluteURL(URL(), specifier);
+    if (absoluteURL.isValid())
+        return absoluteURL;
+
+    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
+        return makeUnexpected(makeString("Module specifier: "_s, specifier, " does not start with \"/\", \"./\", or \"../\"."_s));
+
+    if (specifier.startsWith('/')) {
+        absoluteURL = URL(URL({ }, "file://"), specifier);
+        if (absoluteURL.isValid())
+            return absoluteURL;
+    }
+
+    if (base == URL())
+        return makeUnexpected("Could not determine the base URL for loading."_s);
+
+    if (!base.isValid())
+        return makeUnexpected(makeString("Referrering script's url is not valid: "_s, base.string()));
+
+    absoluteURL = URL(base, specifier);
+    if (absoluteURL.isValid())
+        return absoluteURL;
+    return makeUnexpected(makeString("Could not form valid URL from identifier and base. Tried:"_s, absoluteURL.string()));
+}
+
 Identifier JSAPIGlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue referrer, JSValue)
 {
     VM& vm = exec->vm();
@@ -76,23 +103,22 @@
     ASSERT_UNUSED(globalObject, globalObject == exec->lexicalGlobalObject());
     ASSERT(key.isString() || key.isSymbol());
     String name =  key.toWTFString(exec);
+    RETURN_IF_EXCEPTION(scope, { });
 
+    URL base;
     if (JSString* referrerString = jsDynamicCast<JSString*>(vm, referrer)) {
         String value = referrerString->value(exec);
+        RETURN_IF_EXCEPTION(scope, { });
         URL referrerURL({ }, value);
-        RETURN_IF_EXCEPTION(scope, { });
         RELEASE_ASSERT(referrerURL.isValid());
-
-        URL url = "" name);
-        if (url.isValid())
-            return Identifier::fromString(exec, url);
-    } else {
-        URL url = "" }, name);
-        if (url.isValid())
-            return Identifier::fromString(exec, url);
+        base = WTFMove(referrerURL);
     }
 
-    throwVMError(exec, scope, "Could not form valid URL from identifier and base"_s);
+    auto result = computeValidImportSpecifier(base, name);
+    if (result)
+        return Identifier::fromString(&vm, result.value());
+
+    throwVMError(exec, scope, createError(exec, result.error()));
     return { };
 }
 
@@ -121,33 +147,12 @@
         return reject(exception);
     }
 
-    URL absoluteURL(URL(), specifier);
-    if (absoluteURL.isValid())
-        return import(absoluteURL);
-
-    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
-        return reject(createError(exec, makeString("Module specifier: ", specifier, " does not start with \"/\", \"./\", or \"../\"."_s)));
-
-    if (specifier.startsWith('/')) {
-        absoluteURL = URL(URL({ }, "file://"), specifier);
-        if (absoluteURL.isValid())
-            return import(absoluteURL);
-    }
-
-    auto noBaseErrorMessage = "Could not determine the base URL for loading."_s;
-    if (sourceOrigin.isNull())
-        return reject(createError(exec, makeString(noBaseErrorMessage, " Referring script has no URL."_s)));
-
-    auto referrer = sourceOrigin.string();
+    String referrer = !sourceOrigin.isNull() ? sourceOrigin.string() : String();
     URL baseURL(URL(), referrer);
-    if (!baseURL.isValid())
-        return reject(createError(exec, makeString(noBaseErrorMessage, " Referring script's URL is not valid: "_s, baseURL.string())));
-
-    URL url(baseURL, specifier);
-    if (!url.isValid())
-        return reject(createError(exec, makeString("could not determine a valid URL for module specifier. Tried: "_s, url.string())));
-
-    return import(url);
+    auto result = computeValidImportSpecifier(baseURL, specifier);
+    if (result)
+        return import(result.value());
+    return reject(createError(exec, result.error()));
 }
 
 JSInternalPromise* JSAPIGlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue, JSValue)

Modified: trunk/Source/_javascript_Core/API/JSContext.mm (247402 => 247403)


--- trunk/Source/_javascript_Core/API/JSContext.mm	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/API/JSContext.mm	2019-07-12 22:15:55 UTC (rev 247403)
@@ -146,6 +146,32 @@
     return [JSValue valueWithJSValueRef:toRef(vm, result) inContext:self];
 }
 
+- (JSValue *)dependencyIdentifiersForModuleJSScript:(JSScript *)script
+{
+    JSC::ExecState* exec = toJS(m_context);
+    JSC::VM& vm = exec->vm();
+    JSC::JSLockHolder locker(vm);
+
+    if (script.type != kJSScriptTypeModule) {
+        self.exceptionHandler(self, [JSValue valueWithNewErrorFromMessage:@"script is not a module" inContext:self]);
+        return [JSValue valueWithUndefinedInContext:self];
+    }
+
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    JSC::JSArray* result = exec->lexicalGlobalObject()->moduleLoader()->dependencyKeysIfEvaluated(exec, JSC::jsString(&vm, [[script sourceURL] absoluteString]));
+    if (scope.exception()) {
+        JSValueRef exceptionValue = toRef(exec, scope.exception()->value());
+        scope.clearException();
+        return [self valueFromNotifyException:exceptionValue];
+    }
+
+    if (!result) {
+        self.exceptionHandler(self, [JSValue valueWithNewErrorFromMessage:@"script has not run in context or was not evaluated successfully" inContext:self]);
+        return [JSValue valueWithUndefinedInContext:self];
+    }
+    return [JSValue valueWithJSValueRef:toRef(vm, result) inContext:self];
+}
+
 - (void)setException:(JSValue *)value
 {
     JSC::ExecState* exec = toJS(m_context);

Modified: trunk/Source/_javascript_Core/API/JSContextPrivate.h (247402 => 247403)


--- trunk/Source/_javascript_Core/API/JSContextPrivate.h	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/API/JSContextPrivate.h	2019-07-12 22:15:55 UTC (rev 247403)
@@ -84,7 +84,7 @@
 @property (setter=_setDebuggerRunLoop:) CFRunLoopRef _debuggerRunLoop JSC_API_AVAILABLE(macos(10.10), ios(8.0));
 
 /*! @abstract The delegate the context will use when trying to load a module. Note, this delegate will be ignored for contexts returned by UIWebView. */
-@property (nonatomic, weak) id <JSModuleLoaderDelegate> moduleLoaderDelegate JSC_API_AVAILABLE(macos(JSC_MAC_TBA), ios(JSC_IOS_TBA));
+@property (nonatomic, weak) id <JSModuleLoaderDelegate> moduleLoaderDelegate JSC_API_AVAILABLE(macos(10.15), ios(13.0));
 
 /*!
  @method
@@ -94,8 +94,18 @@
 
  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.
  */
-- (JSValue *)evaluateJSScript:(JSScript *)script;
+// FIXME: Before making this public need to fix: https://bugs.webkit.org/show_bug.cgi?id=199714
+- (JSValue *)evaluateJSScript:(JSScript *)script JSC_API_AVAILABLE(macos(10.15), ios(13.0));
 
+/*!
+ @method
+ @abstract Get the identifiers of the modules a JSScript depends on in this context.
+ @param script the JSScript to determine the dependencies of.
+ @result An Array containing all the identifiers of modules script depends on.
+ @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.
+ */
+- (JSValue *)dependencyIdentifiersForModuleJSScript:(JSScript *)script JSC_API_AVAILABLE(macos(10.15), ios(13.0));
+
 @end
 
 #endif

Modified: trunk/Source/_javascript_Core/API/JSScript.h (247402 => 247403)


--- trunk/Source/_javascript_Core/API/JSScript.h	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/API/JSScript.h	2019-07-12 22:15:55 UTC (rev 247403)
@@ -43,7 +43,7 @@
 };
 
 
-JSC_CLASS_AVAILABLE(macos(JSC_MAC_TBA), ios(JSC_IOS_TBA))
+JSC_CLASS_AVAILABLE(macos(10.15), ios(13.0))
 @interface JSScript : NSObject
 
 /*!

Deleted: trunk/Source/_javascript_Core/API/tests/testapi-function-overrides.js (247402 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapi-function-overrides.js	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/API/tests/testapi-function-overrides.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -1,16 +0,0 @@
-// testapi function overrides for testing.
-override %%%{ /* Original f1 */ }%%%
-with %%%{ /* Overridden f1 */ }%%%
-
-override #$%{
-    // Original f2
-}#$%
-with $$${ /* Overridden f2 */ }$$$
-
-override %%%{ /* Original f3 */ }%%%
-with %%%{ /* Overridden f3 */ }%%%
-
-override %%%{
-/* Original f4 */
-}%%%
-with %%%{ /* Overridden f4 */ }%%%

Deleted: trunk/Source/_javascript_Core/API/tests/testapi.js (247402 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapi.js	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/API/tests/testapi.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -1,307 +0,0 @@
-/*
- * Copyright (C) 2006 Apple Inc.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-function bludgeonArguments() { if (0) arguments; return function g() {} }
-h = bludgeonArguments();
-gc();
-
-var failed = false;
-function pass(msg)
-{
-    print("PASS: " + msg, "green");
-}
-
-function fail(msg)
-{
-    print("FAIL: " + msg, "red");
-    failed = true;
-}
-
-function shouldBe(a, b)
-{
-    var evalA;
-    try {
-        evalA = eval(a);
-    } catch(e) {
-        evalA = e;
-    }
-    
-    if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
-        pass(a + " should be " + b + " and is.");
-    else
-        fail(a + " should be " + b + " but instead is " + evalA + ".");
-}
-
-function shouldThrow(a)
-{
-    var evalA;
-    try {
-        eval(a);
-    } catch(e) {
-        pass(a + " threw: " + e);
-        return;
-    }
-
-    fail(a + " did not throw an exception.");
-}
-
-function globalStaticFunction()
-{
-    return 4;
-}
-
-shouldBe("globalStaticValue", 3);
-shouldBe("globalStaticFunction()", 4);
-shouldBe("this.globalStaticFunction()", 4);
-
-function globalStaticFunction2() {
-    return 10;
-}
-shouldBe("globalStaticFunction2();", 10);
-this.globalStaticFunction2 = function() { return 20; }
-shouldBe("globalStaticFunction2();", 20);
-shouldBe("this.globalStaticFunction2();", 20);
-
-function iAmNotAStaticFunction() { return 10; }
-shouldBe("iAmNotAStaticFunction();", 10);
-this.iAmNotAStaticFunction = function() { return 20; }
-shouldBe("iAmNotAStaticFunction();", 20);
-
-shouldBe("typeof MyObject", "function"); // our object implements 'call'
-MyObject.cantFind = 1;
-shouldBe("MyObject.cantFind", undefined);
-MyObject.regularType = 1;
-shouldBe("MyObject.regularType", 1);
-MyObject.alwaysOne = 2;
-shouldBe("MyObject.alwaysOne", 1);
-MyObject.cantDelete = 1;
-delete MyObject.cantDelete;
-shouldBe("MyObject.cantDelete", 1);
-shouldBe("delete MyObject.throwOnDelete", "an exception");
-MyObject.cantSet = 1;
-shouldBe("MyObject.cantSet", undefined);
-shouldBe("MyObject.throwOnGet", "an exception");
-shouldBe("MyObject.throwOnSet = 5", "an exception");
-shouldBe("MyObject('throwOnCall')", "an exception");
-shouldBe("new MyObject('throwOnConstruct')", "an exception");
-shouldBe("'throwOnHasInstance' instanceof MyObject", "an exception");
-
-MyObject.nullGetForwardSet = 1;
-shouldBe("MyObject.nullGetForwardSet", 1);
-
-var foundMyPropertyName = false;
-var foundRegularType = false;
-for (var p in MyObject) {
-    if (p == "myPropertyName")
-        foundMyPropertyName = true;
-    if (p == "regularType")
-        foundRegularType = true;
-}
-
-if (foundMyPropertyName)
-    pass("MyObject.myPropertyName was enumerated");
-else
-    fail("MyObject.myPropertyName was not enumerated");
-
-if (foundRegularType)
-    pass("MyObject.regularType was enumerated");
-else
-    fail("MyObject.regularType was not enumerated");
-
-var alwaysOneDescriptor = Object.getOwnPropertyDescriptor(MyObject, "alwaysOne");
-shouldBe('typeof alwaysOneDescriptor', "object");
-shouldBe('alwaysOneDescriptor.value', MyObject.alwaysOne);
-shouldBe('alwaysOneDescriptor.configurable', true);
-shouldBe('alwaysOneDescriptor.enumerable', false); // Actually it is.
-var cantFindDescriptor = Object.getOwnPropertyDescriptor(MyObject, "cantFind");
-shouldBe('typeof cantFindDescriptor', "object");
-shouldBe('cantFindDescriptor.value', MyObject.cantFind);
-shouldBe('cantFindDescriptor.configurable', true);
-shouldBe('cantFindDescriptor.enumerable', false);
-try {
-    // If getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
-    Object.getOwnPropertyDescriptor(MyObject, "throwOnGet");
-} catch (e) {
-    pass("getting property descriptor of throwOnGet threw exception");
-}
-var myPropertyNameDescriptor = Object.getOwnPropertyDescriptor(MyObject, "myPropertyName");
-shouldBe('typeof myPropertyNameDescriptor', "object");
-shouldBe('myPropertyNameDescriptor.value', MyObject.myPropertyName);
-shouldBe('myPropertyNameDescriptor.configurable', true);
-shouldBe('myPropertyNameDescriptor.enumerable', false); // Actually it is.
-try {
-    // if getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
-    Object.getOwnPropertyDescriptor(MyObject, "hasPropertyLie");
-} catch (e) {
-    pass("getting property descriptor of hasPropertyLie threw exception");
-}
-shouldBe('Object.getOwnPropertyDescriptor(MyObject, "doesNotExist")', undefined);
-
-myObject = new MyObject();
-
-shouldBe("delete MyObject.regularType", true);
-shouldBe("MyObject.regularType", undefined);
-shouldBe("MyObject(0)", 1);
-shouldBe("MyObject()", undefined);
-shouldBe("typeof myObject", "object");
-shouldBe("MyObject ? 1 : 0", true); // toBoolean
-shouldBe("+MyObject", 1); // toNumber
-shouldBe("(Object.prototype.toString.call(MyObject))", "[object MyObject]"); // Object.prototype.toString
-shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
-shouldBe("String(MyObject)", "MyObjectAsString"); // toString
-shouldBe("MyObject - 0", 1); // toNumber
-shouldBe("MyObject.valueOf()", 1); // valueOf
-
-shouldBe("typeof MyConstructor", "object");
-constructedObject = new MyConstructor(1);
-shouldBe("typeof constructedObject", "object");
-shouldBe("constructedObject.value", 1);
-shouldBe("myObject instanceof MyObject", true);
-shouldBe("(new Object()) instanceof MyObject", false);
-
-shouldThrow("new MyBadConstructor()");
-
-MyObject.nullGetSet = 1;
-shouldBe("MyObject.nullGetSet", 1);
-shouldThrow("MyObject.nullCall()");
-shouldThrow("MyObject.hasPropertyLie");
-
-derived = new Derived();
-
-shouldBe("derived instanceof Derived", true);
-shouldBe("derived instanceof Base", true);
-
-// base properties and functions return 1 when called/gotten; derived, 2
-shouldBe("derived.baseProtoDup()", 2);
-shouldBe("derived.baseProto()", 1);
-shouldBe("derived.baseDup", 2);
-shouldBe("derived.baseOnly", 1);
-shouldBe("derived.protoOnly()", 2);
-shouldBe("derived.protoDup", 2);
-shouldBe("derived.derivedOnly", 2)
-
-shouldBe("derived.baseHardNull()", undefined)
-
-// base properties throw 1 when set; derived, 2
-shouldBe("derived.baseDup = 0", 2);
-shouldBe("derived.baseOnly = 0", 1);
-shouldBe("derived.derivedOnly = 0", 2)
-shouldBe("derived.protoDup = 0", 2);
-
-derived2 = new Derived2();
-
-shouldBe("derived2 instanceof Derived2", true);
-shouldBe("derived2 instanceof Derived", true);
-shouldBe("derived2 instanceof Base", true);
-
-// base properties and functions return 1 when called/gotten; derived, 2
-shouldBe("derived2.baseProtoDup()", 2);
-shouldBe("derived2.baseProto()", 1);
-shouldBe("derived2.baseDup", 2);
-shouldBe("derived2.baseOnly", 1);
-shouldBe("derived2.protoOnly()", 2);
-shouldBe("derived2.protoDup", 2);
-shouldBe("derived2.derivedOnly", 2)
-
-// base properties throw 1 when set; derived, 2
-shouldBe("derived2.baseDup = 0", 2);
-shouldBe("derived2.baseOnly = 0", 1);
-shouldBe("derived2.derivedOnly = 0", 2)
-shouldBe("derived2.protoDup = 0", 2);
-
-shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProto")', undefined);
-shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProtoDup")', undefined);
-var baseDupDescriptor = Object.getOwnPropertyDescriptor(derived, "baseDup");
-shouldBe('typeof baseDupDescriptor', "object");
-shouldBe('baseDupDescriptor.value', derived.baseDup);
-shouldBe('baseDupDescriptor.configurable', true);
-shouldBe('baseDupDescriptor.enumerable', false);
-var baseOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "baseOnly");
-shouldBe('typeof baseOnlyDescriptor', "object");
-shouldBe('baseOnlyDescriptor.value', derived.baseOnly);
-shouldBe('baseOnlyDescriptor.configurable', true);
-shouldBe('baseOnlyDescriptor.enumerable', false);
-shouldBe('Object.getOwnPropertyDescriptor(derived, "protoOnly")', undefined);
-var protoDupDescriptor = Object.getOwnPropertyDescriptor(derived, "protoDup");
-shouldBe('typeof protoDupDescriptor', "object");
-shouldBe('protoDupDescriptor.value', derived.protoDup);
-shouldBe('protoDupDescriptor.configurable', true);
-shouldBe('protoDupDescriptor.enumerable', false);
-var derivedOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "derivedOnly");
-shouldBe('typeof derivedOnlyDescriptor', "object");
-shouldBe('derivedOnlyDescriptor.value', derived.derivedOnly);
-shouldBe('derivedOnlyDescriptor.configurable', true);
-shouldBe('derivedOnlyDescriptor.enumerable', false);
-
-shouldBe("undefined instanceof MyObject", false);
-EvilExceptionObject.hasInstance = function f() { return f(); };
-EvilExceptionObject.__proto__ = undefined;
-shouldThrow("undefined instanceof EvilExceptionObject");
-EvilExceptionObject.hasInstance = function () { return true; };
-shouldBe("undefined instanceof EvilExceptionObject", true);
-
-EvilExceptionObject.toNumber = function f() { return f(); }
-shouldThrow("EvilExceptionObject*5");
-EvilExceptionObject.toStringExplicit = function f() { return f(); }
-shouldThrow("String(EvilExceptionObject)");
-
-shouldBe("console", "[object Console]");
-shouldBe("typeof console.log", "function");
-
-shouldBe("EmptyObject", "[object CallbackObject]");
-
-for (var i = 0; i < 6; ++i)
-    PropertyCatchalls.x = i;
-shouldBe("PropertyCatchalls.x", 4);
-
-for (var i = 0; i < 6; ++i)
-    var x = PropertyCatchalls.x;
-shouldBe("x", null);
-var make_throw = 'make_throw';
-shouldThrow("PropertyCatchalls[make_throw]=1");
-make_throw = 0;
-shouldThrow("PropertyCatchalls[make_throw]=1");
-
-for (var i = 0; i < 10; ++i) {
-    for (var p in PropertyCatchalls) {
-        if (p == "x")
-            continue;
-        shouldBe("p", i % 10);
-        break;
-    }
-}
-
-PropertyCatchalls.__proto__ = { y: 1 };
-for (var i = 0; i < 6; ++i)
-    var y = PropertyCatchalls.y;
-shouldBe("y", null);
-
-var o = { __proto__: PropertyCatchalls };
-for (var i = 0; i < 6; ++i)
-    var z = PropertyCatchalls.z;
-shouldBe("z", null);
-
-if (failed)
-    throw "Some tests failed";

Modified: trunk/Source/_javascript_Core/API/tests/testapi.mm (247402 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapi.mm	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/API/tests/testapi.mm	2019-07-12 22:15:55 UTC (rev 247403)
@@ -1946,7 +1946,7 @@
                     error:nil]]];
             } else if ([identifier isEqualToObject:@"file:///foo.js"]) {
                 [resolve callWithArguments:@[[JSScript scriptOfType:kJSScriptTypeModule 
-                    withSource:@"import \"directory/bar.js\"; globalThis.ran = null; export let n = null;"
+                    withSource:@"import \"./directory/bar.js\"; globalThis.ran = null; export let n = null;"
                     andSourceURL:[NSURL fileURLWithPath:@"/foo.js"]
                     andBytecodeCache:nil
                     inVirtualMachine:[context virtualMachine]
@@ -1977,7 +1977,7 @@
                     error:nil]]];
             } else if ([identifier isEqualToObject:@"file:///foo.js"]) {
                 [resolve callWithArguments:@[[JSScript scriptOfType:kJSScriptTypeModule 
-                    withSource:@"import \"otherDirectory/baz.js\"; export let n = null;"
+                    withSource:@"import \"./otherDirectory/baz.js\"; export let n = null;"
                     andSourceURL:[NSURL fileURLWithPath:@"/foo.js"] 
                     andBytecodeCache:nil
                     inVirtualMachine:[context virtualMachine]
@@ -2107,7 +2107,7 @@
 static void testModuleBytecodeCache()
 {
     @autoreleasepool {
-        NSString *fooSource = @"import 'otherDirectory/baz.js'; export let n = null;";
+        NSString *fooSource = @"import './otherDirectory/baz.js'; export let n = null;";
         NSString *barSource = @"import { n } from '../foo.js'; export let foo = () => n;";
         NSString *bazSource = @"import { foo } from '../directory/bar.js'; globalThis.ran = null; export let exp = foo();";
 
@@ -2428,15 +2428,19 @@
 @interface JSContextFileLoaderDelegate : JSContext <JSModuleLoaderDelegate>
 
 + (instancetype)newContext;
+- (JSScript *)fetchModuleScript:(NSString *)relativePath;
 
 @end
 
 @implementation JSContextFileLoaderDelegate {
+    NSMutableDictionary<NSString *, JSScript *> *m_keyToScript;
 }
 
 + (instancetype)newContext
 {
     auto *result = [[JSContextFileLoaderDelegate alloc] init];
+    result.moduleLoaderDelegate = result;
+    result->m_keyToScript = [[NSMutableDictionary<NSString *, JSScript *> alloc] init];
     return result;
 }
 
@@ -2459,9 +2463,35 @@
     return [NSURL fileURLWithPath:@"./testapiScripts/" isDirectory:YES relativeToURL:base];
 }
 
+- (JSScript *)fetchModuleScript:(NSString *)relativePath
+{
+    auto *filePath = [NSURL URLWithString:relativePath relativeToURL:resolvePathToScripts()];
+    if (auto *script = [self findScriptForKey:[filePath absoluteString]])
+        return script;
+    NSError *error;
+    auto *result = [JSScript scriptOfType:kJSScriptTypeModule memoryMappedFromASCIIFile:filePath withSourceURL:filePath andBytecodeCache:nil inVirtualMachine:[self virtualMachine] error:&error];
+    if (!result) {
+        NSLog(@"%@\n", error);
+        CRASH();
+    }
+    [m_keyToScript setObject:result forKey:[filePath absoluteString]];
+    return result;
+}
+
+- (JSScript *)findScriptForKey:(NSString *)key
+{
+    return [m_keyToScript objectForKey:key];
+}
+
 - (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject
 {
     NSURL *filePath = [NSURL URLWithString:[identifier toString]];
+    // FIXME: We should fix this: https://bugs.webkit.org/show_bug.cgi?id=199714
+    if (auto *script = [self findScriptForKey:[identifier toString]]) {
+        [resolve callWithArguments:@[script]];
+        return;
+    }
+
     auto* script = [JSScript scriptOfType:kJSScriptTypeModule
         memoryMappedFromASCIIFile:filePath
         withSourceURL:filePath
@@ -2468,9 +2498,10 @@
         andBytecodeCache:nil 
         inVirtualMachine:context.virtualMachine
         error:nil];
-    if (script)
+    if (script) {
+        [m_keyToScript setObject:script forKey:[identifier toString]];
         [resolve callWithArguments:@[script]];
-    else
+    } else
         [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Unable to create Script" inContext:context]]];
 }
 
@@ -2604,7 +2635,112 @@
     }
 }
 
+static void testDependenciesArray()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFileLoaderDelegate newContext];
 
+        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/dependenciesEntry.js"];
+
+        JSValue *promise = [context evaluateJSScript:entryScript];
+        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
+            checkResult(@"module ran successfully", true);
+        }, ^(JSValue *) {
+            checkResult(@"module ran successfully", false);
+        }]];
+
+        checkResult(@"looking up the entry script should find the same script again.", [context findScriptForKey:[entryScript.sourceURL absoluteString]] == entryScript);
+
+        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
+
+        checkResult(@"deps should be an array", [deps isArray]);
+        checkResult(@"deps should have two entries", [deps[@"length"] isEqualToObject:@(2)]);
+
+        checkResult(@"first dependency should be foo.js", [[[[context fetchModuleScript:@"./dependencyListTests/foo.js"] sourceURL] absoluteString] isEqual:[deps[@(0)] toString]]);
+        checkResult(@"second dependency should be bar.js", [[[[context fetchModuleScript:@"./dependencyListTests/bar.js"] sourceURL] absoluteString] isEqual:[deps[@(1)] toString]]);
+    }
+}
+
+static void testDependenciesEvaluationError()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFileLoaderDelegate newContext];
+
+        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/referenceError.js"];
+
+        JSValue *promise = [context evaluateJSScript:entryScript];
+        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
+            checkResult(@"module failed successfully", false);
+        }, ^(JSValue *) {
+            checkResult(@"module failed successfully", true);
+        }]];
+
+        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
+        checkResult(@"deps should be an Array", [deps isArray]);
+        checkResult(@"first dependency should be foo.js", [[[[context fetchModuleScript:@"./dependencyListTests/foo.js"] sourceURL] absoluteString] isEqual:[deps[@(0)] toString]]);
+    }
+}
+
+static void testDependenciesSyntaxError()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFileLoaderDelegate newContext];
+
+        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/syntaxError.js"];
+
+        JSValue *promise = [context evaluateJSScript:entryScript];
+        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
+            checkResult(@"module failed successfully", false);
+        }, ^(JSValue *) {
+            checkResult(@"module failed successfully", true);
+        }]];
+
+        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
+        checkResult(@"deps should be undefined", [deps isUndefined]);
+        checkResult(@"there should be a pending exception on the context", context.exception);
+    }
+}
+
+static void testDependenciesBadImportId()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFileLoaderDelegate newContext];
+
+        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/badModuleImportId.js"];
+
+        JSValue *promise = [context evaluateJSScript:entryScript];
+        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
+            checkResult(@"module failed successfully", false);
+        }, ^(JSValue *) {
+            checkResult(@"module failed successfully", true);
+        }]];
+
+        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
+        checkResult(@"deps should be undefined", [deps isUndefined]);
+        checkResult(@"there should be a pending exception on the context", context.exception);
+    }
+}
+
+static void testDependenciesMissingImport()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFileLoaderDelegate newContext];
+
+        JSScript *entryScript = [context fetchModuleScript:@"./dependencyListTests/missingImport.js"];
+
+        JSValue *promise = [context evaluateJSScript:entryScript];
+        [promise invokeMethod:@"then" withArguments:@[^(JSValue *) {
+            checkResult(@"module failed successfully", false);
+        }, ^(JSValue *) {
+            checkResult(@"module failed successfully", true);
+        }]];
+
+        auto *deps = [context dependencyIdentifiersForModuleJSScript:entryScript];
+        checkResult(@"deps should be undefined", [deps isUndefined]);
+        checkResult(@"there should be a pending exception on the context", context.exception);
+    }
+}
+
 @protocol ToString <JSExport>
 - (NSString *)toString;
 @end
@@ -2708,6 +2844,12 @@
     RUN(testLoadBasicFileLegacySPI());
     RUN(testLoadBasicFile());
 
+    RUN(testDependenciesArray());
+    RUN(testDependenciesSyntaxError());
+    RUN(testDependenciesEvaluationError());
+    RUN(testDependenciesBadImportId());
+    RUN(testDependenciesMissingImport());
+
     RUN(promiseWithExecutor(Resolution::ResolveEager));
     RUN(promiseWithExecutor(Resolution::RejectEager));
     RUN(promiseWithExecutor(Resolution::ResolveLate));

Added: trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/badModuleImportId.js (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/badModuleImportId.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/badModuleImportId.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1,3 @@
+
+// This is not a valid identfier for an import so it will fail to import.
+import "sethua"

Added: trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/bar.js (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/bar.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/bar.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1 @@
+export let hello = 1;

Added: trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/dependenciesEntry.js (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/dependenciesEntry.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/dependenciesEntry.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1,2 @@
+import "./foo.js";
+import "./bar.js";

Added: trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/foo.js (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/foo.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/foo.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1 @@
+export let things = null;

Added: trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/missingImport.js (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/missingImport.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/missingImport.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1 @@
+import "./file-that-does-not-exist.js"

Added: trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/referenceError.js (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/referenceError.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/referenceError.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1,3 @@
+import "./foo.js";
+
+tosehuas;

Added: trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/syntaxError.js (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/syntaxError.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/dependencyListTests/syntaxError.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1,3 @@
+import "./foo.js";
+
+theoasutas thea tehlr  ebsa;

Copied: trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi-function-overrides.js (from rev 247402, trunk/Source/_javascript_Core/API/tests/testapi-function-overrides.js) (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi-function-overrides.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi-function-overrides.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1,16 @@
+// testapi function overrides for testing.
+override %%%{ /* Original f1 */ }%%%
+with %%%{ /* Overridden f1 */ }%%%
+
+override #$%{
+    // Original f2
+}#$%
+with $$${ /* Overridden f2 */ }$$$
+
+override %%%{ /* Original f3 */ }%%%
+with %%%{ /* Overridden f3 */ }%%%
+
+override %%%{
+/* Original f4 */
+}%%%
+with %%%{ /* Overridden f4 */ }%%%

Copied: trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js (from rev 247402, trunk/Source/_javascript_Core/API/tests/testapi.js) (0 => 247403)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/testapi.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2006 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+function bludgeonArguments() { if (0) arguments; return function g() {} }
+h = bludgeonArguments();
+gc();
+
+var failed = false;
+function pass(msg)
+{
+    print("PASS: " + msg, "green");
+}
+
+function fail(msg)
+{
+    print("FAIL: " + msg, "red");
+    failed = true;
+}
+
+function shouldBe(a, b)
+{
+    var evalA;
+    try {
+        evalA = eval(a);
+    } catch(e) {
+        evalA = e;
+    }
+    
+    if (evalA == b || isNaN(evalA) && typeof evalA == 'number' && isNaN(b) && typeof b == 'number')
+        pass(a + " should be " + b + " and is.");
+    else
+        fail(a + " should be " + b + " but instead is " + evalA + ".");
+}
+
+function shouldThrow(a)
+{
+    var evalA;
+    try {
+        eval(a);
+    } catch(e) {
+        pass(a + " threw: " + e);
+        return;
+    }
+
+    fail(a + " did not throw an exception.");
+}
+
+function globalStaticFunction()
+{
+    return 4;
+}
+
+shouldBe("globalStaticValue", 3);
+shouldBe("globalStaticFunction()", 4);
+shouldBe("this.globalStaticFunction()", 4);
+
+function globalStaticFunction2() {
+    return 10;
+}
+shouldBe("globalStaticFunction2();", 10);
+this.globalStaticFunction2 = function() { return 20; }
+shouldBe("globalStaticFunction2();", 20);
+shouldBe("this.globalStaticFunction2();", 20);
+
+function iAmNotAStaticFunction() { return 10; }
+shouldBe("iAmNotAStaticFunction();", 10);
+this.iAmNotAStaticFunction = function() { return 20; }
+shouldBe("iAmNotAStaticFunction();", 20);
+
+shouldBe("typeof MyObject", "function"); // our object implements 'call'
+MyObject.cantFind = 1;
+shouldBe("MyObject.cantFind", undefined);
+MyObject.regularType = 1;
+shouldBe("MyObject.regularType", 1);
+MyObject.alwaysOne = 2;
+shouldBe("MyObject.alwaysOne", 1);
+MyObject.cantDelete = 1;
+delete MyObject.cantDelete;
+shouldBe("MyObject.cantDelete", 1);
+shouldBe("delete MyObject.throwOnDelete", "an exception");
+MyObject.cantSet = 1;
+shouldBe("MyObject.cantSet", undefined);
+shouldBe("MyObject.throwOnGet", "an exception");
+shouldBe("MyObject.throwOnSet = 5", "an exception");
+shouldBe("MyObject('throwOnCall')", "an exception");
+shouldBe("new MyObject('throwOnConstruct')", "an exception");
+shouldBe("'throwOnHasInstance' instanceof MyObject", "an exception");
+
+MyObject.nullGetForwardSet = 1;
+shouldBe("MyObject.nullGetForwardSet", 1);
+
+var foundMyPropertyName = false;
+var foundRegularType = false;
+for (var p in MyObject) {
+    if (p == "myPropertyName")
+        foundMyPropertyName = true;
+    if (p == "regularType")
+        foundRegularType = true;
+}
+
+if (foundMyPropertyName)
+    pass("MyObject.myPropertyName was enumerated");
+else
+    fail("MyObject.myPropertyName was not enumerated");
+
+if (foundRegularType)
+    pass("MyObject.regularType was enumerated");
+else
+    fail("MyObject.regularType was not enumerated");
+
+var alwaysOneDescriptor = Object.getOwnPropertyDescriptor(MyObject, "alwaysOne");
+shouldBe('typeof alwaysOneDescriptor', "object");
+shouldBe('alwaysOneDescriptor.value', MyObject.alwaysOne);
+shouldBe('alwaysOneDescriptor.configurable', true);
+shouldBe('alwaysOneDescriptor.enumerable', false); // Actually it is.
+var cantFindDescriptor = Object.getOwnPropertyDescriptor(MyObject, "cantFind");
+shouldBe('typeof cantFindDescriptor', "object");
+shouldBe('cantFindDescriptor.value', MyObject.cantFind);
+shouldBe('cantFindDescriptor.configurable', true);
+shouldBe('cantFindDescriptor.enumerable', false);
+try {
+    // If getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
+    Object.getOwnPropertyDescriptor(MyObject, "throwOnGet");
+} catch (e) {
+    pass("getting property descriptor of throwOnGet threw exception");
+}
+var myPropertyNameDescriptor = Object.getOwnPropertyDescriptor(MyObject, "myPropertyName");
+shouldBe('typeof myPropertyNameDescriptor', "object");
+shouldBe('myPropertyNameDescriptor.value', MyObject.myPropertyName);
+shouldBe('myPropertyNameDescriptor.configurable', true);
+shouldBe('myPropertyNameDescriptor.enumerable', false); // Actually it is.
+try {
+    // if getOwnPropertyDescriptor() returned an access descriptor, this wouldn't throw.
+    Object.getOwnPropertyDescriptor(MyObject, "hasPropertyLie");
+} catch (e) {
+    pass("getting property descriptor of hasPropertyLie threw exception");
+}
+shouldBe('Object.getOwnPropertyDescriptor(MyObject, "doesNotExist")', undefined);
+
+myObject = new MyObject();
+
+shouldBe("delete MyObject.regularType", true);
+shouldBe("MyObject.regularType", undefined);
+shouldBe("MyObject(0)", 1);
+shouldBe("MyObject()", undefined);
+shouldBe("typeof myObject", "object");
+shouldBe("MyObject ? 1 : 0", true); // toBoolean
+shouldBe("+MyObject", 1); // toNumber
+shouldBe("(Object.prototype.toString.call(MyObject))", "[object MyObject]"); // Object.prototype.toString
+shouldBe("(MyObject.toString())", "[object MyObject]"); // toString
+shouldBe("String(MyObject)", "MyObjectAsString"); // toString
+shouldBe("MyObject - 0", 1); // toNumber
+shouldBe("MyObject.valueOf()", 1); // valueOf
+
+shouldBe("typeof MyConstructor", "object");
+constructedObject = new MyConstructor(1);
+shouldBe("typeof constructedObject", "object");
+shouldBe("constructedObject.value", 1);
+shouldBe("myObject instanceof MyObject", true);
+shouldBe("(new Object()) instanceof MyObject", false);
+
+shouldThrow("new MyBadConstructor()");
+
+MyObject.nullGetSet = 1;
+shouldBe("MyObject.nullGetSet", 1);
+shouldThrow("MyObject.nullCall()");
+shouldThrow("MyObject.hasPropertyLie");
+
+derived = new Derived();
+
+shouldBe("derived instanceof Derived", true);
+shouldBe("derived instanceof Base", true);
+
+// base properties and functions return 1 when called/gotten; derived, 2
+shouldBe("derived.baseProtoDup()", 2);
+shouldBe("derived.baseProto()", 1);
+shouldBe("derived.baseDup", 2);
+shouldBe("derived.baseOnly", 1);
+shouldBe("derived.protoOnly()", 2);
+shouldBe("derived.protoDup", 2);
+shouldBe("derived.derivedOnly", 2)
+
+shouldBe("derived.baseHardNull()", undefined)
+
+// base properties throw 1 when set; derived, 2
+shouldBe("derived.baseDup = 0", 2);
+shouldBe("derived.baseOnly = 0", 1);
+shouldBe("derived.derivedOnly = 0", 2)
+shouldBe("derived.protoDup = 0", 2);
+
+derived2 = new Derived2();
+
+shouldBe("derived2 instanceof Derived2", true);
+shouldBe("derived2 instanceof Derived", true);
+shouldBe("derived2 instanceof Base", true);
+
+// base properties and functions return 1 when called/gotten; derived, 2
+shouldBe("derived2.baseProtoDup()", 2);
+shouldBe("derived2.baseProto()", 1);
+shouldBe("derived2.baseDup", 2);
+shouldBe("derived2.baseOnly", 1);
+shouldBe("derived2.protoOnly()", 2);
+shouldBe("derived2.protoDup", 2);
+shouldBe("derived2.derivedOnly", 2)
+
+// base properties throw 1 when set; derived, 2
+shouldBe("derived2.baseDup = 0", 2);
+shouldBe("derived2.baseOnly = 0", 1);
+shouldBe("derived2.derivedOnly = 0", 2)
+shouldBe("derived2.protoDup = 0", 2);
+
+shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProto")', undefined);
+shouldBe('Object.getOwnPropertyDescriptor(derived, "baseProtoDup")', undefined);
+var baseDupDescriptor = Object.getOwnPropertyDescriptor(derived, "baseDup");
+shouldBe('typeof baseDupDescriptor', "object");
+shouldBe('baseDupDescriptor.value', derived.baseDup);
+shouldBe('baseDupDescriptor.configurable', true);
+shouldBe('baseDupDescriptor.enumerable', false);
+var baseOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "baseOnly");
+shouldBe('typeof baseOnlyDescriptor', "object");
+shouldBe('baseOnlyDescriptor.value', derived.baseOnly);
+shouldBe('baseOnlyDescriptor.configurable', true);
+shouldBe('baseOnlyDescriptor.enumerable', false);
+shouldBe('Object.getOwnPropertyDescriptor(derived, "protoOnly")', undefined);
+var protoDupDescriptor = Object.getOwnPropertyDescriptor(derived, "protoDup");
+shouldBe('typeof protoDupDescriptor', "object");
+shouldBe('protoDupDescriptor.value', derived.protoDup);
+shouldBe('protoDupDescriptor.configurable', true);
+shouldBe('protoDupDescriptor.enumerable', false);
+var derivedOnlyDescriptor = Object.getOwnPropertyDescriptor(derived, "derivedOnly");
+shouldBe('typeof derivedOnlyDescriptor', "object");
+shouldBe('derivedOnlyDescriptor.value', derived.derivedOnly);
+shouldBe('derivedOnlyDescriptor.configurable', true);
+shouldBe('derivedOnlyDescriptor.enumerable', false);
+
+shouldBe("undefined instanceof MyObject", false);
+EvilExceptionObject.hasInstance = function f() { return f(); };
+EvilExceptionObject.__proto__ = undefined;
+shouldThrow("undefined instanceof EvilExceptionObject");
+EvilExceptionObject.hasInstance = function () { return true; };
+shouldBe("undefined instanceof EvilExceptionObject", true);
+
+EvilExceptionObject.toNumber = function f() { return f(); }
+shouldThrow("EvilExceptionObject*5");
+EvilExceptionObject.toStringExplicit = function f() { return f(); }
+shouldThrow("String(EvilExceptionObject)");
+
+shouldBe("console", "[object Console]");
+shouldBe("typeof console.log", "function");
+
+shouldBe("EmptyObject", "[object CallbackObject]");
+
+for (var i = 0; i < 6; ++i)
+    PropertyCatchalls.x = i;
+shouldBe("PropertyCatchalls.x", 4);
+
+for (var i = 0; i < 6; ++i)
+    var x = PropertyCatchalls.x;
+shouldBe("x", null);
+var make_throw = 'make_throw';
+shouldThrow("PropertyCatchalls[make_throw]=1");
+make_throw = 0;
+shouldThrow("PropertyCatchalls[make_throw]=1");
+
+for (var i = 0; i < 10; ++i) {
+    for (var p in PropertyCatchalls) {
+        if (p == "x")
+            continue;
+        shouldBe("p", i % 10);
+        break;
+    }
+}
+
+PropertyCatchalls.__proto__ = { y: 1 };
+for (var i = 0; i < 6; ++i)
+    var y = PropertyCatchalls.y;
+shouldBe("y", null);
+
+var o = { __proto__: PropertyCatchalls };
+for (var i = 0; i < 6; ++i)
+    var z = PropertyCatchalls.z;
+shouldBe("z", null);
+
+if (failed)
+    throw "Some tests failed";

Modified: trunk/Source/_javascript_Core/ChangeLog (247402 => 247403)


--- trunk/Source/_javascript_Core/ChangeLog	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-07-12 22:15:55 UTC (rev 247403)
@@ -1,3 +1,65 @@
+2019-07-12  Keith Miller  <keith_mil...@apple.com>
+
+        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/_javascript_Core/API/tests/testapi-function-overrides.js.
+        * API/tests/testapiScripts/testapi.js: Renamed from Source/_javascript_Core/API/tests/testapi.js.
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * builtins/ModuleLoader.js:
+        (dependencyKeysIfEvaluated):
+        * runtime/JSModuleLoader.cpp:
+        (JSC::JSModuleLoader::dependencyKeysIfEvaluated):
+        * runtime/JSModuleLoader.h:
+        * shell/CMakeLists.txt:
+
 2019-07-12  Justin Michaud  <justin_mich...@apple.com>
 
         B3 should reduce (integer) Sub(Neg(x), y) to Neg(Add(x, y))

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (247402 => 247403)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-07-12 22:15:55 UTC (rev 247403)
@@ -898,7 +898,6 @@
 		52CD0F5D2242F569004A18A5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
 		52CD0F5E2242F569004A18A5 /* _javascript_Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 932F5BD90822A1C700736975 /* _javascript_Core.framework */; };
 		52CD0F682242F71C004A18A5 /* testdfg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52CD0F672242F71C004A18A5 /* testdfg.cpp */; };
-		52D13091221CE176009C836C /* foo.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 52D1308F221CE03A009C836C /* foo.js */; };
 		52F6C35E1E71EB080081F4CC /* WebAssemblyWrapperFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 52F6C35C1E71EB080081F4CC /* WebAssemblyWrapperFunction.h */; };
 		530A66B91FA3E78B0026A545 /* UnifiedSource3-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 530A66B11FA3E77A0026A545 /* UnifiedSource3-mm.mm */; };
 		530A66BA1FA3E78B0026A545 /* UnifiedSource4-mm.mm in Sources */ = {isa = PBXBuildFile; fileRef = 530A66B81FA3E77E0026A545 /* UnifiedSource4-mm.mm */; };
@@ -1082,7 +1081,6 @@
 		539FB8BA1C99DA7C00940FA1 /* JSArrayInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 539FB8B91C99DA7C00940FA1 /* JSArrayInlines.h */; };
 		53B4BD121F68B32500D2BEA3 /* WasmOps.h in Headers */ = {isa = PBXBuildFile; fileRef = 533B15DE1DC7F463004D500A /* WasmOps.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		53B601EC2034B8C5006BE667 /* JSCast.h in Headers */ = {isa = PBXBuildFile; fileRef = 53B601EB2034B8C5006BE667 /* JSCast.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 53C3D5E421ECE6CE0087FDFC /* basic.js */; };
 		53C4F66B21B1A409002FD009 /* JSAPIGlobalObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 53C4F66A21B1A409002FD009 /* JSAPIGlobalObject.h */; };
 		53C6FEEF1E8ADFA900B18425 /* WasmOpcodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 53C6FEEE1E8ADFA900B18425 /* WasmOpcodeOrigin.h */; };
 		53CA730A1EA533D80076049D /* WasmBBQPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 53CA73081EA533D80076049D /* WasmBBQPlan.h */; };
@@ -1111,7 +1109,6 @@
 		5C4196622270E0000047B7CD /* InspectorBackendDispatcherCompatibility.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C4196612270DFF30047B7CD /* InspectorBackendDispatcherCompatibility.cpp */; };
 		5C4E8E961DBEBE620036F1FC /* JSONParseTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5C4E8E941DBEBDA20036F1FC /* JSONParseTest.cpp */; };
 		5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; };
-		5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; };
 		5DBB1525131D0BD70056AD36 /* minidom.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 1412110D0A48788700480255 /* minidom.js */; };
 		5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (); }; };
 		623A37EC1B87A7C000754209 /* RegisterMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 623A37EB1B87A7BD00754209 /* RegisterMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -1287,10 +1284,10 @@
 		933040040E6A749400786E6A /* SmallStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 93303FEA0E6A72C000786E6A /* SmallStrings.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		960097A60EBABB58007A7297 /* LabelScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 960097A50EBABB58007A7297 /* LabelScope.h */; };
 		9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB130ED12B4E001D649F /* AssemblerBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		9688CB160ED12B4E001D6491 /* X86Registers.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D6491 /* X86Registers.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		9688CB160ED12B4E001D6492 /* X86_64Registers.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D6492 /* X86_64Registers.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		9688CB160ED12B4E001D6499 /* RegisterInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D6499 /* RegisterInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9688CB140ED12B4E001D649F /* X86Assembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		969A07230ED1CE3300F1F681 /* BytecodeGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */; };
 		969A072A0ED1CE6900F1F681 /* Label.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07270ED1CE6900F1F681 /* Label.h */; };
 		969A072B0ED1CE6900F1F681 /* RegisterID.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07280ED1CE6900F1F681 /* RegisterID.h */; };
@@ -1885,7 +1882,6 @@
 		FEB51F6C1A97B688001F921C /* Regress141809.mm in Sources */ = {isa = PBXBuildFile; fileRef = FEB51F6B1A97B688001F921C /* Regress141809.mm */; };
 		FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FEB58C13187B8B160098EF0B /* ErrorHandlingScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FECB8B271D25BB85006F2463 /* FunctionOverridesTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FECB8B251D25BB6E006F2463 /* FunctionOverridesTest.cpp */; };
-		FECB8B2A1D25CB5A006F2463 /* testapi-function-overrides.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = FECB8B291D25CABB006F2463 /* testapi-function-overrides.js */; };
 		FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */ = {isa = PBXBuildFile; fileRef = FED287B115EC9A5700DA8161 /* LLIntOpcode.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FED94F2F171E3E2300BE77A4 /* Watchdog.h in Headers */ = {isa = PBXBuildFile; fileRef = FED94F2C171E3E2300BE77A4 /* Watchdog.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		FEF040511AAE662D00BD28B0 /* CompareAndSwapTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */; };
@@ -2079,20 +2075,6 @@
 /* End PBXContainerItemProxy section */
 
 /* Begin PBXCopyFilesBuildPhase section */
-		5DBB1511131D0B130056AD36 /* Copy Support Script */ = {
-			isa = PBXCopyFilesBuildPhase;
-			buildActionMask = 12;
-			dstPath = testapiScripts;
-			dstSubfolderSpec = 16;
-			files = (
-				53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */,
-				52D13091221CE176009C836C /* foo.js in Copy Support Script */,
-				FECB8B2A1D25CB5A006F2463 /* testapi-function-overrides.js in Copy Support Script */,
-				5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */,
-			);
-			name = "Copy Support Script";
-			runOnlyForDeploymentPostprocessing = 0;
-		};
 		5DBB1524131D0BA10056AD36 /* Copy Support Script */ = {
 			isa = PBXCopyFilesBuildPhase;
 			buildActionMask = 2147483647;
@@ -4082,10 +4064,10 @@
 		95C18D3E0C90E7EF00E72F73 /* JSRetainPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSRetainPtr.h; sourceTree = "<group>"; };
 		960097A50EBABB58007A7297 /* LabelScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelScope.h; sourceTree = "<group>"; };
 		9688CB130ED12B4E001D649F /* AssemblerBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssemblerBuffer.h; sourceTree = "<group>"; };
-		9688CB140ED12B4E001D649F /* X86Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Assembler.h; sourceTree = "<group>"; };
 		9688CB140ED12B4E001D6491 /* X86Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Registers.h; sourceTree = "<group>"; };
 		9688CB140ED12B4E001D6492 /* X86_64Registers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86_64Registers.h; sourceTree = "<group>"; };
 		9688CB140ED12B4E001D6499 /* RegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterInfo.h; sourceTree = "<group>"; };
+		9688CB140ED12B4E001D649F /* X86Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86Assembler.h; sourceTree = "<group>"; };
 		969A07200ED1CE3300F1F681 /* BytecodeGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BytecodeGenerator.cpp; sourceTree = "<group>"; };
 		969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeGenerator.h; sourceTree = "<group>"; };
 		969A07270ED1CE6900F1F681 /* Label.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Label.h; sourceTree = "<group>"; };
@@ -7910,9 +7892,9 @@
 				FE10AAEA1F44D512009DEDC5 /* ProbeStack.h */,
 				9688CB140ED12B4E001D6499 /* RegisterInfo.h */,
 				FE533CA01F217C310016A1FE /* testmasm.cpp */,
+				9688CB140ED12B4E001D6492 /* X86_64Registers.h */,
 				9688CB140ED12B4E001D649F /* X86Assembler.h */,
 				9688CB140ED12B4E001D6491 /* X86Registers.h */,
-				9688CB140ED12B4E001D6492 /* X86_64Registers.h */,
 			);
 			path = assembler;
 			sourceTree = "<group>";
@@ -8656,7 +8638,7 @@
 				0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */,
 				A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
 				FE1E2C402240DD6200F6B729 /* ARM64EAssembler.h in Headers */,
-				A1A009C11831A26E00CF8722 /* ARM64Registers.h */,
+				A1A009C11831A26E00CF8722 /* ARM64Registers.h in Headers */,
 				86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
 				86ADD1450FDDEA980006FFCC /* ARMv7Registers.h in Headers */,
 				0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */,
@@ -10098,9 +10080,9 @@
 				A7DCB97312E5193F00911940 /* WriteBarrier.h in Headers */,
 				C2B6D75318A33793004A9301 /* WriteBarrierInlines.h in Headers */,
 				0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */,
+				9688CB160ED12B4E001D6492 /* X86_64Registers.h in Headers */,
 				9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */,
 				9688CB160ED12B4E001D6491 /* X86Registers.h in Headers */,
-				9688CB160ED12B4E001D6492 /* X86_64Registers.h in Headers */,
 				9959E92E1BD17FA4001AA413 /* xxd.pl in Headers */,
 				451539B912DC994500EF7AC4 /* Yarr.h in Headers */,
 				E3282BBB1FE930AF00EDAF71 /* YarrErrorCode.h in Headers */,
@@ -10208,7 +10190,7 @@
 			buildPhases = (
 				14BD59BC0A3E8F9000BAF59C /* Sources */,
 				14BD59BD0A3E8F9000BAF59C /* Frameworks */,
-				5DBB1511131D0B130056AD36 /* Copy Support Script */,
+				5366FDB222D5485B00BF94AF /* Copy Support Scripts */,
 				5DAFD6CD146B6B6E00FBEFB4 /* Install Support Script */,
 			);
 			buildRules = (
@@ -10539,6 +10521,24 @@
 			shellPath = /bin/sh;
 			shellScript = "Scripts/check-xcfilelists.sh\n";
 		};
+		5366FDB222D5485B00BF94AF /* Copy Support Scripts */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+			);
+			name = "Copy Support Scripts";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "rsync -r ${SRCROOT}/API/tests/testapiScripts ${BUILT_PRODUCTS_DIR}\n";
+		};
 		53B4BD091F68AF8900D2BEA3 /* Generate Unified Sources */ = {
 			isa = PBXShellScriptBuildPhase;
 			buildActionMask = 2147483647;

Modified: trunk/Source/_javascript_Core/builtins/ModuleLoader.js (247402 => 247403)


--- trunk/Source/_javascript_Core/builtins/ModuleLoader.js	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/builtins/ModuleLoader.js	2019-07-12 22:15:55 UTC (rev 247403)
@@ -369,3 +369,20 @@
     this.linkAndEvaluateModule(entry.key, fetcher);
     return this.getModuleNamespaceObject(entry.module);
 }
+
+function dependencyKeysIfEvaluated(key)
+{
+    "use strict";
+
+    let entry = this.registry.@get(key);
+    if (!entry || !entry.evaluated)
+        return null;
+
+    let dependencies = entry.dependencies;
+    let length = dependencies.length;
+    let result = new @Array(length);
+    for (let i = 0; i < length; ++i)
+        result[i] = dependencies[i].key;
+
+    return result;
+}

Modified: trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp (247402 => 247403)


--- trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/runtime/JSModuleLoader.cpp	2019-07-12 22:15:55 UTC (rev 247403)
@@ -86,6 +86,7 @@
     loadModule                     JSBuiltin                                  DontEnum|Function 3
     linkAndEvaluateModule          JSBuiltin                                  DontEnum|Function 2
     requestImportModule            JSBuiltin                                  DontEnum|Function 3
+    dependencyKeysIfEvaluated      JSBuiltin                                  DontEnum|Function 1
     getModuleNamespaceObject       moduleLoaderGetModuleNamespaceObject       DontEnum|Function 1
     parseModule                    moduleLoaderParseModule                    DontEnum|Function 2
     requestedModules               moduleLoaderRequestedModules               DontEnum|Function 1
@@ -125,6 +126,26 @@
     return vm.propertyNames->emptyIdentifier.impl();
 }
 
+JSArray* JSModuleLoader::dependencyKeysIfEvaluated(ExecState* exec, JSValue key)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().dependencyKeysIfEvaluatedPublicName()));
+    RETURN_IF_EXCEPTION(scope, nullptr);
+    CallData callData;
+    CallType callType = JSC::getCallData(vm, function, callData);
+    ASSERT(callType != CallType::None);
+
+    MarkedArgumentBuffer arguments;
+    arguments.append(key);
+
+    JSValue result = call(exec, function, callType, callData, this, arguments);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+
+    return jsDynamicCast<JSArray*>(vm, result);
+}
+
 JSValue JSModuleLoader::provideFetch(ExecState* exec, JSValue key, const SourceCode& sourceCode)
 {
     VM& vm = exec->vm();

Modified: trunk/Source/_javascript_Core/runtime/JSModuleLoader.h (247402 => 247403)


--- trunk/Source/_javascript_Core/runtime/JSModuleLoader.h	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/runtime/JSModuleLoader.h	2019-07-12 22:15:55 UTC (rev 247403)
@@ -84,6 +84,7 @@
 
     // Utility functions.
     JSModuleNamespaceObject* getModuleNamespaceObject(ExecState*, JSValue moduleRecord);
+    JSArray* dependencyKeysIfEvaluated(ExecState*, JSValue key);
 
 protected:
     void finishCreation(ExecState*, VM&, JSGlobalObject*);

Modified: trunk/Source/_javascript_Core/shell/CMakeLists.txt (247402 => 247403)


--- trunk/Source/_javascript_Core/shell/CMakeLists.txt	2019-07-12 22:12:59 UTC (rev 247402)
+++ trunk/Source/_javascript_Core/shell/CMakeLists.txt	2019-07-12 22:15:55 UTC (rev 247403)
@@ -92,13 +92,8 @@
     WEBKIT_EXECUTABLE(testdfg)
 
     file(COPY
-        "${_javascript_CORE_DIR}/API/tests/testapi.js"
+        "${_javascript_CORE_DIR}/API/tests/testapiScripts"
         DESTINATION
         ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/testapiScripts
     )
-    file(COPY
-        "${_javascript_CORE_DIR}/API/tests/testapi-function-overrides.js"
-        DESTINATION
-        ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/testapiScripts
-    )
 endif ()
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to