Title: [239933] trunk/Source/_javascript_Core
Revision
239933
Author
[email protected]
Date
2019-01-14 12:27:17 -0800 (Mon, 14 Jan 2019)

Log Message

JSC should have a module loader API
https://bugs.webkit.org/show_bug.cgi?id=191121

Reviewed by Michael Saboff.

This patch adds a new delegate to JSContext that is called to fetch
any resolved module. The resolution of a module identifier is computed
as if it were a URL on the web with the caveat that it must be a file URL.

A new class JSScript has also been added that is similar to JSScriptRef.
Right now all JSScripts are copied into memory. In the future we should
mmap the provided file into memory so the OS can evict it to disk under
pressure. Additionally, the API does not make use of the code signing path
nor the bytecode caching path, which we will add in subsequent patches.

Lastly, a couple of new convenience methods have been added. C API
conversion, can now toRef a JSValue with just a vm rather than
requiring an ExecState. Secondly, there is now a call wrapper that
does not require CallData and CallType since many places don't
care about this.

* API/APICast.h:
(toRef):
* API/JSAPIGlobalObject.cpp: Copied from Source/_javascript_Core/API/JSVirtualMachineInternal.h.
* API/JSAPIGlobalObject.h: Added.
(JSC::JSAPIGlobalObject::create):
(JSC::JSAPIGlobalObject::createStructure):
(JSC::JSAPIGlobalObject::JSAPIGlobalObject):
* API/JSAPIGlobalObject.mm: Added.
(JSC::JSAPIGlobalObject::moduleLoaderResolve):
(JSC::JSAPIGlobalObject::moduleLoaderImportModule):
(JSC::JSAPIGlobalObject::moduleLoaderFetch):
(JSC::JSAPIGlobalObject::moduleLoaderCreateImportMetaProperties):
* API/JSAPIValueWrapper.h:
(JSC::jsAPIValueWrapper): Deleted.
* API/JSContext.h:
* API/JSContext.mm:
(-[JSContext moduleLoaderDelegate]):
(-[JSContext setModuleLoaderDelegate:]):
* API/JSContextInternal.h:
* API/JSContextPrivate.h:
* API/JSContextRef.cpp:
(JSGlobalContextCreateInGroup):
* API/JSScript.h: Added.
* API/JSScript.mm: Added.
(+[JSScript scriptWithSource:inVirtualMachine:]):
(fillBufferWithContentsOfFile):
(+[JSScript scriptFromUTF8File:inVirtualMachine:withCodeSigning:andBytecodeCache:]):
(getJSScriptSourceCode):
* API/JSScriptInternal.h: Copied from Source/_javascript_Core/API/JSVirtualMachineInternal.h.
* API/JSValueInternal.h:
* API/JSVirtualMachineInternal.h:
* API/tests/testapi.mm:
(+[JSContextFetchDelegate contextWithBlockForFetch:]):
(-[JSContextFetchDelegate context:fetchModuleForIdentifier:withResolveHandler:andRejectHandler:]):
(checkModuleCodeRan):
(checkModuleWasRejected):
(testFetch):
(testFetchWithTwoCycle):
(testFetchWithThreeCycle):
(testLoaderResolvesAbsoluteScriptURL):
(testLoaderRejectsNilScriptURL):
(testLoaderRejectsFailedFetch):
(testImportModuleTwice):
(+[JSContextFileLoaderDelegate newContext]):
(resolvePathToScripts):
(-[JSContextFileLoaderDelegate context:fetchModuleForIdentifier:withResolveHandler:andRejectHandler:]):
(testLoadBasicFile):
(testObjectiveCAPI):
* API/tests/testapiScripts/basic.js: Copied from Source/_javascript_Core/API/JSVirtualMachineInternal.h.
* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* SourcesCocoa.txt:
* config.h:
* postprocess-headers.sh:
* runtime/CallData.cpp:
(JSC::call):
* runtime/CallData.h:
* runtime/Completion.cpp:
(JSC::loadAndEvaluateModule):
* runtime/Completion.h:
* runtime/JSCast.h:
(JSC::jsSecureCast):
* runtime/JSGlobalObject.cpp:
(JSC::createProxyProperty):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/API/APICast.h (239932 => 239933)


--- trunk/Source/_javascript_Core/API/APICast.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/APICast.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -128,21 +128,26 @@
     return reinterpret_cast<JSC::VM*>(const_cast<OpaqueJSContextGroup*>(g));
 }
 
-inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v)
+inline JSValueRef toRef(JSC::VM& vm, JSC::JSValue v)
 {
-    ASSERT(exec->vm().currentThreadIsHoldingAPILock());
+    ASSERT(vm.currentThreadIsHoldingAPILock());
 #if !CPU(ADDRESS64)
     if (!v)
         return 0;
     if (!v.isCell())
-        return reinterpret_cast<JSValueRef>(JSC::jsAPIValueWrapper(exec, v).asCell());
+        return reinterpret_cast<JSValueRef>(JSC::JSAPIValueWrapper::create(vm, v));
     return reinterpret_cast<JSValueRef>(v.asCell());
 #else
-    UNUSED_PARAM(exec);
+    UNUSED_PARAM(vm);
     return bitwise_cast<JSValueRef>(v);
 #endif
 }
 
+inline JSValueRef toRef(JSC::ExecState* exec, JSC::JSValue v)
+{
+    return toRef(exec->vm(), v);
+}
+
 inline JSObjectRef toRef(JSC::JSObject* o)
 {
     return reinterpret_cast<JSObjectRef>(o);

Copied: trunk/Source/_javascript_Core/API/JSAPIGlobalObject.cpp (from rev 239932, trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h) (0 => 239933)


--- trunk/Source/_javascript_Core/API/JSAPIGlobalObject.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSAPIGlobalObject.cpp	2019-01-14 20:27:17 UTC (rev 239933)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include "config.h"
+#include "JSAPIGlobalObject.h"
+
+#if !JSC_OBJC_API_ENABLED
+
+namespace JSC {
+
+const ClassInfo JSAPIGlobalObject::s_info = { "GlobalObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAPIGlobalObject) };
+
+const GlobalObjectMethodTable JSAPIGlobalObject::s_globalObjectMethodTable = {
+    &supportsRichSourceInfo,
+    &shouldInterruptScript,
+    &_javascript_RuntimeFlags,
+    nullptr, // queueTaskToEventLoop
+    &shouldInterruptScriptBeforeTimeout,
+    nullptr, // moduleLoaderImportModule
+    nullptr, // moduleLoaderResolve
+    nullptr, // moduleLoaderFetch
+    nullptr, // moduleLoaderCreateImportMetaProperties
+    nullptr, // moduleLoaderEvaluate
+    nullptr, // promiseRejectionTracker
+    nullptr, // defaultLanguage
+    nullptr, // compileStreaming
+    nullptr, // instantiateStreaming
+};
+
+}
+
+#endif

Added: trunk/Source/_javascript_Core/API/JSAPIGlobalObject.h (0 => 239933)


--- trunk/Source/_javascript_Core/API/JSAPIGlobalObject.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSAPIGlobalObject.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#include "JSGlobalObject.h"
+
+namespace JSC {
+
+class JSAPIGlobalObject : public JSGlobalObject {
+public:
+    using Base = JSGlobalObject;
+
+    DECLARE_EXPORT_INFO;
+    static const GlobalObjectMethodTable s_globalObjectMethodTable;
+
+    static JSAPIGlobalObject* create(VM& vm, Structure* structure)
+    {
+        auto* object = new (NotNull, allocateCell<JSAPIGlobalObject>(vm.heap)) JSAPIGlobalObject(vm, structure);
+        object->finishCreation(vm);
+        return object;
+    }
+
+    static Structure* createStructure(VM& vm, JSValue prototype)
+    {
+        auto* result = Structure::create(vm, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), info());
+        result->setTransitionWatchpointIsLikelyToBeFired(true);
+        return result;
+    }
+
+    static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString* moduleNameValue, JSValue parameters, const SourceOrigin&);
+    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);
+
+private:
+    JSAPIGlobalObject(VM& vm, Structure* structure)
+        : Base(vm, structure, &s_globalObjectMethodTable)
+    { }
+};
+
+}

Added: trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm (0 => 239933)


--- trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSAPIGlobalObject.mm	2019-01-14 20:27:17 UTC (rev 239933)
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#import "config.h"
+#import "JSAPIGlobalObject.h"
+
+#if JSC_OBJC_API_ENABLED
+
+#import "APICast.h"
+#import "CatchScope.h"
+#import "Completion.h"
+#import "Error.h"
+#import "Exception.h"
+#import "JSContextInternal.h"
+#import "JSInternalPromiseDeferred.h"
+#import "JSNativeStdFunction.h"
+#import "JSScriptInternal.h"
+#import "JSSourceCode.h"
+#import "JSValueInternal.h"
+#import "JSVirtualMachineInternal.h"
+#import "_javascript_Core.h"
+#import "ObjectConstructor.h"
+#import "SourceOrigin.h"
+
+#import <wtf/URL.h>
+
+namespace JSC {
+
+const ClassInfo JSAPIGlobalObject::s_info = { "GlobalObject", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSAPIGlobalObject) };
+
+const GlobalObjectMethodTable JSAPIGlobalObject::s_globalObjectMethodTable = {
+    &supportsRichSourceInfo,
+    &shouldInterruptScript,
+    &_javascript_RuntimeFlags,
+    nullptr, // queueTaskToEventLoop
+    &shouldInterruptScriptBeforeTimeout,
+    &moduleLoaderImportModule, // moduleLoaderImportModule
+    &moduleLoaderResolve, // moduleLoaderResolve
+    &moduleLoaderFetch, // moduleLoaderFetch
+    &moduleLoaderCreateImportMetaProperties, // moduleLoaderCreateImportMetaProperties
+    nullptr, // moduleLoaderEvaluate
+    nullptr, // promiseRejectionTracker
+    nullptr, // defaultLanguage
+    nullptr, // compileStreaming
+    nullptr, // instantiateStreaming
+};
+
+Identifier JSAPIGlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue referrer, JSValue)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+    ASSERT_UNUSED(globalObject, globalObject == exec->lexicalGlobalObject());
+    ASSERT(key.isString() || key.isSymbol());
+    String name =  key.toWTFString(exec);
+
+    URL referrerURL(URL(), jsCast<JSString*>(referrer)->tryGetValue());
+    RELEASE_ASSERT(referrerURL.isValid());
+
+    URL url = "" name);
+    if (url.isValid())
+        return Identifier::fromString(exec, url);
+
+    throwVMError(exec, scope, "Could not form valid URL from identifier and base"_s);
+    return { };
+}
+
+JSInternalPromise* JSAPIGlobalObject::moduleLoaderImportModule(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSString* specifierValue, JSValue, const SourceOrigin& sourceOrigin)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+    auto reject = [&] (JSValue exception) -> JSInternalPromise* {
+        scope.clearException();
+        auto* promise = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
+        scope.clearException();
+        return promise->reject(exec, exception);
+    };
+
+    auto import = [&] (URL& url) {
+        auto result = importModule(exec, Identifier::fromString(&vm, url), jsUndefined(), jsUndefined());
+        if (UNLIKELY(scope.exception()))
+            return reject(scope.exception());
+        return result;
+    };
+
+    auto specifier = specifierValue->value(exec);
+    if (UNLIKELY(scope.exception())) {
+        JSValue exception = scope.exception();
+        scope.clearException();
+        return reject(exception);
+    }
+
+    URL absoluteURL(URL(), specifier);
+    if (absoluteURL.isValid())
+        return import(absoluteURL);
+
+    if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
+        return reject(createError(exec, "Module 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, noBaseErrorMessage));
+
+    auto referrer = sourceOrigin.string();
+    URL baseURL(URL(), referrer);
+    if (!baseURL.isValid())
+        return reject(createError(exec, noBaseErrorMessage));
+
+    URL url(baseURL, specifier);
+    if (!url.isValid())
+        return reject(createError(exec, "could not determine a valid URL for module specifier"_s));
+
+    return import(url);
+}
+
+JSInternalPromise* JSAPIGlobalObject::moduleLoaderFetch(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSValue, JSValue)
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
+    ASSERT(globalObject == exec->lexicalGlobalObject());
+    JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject->globalExec())];
+
+    JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+
+    Identifier moduleKey = key.toPropertyKey(exec);
+    if (UNLIKELY(scope.exception())) {
+        JSValue exception = scope.exception();
+        scope.clearException();
+        return deferred->reject(exec, exception);
+    }
+
+    if (UNLIKELY(![context moduleLoaderDelegate]))
+        return deferred->reject(exec, createError(exec, "No module loader provided."));
+
+    auto deferredPromise = Strong<JSInternalPromiseDeferred>(vm, deferred);
+    auto strongKey = Strong<JSString>(vm, jsSecureCast<JSString*>(vm, key));
+    auto* resolve = JSNativeStdFunction::create(vm, globalObject, 1, "resolve", [=] (ExecState* exec) {
+        VM& vm = exec->vm();
+        // This captures the globalObject but that's ok because our structure keeps it alive anyway.
+        JSContext *context = [JSContext contextWithJSGlobalContextRef:toGlobalRef(globalObject->globalExec())];
+        id script = valueToObject(context, toRef(exec, exec->argument(0)));
+
+        MarkedArgumentBuffer args;
+        if (UNLIKELY(![script isKindOfClass:[JSScript class]])) {
+            args.append(createTypeError(exec, "First argument of resolution callback is not a JSScript"));
+            call(exec, deferredPromise->JSPromiseDeferred::reject(), args, "This should never be seen...");
+            return encodedJSUndefined();
+        }
+
+        const String& source = getJSScriptSourceCode(static_cast<JSScript *>(script));
+        args.append(JSSourceCode::create(vm, makeSource(source, SourceOrigin(moduleKey.string()), URL({ }, moduleKey.string()), TextPosition(), JSC::SourceProviderSourceType::Module)));
+        call(exec, deferredPromise->JSPromiseDeferred::resolve(), args, "This should never be seen...");
+        return encodedJSUndefined();
+    });
+
+    auto* reject = JSNativeStdFunction::create(vm, globalObject, 1, "reject", [=] (ExecState* exec) {
+        MarkedArgumentBuffer args;
+        args.append(exec->argument(0));
+
+        call(exec, deferredPromise->JSPromiseDeferred::reject(), args, "This should never be seen...");
+        return encodedJSUndefined();
+    });
+
+    [[context moduleLoaderDelegate] context:context fetchModuleForIdentifier:[::JSValue valueWithJSValueRef:toRef(exec, key) inContext:context] withResolveHandler:[::JSValue valueWithJSValueRef:toRef(exec, resolve) inContext:context] andRejectHandler:[::JSValue valueWithJSValueRef:toRef(exec, reject) inContext:context]];
+    if (context.exception) {
+        deferred->reject(exec, toJS(exec, [context.exception JSValueRef]));
+        context.exception = nil;
+    }
+    return deferred->promise();
+}
+
+JSObject* JSAPIGlobalObject::moduleLoaderCreateImportMetaProperties(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue key, JSModuleRecord*, JSValue)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSObject* metaProperties = constructEmptyObject(exec, globalObject->nullPrototypeObjectStructure());
+    RETURN_IF_EXCEPTION(scope, nullptr);
+
+    metaProperties->putDirect(vm, Identifier::fromString(&vm, "filename"), key);
+    RETURN_IF_EXCEPTION(scope, nullptr);
+
+    return metaProperties;
+}
+
+}
+
+#endif // JSC_OBJC_API_ENABLED

Modified: trunk/Source/_javascript_Core/API/JSAPIValueWrapper.h (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSAPIValueWrapper.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSAPIValueWrapper.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten ([email protected])
  *  Copyright (C) 2001 Peter Kelly ([email protected])
- *  Copyright (C) 2003, 2004, 2005, 2007, 2008 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2019 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -44,10 +44,9 @@
 
     DECLARE_EXPORT_INFO;
 
-    static JSAPIValueWrapper* create(ExecState* exec, JSValue value) 
+    static JSAPIValueWrapper* create(VM& vm, JSValue value)
     {
-        VM& vm = exec->vm();
-        JSAPIValueWrapper* wrapper = new (NotNull, allocateCell<JSAPIValueWrapper>(vm.heap)) JSAPIValueWrapper(exec);
+        JSAPIValueWrapper* wrapper = new (NotNull, allocateCell<JSAPIValueWrapper>(vm.heap)) JSAPIValueWrapper(vm);
         wrapper->finishCreation(vm, value);
         return wrapper;
     }
@@ -61,8 +60,8 @@
     }
 
 private:
-    JSAPIValueWrapper(ExecState* exec)
-        : JSCell(exec->vm(), exec->vm().apiWrapperStructure.get())
+    JSAPIValueWrapper(VM& vm)
+        : JSCell(vm, vm.apiWrapperStructure.get())
     {
     }
 
@@ -69,9 +68,4 @@
     WriteBarrier<Unknown> m_value;
 };
 
-inline JSValue jsAPIValueWrapper(ExecState* exec, JSValue value)
-{
-    return JSAPIValueWrapper::create(exec, value);
-}
-
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/API/JSContext.h (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSContext.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSContext.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,7 +31,7 @@
 
 #if JSC_OBJC_API_ENABLED
 
-@class JSVirtualMachine, JSValue;
+@class JSScript, JSVirtualMachine, JSValue, JSContext;
 
 /*!
 @interface
@@ -39,7 +39,7 @@
  _javascript_ execution takes place within a context, and all _javascript_ values
  are tied to a context.
 */
-NS_CLASS_AVAILABLE(10_9, 7_0)
+JSC_CLASS_AVAILABLE(macosx(10.9), ios(7.0))
 @interface JSContext : NSObject
 
 /*!
@@ -177,7 +177,6 @@
 @discussion Name of the JSContext. Exposed when remote debugging the context.
 */
 @property (copy) NSString *name JSC_API_AVAILABLE(macosx(10.10), ios(8.0));
-
 @end
 
 /*!
@@ -231,6 +230,7 @@
 @result The C API equivalent of this JSContext.
 */
 @property (readonly) JSGlobalContextRef JSGlobalContextRef;
+
 @end
 
 #endif

Modified: trunk/Source/_javascript_Core/API/JSContext.mm (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSContext.mm	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSContext.mm	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,11 +26,15 @@
 #include "config.h"
 
 #import "APICast.h"
+#import "Completion.h"
 #import "JSCInlines.h"
 #import "JSContextInternal.h"
 #import "JSContextPrivate.h"
 #import "JSContextRefInternal.h"
 #import "JSGlobalObject.h"
+#import "JSInternalPromise.h"
+#import "JSModuleLoader.h"
+#import "JSScriptInternal.h"
 #import "JSValueInternal.h"
 #import "JSVirtualMachineInternal.h"
 #import "JSWrapperMap.h"
@@ -38,6 +42,8 @@
 #import "ObjcRuntimeExtras.h"
 #import "StrongInlines.h"
 
+#import <wtf/WeakObjCPtr.h>
+
 #if JSC_OBJC_API_ENABLED
 
 @implementation JSContext {
@@ -44,6 +50,7 @@
     JSVirtualMachine *m_virtualMachine;
     JSGlobalContextRef m_context;
     JSC::Strong<JSC::JSObject> m_exception;
+    WeakObjCPtr<id <JSModuleLoaderDelegate>> m_moduleLoaderDelegate;
 }
 
 - (JSGlobalContextRef)JSGlobalContextRef
@@ -233,6 +240,16 @@
     JSGlobalContextSetDebuggerRunLoop(m_context, runLoop);
 }
 
+- (id<JSModuleLoaderDelegate>)moduleLoaderDelegate
+{
+    return m_moduleLoaderDelegate.getAutoreleased();
+}
+
+- (void)setModuleLoaderDelegate:(id<JSModuleLoaderDelegate>)moduleLoaderDelegate
+{
+    m_moduleLoaderDelegate = moduleLoaderDelegate;
+}
+
 @end
 
 @implementation JSContext(SubscriptSupport)

Modified: trunk/Source/_javascript_Core/API/JSContextInternal.h (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSContextInternal.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSContextInternal.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,7 +27,7 @@
 
 #if JSC_OBJC_API_ENABLED
 
-#import <_javascript_Core/JSContext.h>
+#import <_javascript_Core/JSContextPrivate.h>
 
 struct CallbackData {
     CallbackData* next;

Modified: trunk/Source/_javascript_Core/API/JSContextPrivate.h (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSContextPrivate.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSContextPrivate.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -30,6 +30,27 @@
 
 #import <_javascript_Core/JSContext.h>
 
+@protocol JSModuleLoaderDelegate <NSObject>
+
+@required
+
+/*! @abstract Provides source code for any JS module that is actively imported.
+ @param context The context for which the module is being requested.
+ @param identifier The resolved identifier for the requested module.
+ @param resolve A JS function to call with the desired script for identifier.
+ @param reject A JS function to call when identifier cannot be fetched.
+ @discussion Currently, identifier will always be an absolute file URL computed from specifier of the requested module relative to the URL of the requesting script. If the requesting script does not have a URL and the module specifier is not an absolute path the module loader will fail to load the module.
+
+ The first argument to resolve sholud always be a JSScript, otherwise the module loader will reject the module.
+
+ Once an identifier has been resolved or rejected in a given context it will never be requested again. If a script is successfully evaluated it will not be re-evaluated on any subsequent import.
+
+ The VM will retain all evaluated modules for the lifetime of the context.
+ */
+- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject;
+
+@end
+
 @interface JSContext(Private)
 
 /*!
@@ -50,6 +71,9 @@
 */
 @property (setter=_setDebuggerRunLoop:) CFRunLoopRef _debuggerRunLoop JSC_API_AVAILABLE(macosx(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(macosx(JSC_MAC_TBA), ios(JSC_IOS_TBA));
+
 @end
 
 #endif

Modified: trunk/Source/_javascript_Core/API/JSContextRef.cpp (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSContextRef.cpp	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSContextRef.cpp	2019-01-14 20:27:17 UTC (rev 239933)
@@ -30,9 +30,9 @@
 #include "APICast.h"
 #include "CallFrame.h"
 #include "InitializeThreading.h"
+#include "JSAPIGlobalObject.h"
 #include "JSCallbackObject.h"
 #include "JSClassRef.h"
-#include "JSGlobalObject.h"
 #include "JSObject.h"
 #include "JSCInlines.h"
 #include "SourceProvider.h"
@@ -138,7 +138,7 @@
     JSLockHolder locker(vm.ptr());
 
     if (!globalObjectClass) {
-        JSGlobalObject* globalObject = JSGlobalObject::create(vm.get(), JSGlobalObject::createStructure(vm.get(), jsNull()));
+        JSGlobalObject* globalObject = JSAPIGlobalObject::create(vm.get(), JSAPIGlobalObject::createStructure(vm.get(), jsNull()));
 #if ENABLE(REMOTE_INSPECTOR)
         if (JSRemoteInspectorGetInspectionEnabledByDefault())
             globalObject->setRemoteDebuggingEnabled(true);

Added: trunk/Source/_javascript_Core/API/JSScript.h (0 => 239933)


--- trunk/Source/_javascript_Core/API/JSScript.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSScript.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#import <_javascript_Core/JSValue.h>
+
+#if JSC_OBJC_API_ENABLED
+
+NS_ASSUME_NONNULL_BEGIN
+
+OBJC_CLASS JSVirtualMachine;
+
+JSC_CLASS_AVAILABLE(macosx(JSC_MAC_TBA), ios(JSC_IOS_TBA))
+@interface JSScript : NSObject
+
+/*!
+ @method
+ @abstract Create a JSScript for the specified virtual machine.
+ @param source The source code to use when the script is evaluated by the JS vm.
+ @param vm The JSVirtualMachine the script can be evaluated in.
+ @result The new script.
+ */
++ (nullable instancetype)scriptWithSource:(NSString *)source inVirtualMachine:(JSVirtualMachine *)vm;
+
+/*!
+ @method
+ @abstract Create a JSScript for the specified virtual machine with a path to a codesigning and bytecode caching.
+ @param filePath A URL containing the path to a JS source code file on disk.
+ @param vm The JSVirtualMachine the script can be evaluated in.
+ @param codeSigningPath A URL containing the path to the codeSigning file for filePath on disk.
+ @param cachePath A URL containing the path where the VM should cache for future execution.
+ @result The new script.
+ @discussion the files at filePath, codeSigningPath, and cachePath should not be externally modified  for the lifecycle of vm. Note that codeSigningPath and cachePath are not used currently, but that will change in the near future.
+ */
++ (nullable instancetype)scriptFromUTF8File:(NSURL *)filePath inVirtualMachine:(JSVirtualMachine *)vm withCodeSigning:(nullable NSURL *)codeSigningPath andBytecodeCache:(nullable NSURL *)cachePath;
+
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // JSC_OBJC_API_ENABLED

Added: trunk/Source/_javascript_Core/API/JSScript.mm (0 => 239933)


--- trunk/Source/_javascript_Core/API/JSScript.mm	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSScript.mm	2019-01-14 20:27:17 UTC (rev 239933)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#import "config.h"
+#import "JSScriptInternal.h"
+
+#import "APICast.h"
+#import "JSContextInternal.h"
+#import "JSValuePrivate.h"
+#import "Symbol.h"
+
+#if JSC_OBJC_API_ENABLED
+
+@implementation JSScript {
+    String m_source;
+}
+
++ (instancetype)scriptWithSource:(NSString *)source inVirtualMachine:(JSVirtualMachine *)vm
+{
+    UNUSED_PARAM(vm);
+    JSScript *result = [[JSScript alloc] init];
+    result->m_source = source;
+    return result;
+}
+
+template<typename Vector>
+static bool fillBufferWithContentsOfFile(FILE* file, Vector& buffer)
+{
+    // We might have injected "use strict"; at the top.
+    size_t initialSize = buffer.size();
+    if (fseek(file, 0, SEEK_END) == -1)
+        return false;
+    long bufferCapacity = ftell(file);
+    if (bufferCapacity == -1)
+        return false;
+    if (fseek(file, 0, SEEK_SET) == -1)
+        return false;
+    buffer.resize(bufferCapacity + initialSize);
+    size_t readSize = fread(buffer.data() + initialSize, 1, buffer.size(), file);
+    return readSize == buffer.size() - initialSize;
+}
+
+static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer)
+{
+    FILE* f = fopen(fileName.utf8().data(), "rb");
+    if (!f) {
+        fprintf(stderr, "Could not open file: %s\n", fileName.utf8().data());
+        return false;
+    }
+
+    bool result = fillBufferWithContentsOfFile(f, buffer);
+    fclose(f);
+
+    return result;
+}
+
+
++ (instancetype)scriptFromUTF8File:(NSURL *)filePath inVirtualMachine:(JSVirtualMachine *)vm withCodeSigning:(NSURL *)codeSigningPath andBytecodeCache:(NSURL *)cachePath
+{
+    // FIXME: This should check codeSigning.
+    UNUSED_PARAM(codeSigningPath);
+    // FIXME: This should actually cache bytecode.
+    UNUSED_PARAM(cachePath);
+    UNUSED_PARAM(vm);
+    URL filePathURL([filePath absoluteURL]);
+    if (!filePathURL.isLocalFile())
+        return nil;
+    // FIXME: This should mmap the contents of the file instead of copying it into dirty memory.
+    Vector<char> buffer;
+    if (!fillBufferWithContentsOfFile(filePathURL.fileSystemPath(), buffer))
+        return nil;
+
+    JSScript *result = [[JSScript alloc] init];
+    result->m_source = String::fromUTF8WithLatin1Fallback(buffer.data(), buffer.size());
+    return result;
+}
+
+const String& getJSScriptSourceCode(JSScript *module) { return module->m_source; }
+
+@end
+
+
+#endif

Copied: trunk/Source/_javascript_Core/API/JSScriptInternal.h (from rev 239932, trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h) (0 => 239933)


--- trunk/Source/_javascript_Core/API/JSScriptInternal.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/JSScriptInternal.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#pragma once
+
+#import "JSScript.h"
+#import "SourceCode.h"
+
+OBJC_CLASS JSScript;
+
+const String& getJSScriptSourceCode(JSScript *);

Modified: trunk/Source/_javascript_Core/API/JSValueInternal.h (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSValueInternal.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSValueInternal.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,8 +26,7 @@
 #ifndef JSValueInternal_h
 #define JSValueInternal_h
 
-#import <_javascript_Core/_javascript_Core.h>
-#import <_javascript_Core/JSValue.h>
+#import <_javascript_Core/JSValuePrivate.h>
 
 #if JSC_OBJC_API_ENABLED
 

Modified: trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h (239932 => 239933)


--- trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -46,8 +46,8 @@
 
 - (JSContext *)contextForGlobalContextRef:(JSGlobalContextRef)globalContext;
 - (void)addContext:(JSContext *)wrapper forGlobalContextRef:(JSGlobalContextRef)globalContext;
+@end
 
-@end
 #endif // defined(__OBJC__)
 
 void scanExternalObjectGraph(JSC::VM&, JSC::SlotVisitor&, void* root);

Modified: trunk/Source/_javascript_Core/API/tests/testapi.mm (239932 => 239933)


--- trunk/Source/_javascript_Core/API/tests/testapi.mm	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/API/tests/testapi.mm	2019-01-14 20:27:17 UTC (rev 239933)
@@ -31,7 +31,9 @@
 #import "DFGWorklist.h"
 #import "DateTests.h"
 #import "JSCast.h"
+#import "JSContextPrivate.h"
 #import "JSExportTests.h"
+#import "JSScript.h"
 #import "JSValuePrivate.h"
 #import "JSVirtualMachineInternal.h"
 #import "JSVirtualMachinePrivate.h"
@@ -1812,12 +1814,248 @@
     }
 }
 
+typedef JSValue *(^ResolveBlock)(JSContext *, JSValue *, JSScript *);
+typedef void (^FetchBlock)(JSContext *, JSValue *, JSValue *, JSValue *);
+
+@interface JSContextFetchDelegate : JSContext <JSModuleLoaderDelegate>
+
++ (instancetype)contextWithBlockForFetch:(FetchBlock)block;
+
+@end
+
+@implementation JSContextFetchDelegate {
+    FetchBlock m_fetchBlock;
+}
+
++ (instancetype)contextWithBlockForFetch:(FetchBlock)block
+{
+    auto *result = [[JSContextFetchDelegate alloc] init];
+    result->m_fetchBlock = block;
+    return result;
+}
+
+- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject
+{
+    m_fetchBlock(context, identifier, resolve, reject);
+}
+
+@end
+
+static void checkModuleCodeRan(JSContext *context, JSValue *promise, JSValue *expected)
+{
+    __block BOOL promiseWasResolved = false;
+    [promise invokeMethod:@"then" withArguments:@[^(JSValue *exportValue) {
+        promiseWasResolved = true;
+        checkResult(@"module exported value 'exp' is null", [exportValue[@"exp"] isEqualToObject:expected]);
+        checkResult(@"ran is %@", [context[@"ran"] isEqualToObject:expected]);
+    }, ^(JSValue *error) {
+        NSLog(@"%@", [error toString]);
+        checkResult(@"module graph was resolved as expected", NO);
+    }]];
+    checkResult(@"Promise was resolved", promiseWasResolved);
+}
+
+static void checkModuleWasRejected(JSContext *context, JSValue *promise)
+{
+    __block BOOL promiseWasRejected = false;
+    [promise invokeMethod:@"then" withArguments:@[^() {
+        checkResult(@"module was rejected as expected", NO);
+    }, ^(JSValue *error) {
+        promiseWasRejected = true;
+        NSLog(@"%@", [error toString]);
+        checkResult(@"module graph was rejected with error", ![error isEqualWithTypeCoercionToObject:[JSValue valueWithNullInContext:context]]);
+    }]];
+}
+
+static void testFetch()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFetchDelegate contextWithBlockForFetch:^(JSContext *context, JSValue *identifier, JSValue *resolve, JSValue *reject) {
+            if ([identifier isEqualToObject:@"file:///directory/bar.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"import \"../foo.js\"; export let exp = null;" inVirtualMachine:[context virtualMachine]]]];
+            else if ([identifier isEqualToObject:@"file:///foo.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"globalThis.ran = null;" inVirtualMachine:[context virtualMachine]]]];
+            else
+                [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Weird path" inContext:context]]];
+        }];
+        context.moduleLoaderDelegate = context;
+        JSValue *promise = [context evaluateScript:@"import('./bar.js');" withSourceURL:[NSURL fileURLWithPath:@"/directory" isDirectory:YES]];
+        JSValue *null = [JSValue valueWithNullInContext:context];
+        checkModuleCodeRan(context, promise, null);
+    }
+}
+
+static void testFetchWithTwoCycle()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFetchDelegate contextWithBlockForFetch:^(JSContext *context, JSValue *identifier, JSValue *resolve, JSValue *reject) {
+            if ([identifier isEqualToObject:@"file:///directory/bar.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"import { n } from \"../foo.js\"; export let exp = n;" inVirtualMachine:[context virtualMachine]]]];
+            else if ([identifier isEqualToObject:@"file:///foo.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"import \"directory/bar.js\"; globalThis.ran = null; export let n = null;" inVirtualMachine:[context virtualMachine]]]];
+            else
+                [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Weird path" inContext:context]]];
+        }];
+        context.moduleLoaderDelegate = context;
+        JSValue *promise = [context evaluateScript:@"import('./bar.js');" withSourceURL:[NSURL fileURLWithPath:@"/directory" isDirectory:YES]];
+        JSValue *null = [JSValue valueWithNullInContext:context];
+        checkModuleCodeRan(context, promise, null);
+    }
+}
+
+
+static void testFetchWithThreeCycle()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFetchDelegate contextWithBlockForFetch:^(JSContext *context, JSValue *identifier, JSValue *resolve, JSValue *reject) {
+            if ([identifier isEqualToObject:@"file:///directory/bar.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"import { n } from \"../foo.js\"; export let foo = n;" inVirtualMachine:[context virtualMachine]]]];
+            else if ([identifier isEqualToObject:@"file:///foo.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"import \"otherDirectory/baz.js\"; export let n = null;" inVirtualMachine:[context virtualMachine]]]];
+            else if ([identifier isEqualToObject:@"file:///otherDirectory/baz.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"import { foo } from \"../directory/bar.js\"; globalThis.ran = null; export let exp = foo;" inVirtualMachine:[context virtualMachine]]]];
+            else
+                [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Weird path" inContext:context]]];
+        }];
+        context.moduleLoaderDelegate = context;
+        JSValue *promise = [context evaluateScript:@"import('../otherDirectory/baz.js');" withSourceURL:[NSURL fileURLWithPath:@"/directory" isDirectory:YES]];
+        JSValue *null = [JSValue valueWithNullInContext:context];
+        checkModuleCodeRan(context, promise, null);
+    }
+}
+
+static void testLoaderResolvesAbsoluteScriptURL()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFetchDelegate contextWithBlockForFetch:^(JSContext *context, JSValue *identifier, JSValue *resolve, JSValue *reject) {
+            if ([identifier isEqualToObject:@"file:///directory/bar.js"])
+                [resolve callWithArguments:@[[JSScript scriptWithSource:@"export let exp = null; globalThis.ran = null;" inVirtualMachine:[context virtualMachine]]]];
+            else
+                [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Weird path" inContext:context]]];
+        }];
+        context.moduleLoaderDelegate = context;
+        JSValue *promise = [context evaluateScript:@"import('/directory/bar.js');"];
+        JSValue *null = [JSValue valueWithNullInContext:context];
+        checkModuleCodeRan(context, promise, null);
+    }
+}
+
+static void testLoaderRejectsNilScriptURL()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFetchDelegate contextWithBlockForFetch:^(JSContext *, JSValue *, JSValue *, JSValue *) {
+            checkResult(@"Code is not run", NO);
+        }];
+        context.moduleLoaderDelegate = context;
+        JSValue *promise = [context evaluateScript:@"import('../otherDirectory/baz.js');"];
+        checkModuleWasRejected(context, promise);
+    }
+}
+
+static void testLoaderRejectsFailedFetch()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFetchDelegate contextWithBlockForFetch:^(JSContext *context, JSValue *, JSValue *, JSValue *reject) {
+            [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Nope" inContext:context]]];
+        }];
+        context.moduleLoaderDelegate = context;
+        JSValue *promise = [context evaluateScript:@"import('/otherDirectory/baz.js');"];
+        checkModuleWasRejected(context, promise);
+    }
+}
+
+static void testImportModuleTwice()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFetchDelegate contextWithBlockForFetch:^(JSContext * context, JSValue *, JSValue *resolve, JSValue *) {
+            [resolve callWithArguments:@[[JSScript scriptWithSource:@"ran++; export let exp = 1;" inVirtualMachine:[context virtualMachine]]]];
+        }];
+        context.moduleLoaderDelegate = context;
+        context[@"ran"] = @(0);
+        JSValue *promise = [context evaluateScript:@"import('/baz.js');"];
+        JSValue *promise2 = [context evaluateScript:@"import('/baz.js');"];
+        JSValue *_one_ = [JSValue valueWithInt32:1 inContext:context];
+        checkModuleCodeRan(context, promise, one);
+        checkModuleCodeRan(context, promise2, one);
+    }
+}
+
+@interface JSContextFileLoaderDelegate : JSContext <JSModuleLoaderDelegate>
+
++ (instancetype)newContext;
+
+@end
+
+@implementation JSContextFileLoaderDelegate {
+}
+
++ (instancetype)newContext
+{
+    auto *result = [[JSContextFileLoaderDelegate alloc] init];
+    return result;
+}
+
+static NSURL *resolvePathToScripts()
+{
+    NSString *arg0 = NSProcessInfo.processInfo.arguments[0];
+    NSURL *base;
+    if ([arg0 hasPrefix:@"/"])
+        base = [NSURL fileURLWithPath:arg0 isDirectory:NO];
+    else {
+        const size_t maxLength = 10000;
+        char cwd[maxLength];
+        if (!getcwd(cwd, maxLength)) {
+            NSLog(@"getcwd errored with code: %s", strerror(errno));
+            exit(1);
+        }
+        NSURL *cwdURL = [NSURL fileURLWithPath:[NSString stringWithFormat:@"%s", cwd]];
+        base = [NSURL fileURLWithPath:arg0 isDirectory:NO relativeToURL:cwdURL];
+    }
+    return [NSURL fileURLWithPath:@"./testapiScripts/" isDirectory:YES relativeToURL:base];
+}
+
+- (void)context:(JSContext *)context fetchModuleForIdentifier:(JSValue *)identifier withResolveHandler:(JSValue *)resolve andRejectHandler:(JSValue *)reject
+{
+    NSURL *filePath = [NSURL URLWithString:[identifier toString]];
+    auto *script = [JSScript scriptFromUTF8File:filePath inVirtualMachine:[context virtualMachine] withCodeSigning:nil andBytecodeCache:nil];
+    if (script)
+        [resolve callWithArguments:@[script]];
+    else
+        [reject callWithArguments:@[[JSValue valueWithNewErrorFromMessage:@"Unable to create Script" inContext:context]]];
+}
+
+@end
+
+static void testLoadBasicFile()
+{
+    @autoreleasepool {
+        auto *context = [JSContextFileLoaderDelegate newContext];
+        context.moduleLoaderDelegate = context;
+        JSValue *promise = [context evaluateScript:@"import('./basic.js');" withSourceURL:resolvePathToScripts()];
+        JSValue *null = [JSValue valueWithNullInContext:context];
+        checkModuleCodeRan(context, promise, null);
+    }
+}
+
 void testObjectiveCAPI()
 {
     NSLog(@"Testing Objective-C API");
+
     checkNegativeNSIntegers();
     runJITThreadLimitTests();
 
+    testLoaderResolvesAbsoluteScriptURL();
+    testFetch();
+    testFetchWithTwoCycle();
+    testFetchWithThreeCycle();
+    testImportModuleTwice();
+
+    testLoaderRejectsNilScriptURL();
+    testLoaderRejectsFailedFetch();
+
+    // File loading
+    testLoadBasicFile();
+
     promiseWithExecutor(Resolution::ResolveEager);
     promiseWithExecutor(Resolution::RejectEager);
     promiseWithExecutor(Resolution::ResolveLate);

Copied: trunk/Source/_javascript_Core/API/tests/testapiScripts/basic.js (from rev 239932, trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h) (0 => 239933)


--- trunk/Source/_javascript_Core/API/tests/testapiScripts/basic.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/API/tests/testapiScripts/basic.js	2019-01-14 20:27:17 UTC (rev 239933)
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+export let exp = null;
+globalThis.ran = null;

Modified: trunk/Source/_javascript_Core/ChangeLog (239932 => 239933)


--- trunk/Source/_javascript_Core/ChangeLog	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/ChangeLog	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,3 +1,91 @@
+2019-01-14  Keith Miller  <[email protected]>
+
+        JSC should have a module loader API
+        https://bugs.webkit.org/show_bug.cgi?id=191121
+
+        Reviewed by Michael Saboff.
+
+        This patch adds a new delegate to JSContext that is called to fetch
+        any resolved module. The resolution of a module identifier is computed
+        as if it were a URL on the web with the caveat that it must be a file URL.
+
+        A new class JSScript has also been added that is similar to JSScriptRef.
+        Right now all JSScripts are copied into memory. In the future we should
+        mmap the provided file into memory so the OS can evict it to disk under
+        pressure. Additionally, the API does not make use of the code signing path
+        nor the bytecode caching path, which we will add in subsequent patches.
+
+        Lastly, a couple of new convenience methods have been added. C API
+        conversion, can now toRef a JSValue with just a vm rather than
+        requiring an ExecState. Secondly, there is now a call wrapper that
+        does not require CallData and CallType since many places don't
+        care about this.
+
+        * API/APICast.h:
+        (toRef):
+        * API/JSAPIGlobalObject.cpp: Copied from Source/_javascript_Core/API/JSVirtualMachineInternal.h.
+        * API/JSAPIGlobalObject.h: Added.
+        (JSC::JSAPIGlobalObject::create):
+        (JSC::JSAPIGlobalObject::createStructure):
+        (JSC::JSAPIGlobalObject::JSAPIGlobalObject):
+        * API/JSAPIGlobalObject.mm: Added.
+        (JSC::JSAPIGlobalObject::moduleLoaderResolve):
+        (JSC::JSAPIGlobalObject::moduleLoaderImportModule):
+        (JSC::JSAPIGlobalObject::moduleLoaderFetch):
+        (JSC::JSAPIGlobalObject::moduleLoaderCreateImportMetaProperties):
+        * API/JSAPIValueWrapper.h:
+        (JSC::jsAPIValueWrapper): Deleted.
+        * API/JSContext.h:
+        * API/JSContext.mm:
+        (-[JSContext moduleLoaderDelegate]):
+        (-[JSContext setModuleLoaderDelegate:]):
+        * API/JSContextInternal.h:
+        * API/JSContextPrivate.h:
+        * API/JSContextRef.cpp:
+        (JSGlobalContextCreateInGroup):
+        * API/JSScript.h: Added.
+        * API/JSScript.mm: Added.
+        (+[JSScript scriptWithSource:inVirtualMachine:]):
+        (fillBufferWithContentsOfFile):
+        (+[JSScript scriptFromUTF8File:inVirtualMachine:withCodeSigning:andBytecodeCache:]):
+        (getJSScriptSourceCode):
+        * API/JSScriptInternal.h: Copied from Source/_javascript_Core/API/JSVirtualMachineInternal.h.
+        * API/JSValueInternal.h:
+        * API/JSVirtualMachineInternal.h:
+        * API/tests/testapi.mm:
+        (+[JSContextFetchDelegate contextWithBlockForFetch:]):
+        (-[JSContextFetchDelegate context:fetchModuleForIdentifier:withResolveHandler:andRejectHandler:]):
+        (checkModuleCodeRan):
+        (checkModuleWasRejected):
+        (testFetch):
+        (testFetchWithTwoCycle):
+        (testFetchWithThreeCycle):
+        (testLoaderResolvesAbsoluteScriptURL):
+        (testLoaderRejectsNilScriptURL):
+        (testLoaderRejectsFailedFetch):
+        (testImportModuleTwice):
+        (+[JSContextFileLoaderDelegate newContext]):
+        (resolvePathToScripts):
+        (-[JSContextFileLoaderDelegate context:fetchModuleForIdentifier:withResolveHandler:andRejectHandler:]):
+        (testLoadBasicFile):
+        (testObjectiveCAPI):
+        * API/tests/testapiScripts/basic.js: Copied from Source/_javascript_Core/API/JSVirtualMachineInternal.h.
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * SourcesCocoa.txt:
+        * config.h:
+        * postprocess-headers.sh:
+        * runtime/CallData.cpp:
+        (JSC::call):
+        * runtime/CallData.h:
+        * runtime/Completion.cpp:
+        (JSC::loadAndEvaluateModule):
+        * runtime/Completion.h:
+        * runtime/JSCast.h:
+        (JSC::jsSecureCast):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::createProxyProperty):
+
 2019-01-14  Dominik Infuehr  <[email protected]>
 
         Fix property access on ARM with the baseline JIT

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (239932 => 239933)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1057,6 +1057,8 @@
 		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 */; };
 		53D444DC1DAF08AB00B92784 /* B3WasmAddressValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 53D444DB1DAF08AB00B92784 /* B3WasmAddressValue.h */; };
@@ -1065,6 +1067,8 @@
 		53E9E0AC1EAE83DF00FEE251 /* WasmMachineThreads.h in Headers */ = {isa = PBXBuildFile; fileRef = 53E9E0AA1EAE83DE00FEE251 /* WasmMachineThreads.h */; };
 		53E9E0AF1EAEC45700FEE251 /* WasmTierUpCount.h in Headers */ = {isa = PBXBuildFile; fileRef = 53E9E0AE1EAEC45700FEE251 /* WasmTierUpCount.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		53EAFE2F208DFAB4007D524B /* testapi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 531D4E191F59CDD200EC836C /* testapi.cpp */; };
+		53EE01B6218F691600AD1F8D /* JSScript.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EE01B5218F690F00AD1F8D /* JSScript.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		53EE01B8218F7EFF00AD1F8D /* JSScriptInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 53EE01B7218F7EFF00AD1F8D /* JSScriptInternal.h */; };
 		53F11F41209138D700E411A7 /* JSImmutableButterfly.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F11F40209138D700E411A7 /* JSImmutableButterfly.h */; };
 		53F40E851D58F9770099A1B6 /* WasmSections.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E841D58F9770099A1B6 /* WasmSections.h */; };
 		53F40E8B1D5901BB0099A1B6 /* WasmFunctionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */; };
@@ -2005,9 +2009,10 @@
 		5DBB1511131D0B130056AD36 /* Copy Support Script */ = {
 			isa = PBXCopyFilesBuildPhase;
 			buildActionMask = 12;
-			dstPath = "";
+			dstPath = testapiScripts;
 			dstSubfolderSpec = 16;
 			files = (
+				53C3D5E521ECE7720087FDFC /* basic.js in Copy Support Script */,
 				FECB8B2A1D25CB5A006F2463 /* testapi-function-overrides.js in Copy Support Script */,
 				5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */,
 			);
@@ -3559,6 +3564,10 @@
 		53B0BE351E561B0900A8FC29 /* ProxyableAccessCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProxyableAccessCase.cpp; sourceTree = "<group>"; };
 		53B0BE371E561B2400A8FC29 /* IntrinsicGetterAccessCase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntrinsicGetterAccessCase.cpp; sourceTree = "<group>"; };
 		53B601EB2034B8C5006BE667 /* JSCast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSCast.h; sourceTree = "<group>"; };
+		53C3D5E421ECE6CE0087FDFC /* basic.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode._javascript_; path = basic.js; sourceTree = "<group>"; };
+		53C3D5E621ED1C050087FDFC /* JSAPIGlobalObject.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSAPIGlobalObject.cpp; sourceTree = "<group>"; };
+		53C4F66A21B1A409002FD009 /* JSAPIGlobalObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSAPIGlobalObject.h; sourceTree = "<group>"; };
+		53C4F66C21B1A7CA002FD009 /* JSAPIGlobalObject.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = JSAPIGlobalObject.mm; sourceTree = "<group>"; };
 		53C6FEEE1E8ADFA900B18425 /* WasmOpcodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmOpcodeOrigin.h; sourceTree = "<group>"; };
 		53C6FEF01E8AFE0C00B18425 /* WasmOpcodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmOpcodeOrigin.cpp; sourceTree = "<group>"; };
 		53CA73071EA533D80076049D /* WasmBBQPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmBBQPlan.cpp; sourceTree = "<group>"; };
@@ -3571,6 +3580,9 @@
 		53E9E0A91EAE83DE00FEE251 /* WasmMachineThreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmMachineThreads.cpp; sourceTree = "<group>"; };
 		53E9E0AA1EAE83DE00FEE251 /* WasmMachineThreads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmMachineThreads.h; sourceTree = "<group>"; };
 		53E9E0AE1EAEC45700FEE251 /* WasmTierUpCount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmTierUpCount.h; sourceTree = "<group>"; };
+		53EE01B4218F690E00AD1F8D /* JSScript.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = JSScript.mm; sourceTree = "<group>"; };
+		53EE01B5218F690F00AD1F8D /* JSScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSScript.h; sourceTree = "<group>"; };
+		53EE01B7218F7EFF00AD1F8D /* JSScriptInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSScriptInternal.h; sourceTree = "<group>"; };
 		53F11F40209138D700E411A7 /* JSImmutableButterfly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSImmutableButterfly.h; sourceTree = "<group>"; };
 		53F11F422091749800E411A7 /* JSImmutableButterfly.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = JSImmutableButterfly.cpp; sourceTree = "<group>"; };
 		53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewPrototype.cpp; sourceTree = "<group>"; };
@@ -5544,6 +5556,7 @@
 		141211000A48772600480255 /* tests */ = {
 			isa = PBXGroup;
 			children = (
+				53C3D5E321ECE68E0087FDFC /* testapiScripts */,
 				FEF040501AAE662D00BD28B0 /* CompareAndSwapTest.cpp */,
 				FEF040521AAEC4ED00BD28B0 /* CompareAndSwapTest.h */,
 				C29ECB021804D0ED00D2CBB4 /* CurrentThisInsideBlockGetterTest.h */,
@@ -5943,6 +5956,9 @@
 				53529A4B1C457B75000B49C6 /* APIUtils.h */,
 				1CAA8B4A0D32C39A0041BCFF /* _javascript_.h */,
 				1CAA8B4B0D32C39A0041BCFF /* _javascript_Core.h */,
+				53C3D5E621ED1C050087FDFC /* JSAPIGlobalObject.cpp */,
+				53C4F66A21B1A409002FD009 /* JSAPIGlobalObject.h */,
+				53C4F66C21B1A7CA002FD009 /* JSAPIGlobalObject.mm */,
 				BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */,
 				BC0894D60FAFBA2D00001865 /* JSAPIValueWrapper.h */,
 				C2CF39C016E15A8100DD69BE /* JSAPIWrapperObject.h */,
@@ -5984,6 +6000,9 @@
 				A552C37D1ADDB8FE00139726 /* JSRemoteInspector.cpp */,
 				A552C37E1ADDB8FE00139726 /* JSRemoteInspector.h */,
 				95C18D3E0C90E7EF00E72F73 /* JSRetainPtr.h */,
+				53EE01B5218F690F00AD1F8D /* JSScript.h */,
+				53EE01B4218F690E00AD1F8D /* JSScript.mm */,
+				53EE01B7218F7EFF00AD1F8D /* JSScriptInternal.h */,
 				A7C0C4AA167C08CD0017011D /* JSScriptRef.cpp */,
 				A7C0C4AB167C08CD0017011D /* JSScriptRefPrivate.h */,
 				1482B74C0A43032800517CFC /* JSStringRef.cpp */,
@@ -6284,6 +6303,15 @@
 			path = "unified-sources";
 			sourceTree = "<group>";
 		};
+		53C3D5E321ECE68E0087FDFC /* testapiScripts */ = {
+			isa = PBXGroup;
+			children = (
+				53C3D5E421ECE6CE0087FDFC /* basic.js */,
+			);
+			name = testapiScripts;
+			path = API/tests/testapiScripts;
+			sourceTree = "<group>";
+		};
 		650FDF8D09D0FCA700769E54 /* Derived Sources */ = {
 			isa = PBXGroup;
 			children = (
@@ -9177,6 +9205,7 @@
 				0F5EF91F16878F7D003E5C25 /* JITThunks.h in Headers */,
 				0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */,
 				DC0184191D10C1890057B053 /* JITWorklist.h in Headers */,
+				53C4F66B21B1A409002FD009 /* JSAPIGlobalObject.h in Headers */,
 				840480131021A1D9008E7F01 /* JSAPIValueWrapper.h in Headers */,
 				C2CF39C216E15A8100DD69BE /* JSAPIWrapperObject.h in Headers */,
 				BC18C4170E16F5CD00B34460 /* JSArray.h in Headers */,
@@ -9297,8 +9326,10 @@
 				BC18C4260E16F5CD00B34460 /* JSRetainPtr.h in Headers */,
 				534638711E70CF3D00F12AC1 /* JSRunLoopTimer.h in Headers */,
 				14874AE615EBDE4A002E3587 /* JSScope.h in Headers */,
+				53EE01B6218F691600AD1F8D /* JSScript.h in Headers */,
 				9064337DD4B0402BAF34A592 /* JSScriptFetcher.h in Headers */,
 				E3201C1D1F8E82360076A032 /* JSScriptFetchParameters.h in Headers */,
+				53EE01B8218F7EFF00AD1F8D /* JSScriptInternal.h in Headers */,
 				A7C0C4AC168103020017011D /* JSScriptRefPrivate.h in Headers */,
 				0F919D11157F332C004A4E7D /* JSSegmentedVariableObject.h in Headers */,
 				0F4F82881E2FFDE00075184C /* JSSegmentedVariableObjectHeapCellType.h in Headers */,

Modified: trunk/Source/_javascript_Core/Sources.txt (239932 => 239933)


--- trunk/Source/_javascript_Core/Sources.txt	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/Sources.txt	2019-01-14 20:27:17 UTC (rev 239933)
@@ -21,6 +21,7 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 // THE POSSIBILITY OF SUCH DAMAGE.
 
+API/JSAPIGlobalObject.cpp
 API/JSAPIValueWrapper.cpp
 API/JSBase.cpp
 API/JSCTestRunnerUtils.cpp

Modified: trunk/Source/_javascript_Core/SourcesCocoa.txt (239932 => 239933)


--- trunk/Source/_javascript_Core/SourcesCocoa.txt	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/SourcesCocoa.txt	2019-01-14 20:27:17 UTC (rev 239933)
@@ -21,7 +21,9 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 // THE POSSIBILITY OF SUCH DAMAGE.
 
+API/JSAPIGlobalObject.mm
 API/JSAPIWrapperObject.mm
+API/JSScript.mm
 API/JSContext.mm
 API/JSManagedValue.mm
 API/JSRemoteInspector.cpp

Modified: trunk/Source/_javascript_Core/config.h (239932 => 239933)


--- trunk/Source/_javascript_Core/config.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/config.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2006 Samuel Weinig <[email protected]>
  *
  * This library is free software; you can redistribute it and/or
@@ -24,6 +24,7 @@
 #endif
 
 #define JSC_API_AVAILABLE(...)
+#define JSC_CLASS_AVAILABLE(...) JS_EXPORT
 // Use zero since it will be less than any possible version number.
 #define JSC_MAC_VERSION_TBA 0
 #define JSC_IOS_VERSION_TBA 0

Modified: trunk/Source/_javascript_Core/postprocess-headers.sh (239932 => 239933)


--- trunk/Source/_javascript_Core/postprocess-headers.sh	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/postprocess-headers.sh	2019-01-14 20:27:17 UTC (rev 239933)
@@ -72,8 +72,8 @@
             -e s/JSC_IOS_VERSION_TBA/${IOS_VERSION_NUMBER}/g
             -e s/JSC_API_AVAILABLE/API_AVAILABLE/
             -e s/JSC_API_DEPRECATED/API_DEPRECATED/
-            -e "s/^JSC_CLASS_AVAILABLE/JSC_EXTERN API_AVAILABLE/"
-            -e "s/^JSC_CLASS_DEPRECATED/JSC_EXTERN API_DEPRECATED/"
+            -e "s/^JSC_CLASS_AVAILABLE/JS_EXPORT API_AVAILABLE/"
+            -e "s/^JSC_CLASS_DEPRECATED/JS_EXPORT API_DEPRECATED/"
         )
     else
         SED_OPTIONS+=(

Modified: trunk/Source/_javascript_Core/runtime/CallData.cpp (239932 => 239933)


--- trunk/Source/_javascript_Core/runtime/CallData.cpp	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/runtime/CallData.cpp	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2018 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2019 Apple Inc. All Rights Reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -34,6 +34,24 @@
 
 namespace JSC {
 
+JSValue call(ExecState* exec, JSValue functionObject, const ArgList& args, const char* errorMessage)
+{
+    return call(exec, functionObject, functionObject, args, errorMessage);
+}
+
+JSValue call(ExecState* exec, JSValue functionObject, JSValue thisValue, const ArgList& args, const char* errorMessage)
+{
+    VM& vm = exec->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    CallData callData;
+    CallType callType = getCallData(vm, functionObject, callData);
+    if (callType == CallType::None)
+        return throwTypeError(exec, scope, errorMessage);
+
+    RELEASE_AND_RETURN(scope, call(exec, functionObject, callType, callData, thisValue, args));
+}
+
 JSValue call(ExecState* exec, JSValue functionObject, CallType callType, const CallData& callData, JSValue thisValue, const ArgList& args)
 {
     VM& vm = exec->vm();

Modified: trunk/Source/_javascript_Core/runtime/CallData.h (239932 => 239933)


--- trunk/Source/_javascript_Core/runtime/CallData.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/runtime/CallData.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -64,6 +64,10 @@
     Other
 };
 
+// Convenience wrapper so you don't need to deal with CallData and CallType unless you are going to use them.
+JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, const ArgList&, const char* errorMessage);
+JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, JSValue thisValue, const ArgList&, const char* errorMessage);
+
 JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&);
 JS_EXPORT_PRIVATE JSValue call(ExecState*, JSValue functionObject, CallType, const CallData&, JSValue thisValue, const ArgList&, NakedPtr<Exception>& returnedException);
 

Modified: trunk/Source/_javascript_Core/runtime/Completion.cpp (239932 => 239933)


--- trunk/Source/_javascript_Core/runtime/Completion.cpp	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/runtime/Completion.cpp	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten ([email protected])
  *  Copyright (C) 2001 Peter Kelly ([email protected])
- *  Copyright (C) 2003-2018 Apple Inc.
+ *  Copyright (C) 2003-2019 Apple Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -161,6 +161,16 @@
     return deferred->promise();
 }
 
+JSInternalPromise* loadAndEvaluateModule(ExecState* exec, Symbol* moduleId, JSValue parameters, JSValue scriptFetcher)
+{
+    VM& vm = exec->vm();
+    JSLockHolder lock(vm);
+    RELEASE_ASSERT(vm.atomicStringTable() == Thread::current().atomicStringTable());
+    RELEASE_ASSERT(!vm.isCollectorBusyOnCurrentThread());
+
+    return vm.vmEntryGlobalObject(exec)->moduleLoader()->loadAndEvaluateModule(exec, moduleId, parameters, scriptFetcher);
+}
+
 JSInternalPromise* loadAndEvaluateModule(ExecState* exec, const String& moduleName, JSValue parameters, JSValue scriptFetcher)
 {
     VM& vm = exec->vm();

Modified: trunk/Source/_javascript_Core/runtime/Completion.h (239932 => 239933)


--- trunk/Source/_javascript_Core/runtime/Completion.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/runtime/Completion.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1999-2001 Harri Porten ([email protected])
  *  Copyright (C) 2001 Peter Kelly ([email protected])
- *  Copyright (C) 2003, 2007 Apple Inc. All rights reserved.
+ *  Copyright (C) 2003-2019 Apple Inc. All rights reserved.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
@@ -33,6 +33,7 @@
 class JSObject;
 class ParserError;
 class SourceCode;
+class Symbol;
 class VM;
 class JSInternalPromise;
 
@@ -57,6 +58,7 @@
 JS_EXPORT_PRIVATE JSValue evaluateWithScopeExtension(ExecState*, const SourceCode&, JSObject* scopeExtension, NakedPtr<Exception>& returnedException);
 
 // Load the module source and evaluate it.
+JS_EXPORT_PRIVATE JSInternalPromise* loadAndEvaluateModule(ExecState*, Symbol* moduleId, JSValue parameters, JSValue scriptFetcher);
 JS_EXPORT_PRIVATE JSInternalPromise* loadAndEvaluateModule(ExecState*, const String& moduleName, JSValue parameters, JSValue scriptFetcher);
 JS_EXPORT_PRIVATE JSInternalPromise* loadAndEvaluateModule(ExecState*, const SourceCode&, JSValue scriptFetcher);
 

Modified: trunk/Source/_javascript_Core/runtime/JSCast.h (239932 => 239933)


--- trunk/Source/_javascript_Core/runtime/JSCast.h	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/runtime/JSCast.h	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2018-2019 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -165,4 +165,12 @@
     return jsDynamicCast<To>(vm, from.asCell());
 }
 
+template<typename To, typename From>
+To jsSecureCast(VM& vm, From from)
+{
+    auto* result = jsDynamicCast<To>(vm, from);
+    RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result);
+    return result;
 }
+
+}

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (239932 => 239933)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2019-01-14 20:17:24 UTC (rev 239932)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2019-01-14 20:27:17 UTC (rev 239933)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2018 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2019 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Cameron Zwarich ([email protected])
  *
  * Redistribution and use in source and binary forms, with or without
@@ -63,6 +63,7 @@
 #include "Error.h"
 #include "ErrorConstructor.h"
 #include "ErrorPrototype.h"
+#include "Exception.h"
 #include "FunctionConstructor.h"
 #include "FunctionPrototype.h"
 #include "GeneratorFunctionConstructor.h"
@@ -193,7 +194,7 @@
 
 namespace JSC {
 
-    static JSValue createProxyProperty(VM& vm, JSObject* object)
+static JSValue createProxyProperty(VM& vm, JSObject* object)
 {
     JSGlobalObject* global = jsCast<JSGlobalObject*>(object);
     return ProxyConstructor::create(vm, ProxyConstructor::createStructure(vm, global, global->functionPrototype()));
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to