summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSModuleLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSModuleLoader.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/JSModuleLoader.cpp256
1 files changed, 256 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/runtime/JSModuleLoader.cpp b/Source/JavaScriptCore/runtime/JSModuleLoader.cpp
new file mode 100644
index 000000000..bbf3e427e
--- /dev/null
+++ b/Source/JavaScriptCore/runtime/JSModuleLoader.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>.
+ *
+ * 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 "JSModuleLoader.h"
+
+#include "BuiltinNames.h"
+#include "CodeProfiling.h"
+#include "Error.h"
+#include "Exception.h"
+#include "JSCInlines.h"
+#include "JSGlobalObjectFunctions.h"
+#include "JSInternalPromise.h"
+#include "JSInternalPromiseDeferred.h"
+#include "JSMap.h"
+#include "JSModuleEnvironment.h"
+#include "JSModuleRecord.h"
+#include "JSSourceCode.h"
+#include "ModuleAnalyzer.h"
+#include "ModuleLoaderPrototype.h"
+#include "Nodes.h"
+#include "Parser.h"
+#include "ParserError.h"
+
+namespace JSC {
+
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSModuleLoader);
+
+const ClassInfo JSModuleLoader::s_info = { "ModuleLoader", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSModuleLoader) };
+
+JSModuleLoader::JSModuleLoader(VM& vm, Structure* structure)
+ : JSNonFinalObject(vm, structure)
+{
+}
+
+void JSModuleLoader::finishCreation(ExecState* exec, VM& vm, JSGlobalObject* globalObject)
+{
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ Base::finishCreation(vm);
+ ASSERT(inherits(vm, info()));
+ JSMap* map = JSMap::create(exec, vm, globalObject->mapStructure());
+ RELEASE_ASSERT(!scope.exception());
+ putDirect(vm, Identifier::fromString(&vm, "registry"), map);
+}
+
+// ------------------------------ Functions --------------------------------
+
+static String printableModuleKey(ExecState* exec, JSValue key)
+{
+ if (key.isString() || key.isSymbol())
+ return key.toPropertyKey(exec).impl();
+ return exec->propertyNames().emptyIdentifier.impl();
+}
+
+JSValue JSModuleLoader::provide(ExecState* exec, JSValue key, Status status, const SourceCode& sourceCode)
+{
+ VM& vm = exec->vm();
+ JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().providePublicName()));
+ CallData callData;
+ CallType callType = JSC::getCallData(function, callData);
+ ASSERT(callType != CallType::None);
+
+ SourceCode source { sourceCode };
+ MarkedArgumentBuffer arguments;
+ arguments.append(key);
+ arguments.append(jsNumber(status));
+ arguments.append(JSSourceCode::create(vm, WTFMove(source)));
+
+ return call(exec, function, callType, callData, this, arguments);
+}
+
+JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
+{
+ JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().loadAndEvaluateModulePublicName()));
+ CallData callData;
+ CallType callType = JSC::getCallData(function, callData);
+ ASSERT(callType != CallType::None);
+
+ MarkedArgumentBuffer arguments;
+ arguments.append(moduleName);
+ arguments.append(referrer);
+ arguments.append(scriptFetcher);
+
+ return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
+}
+
+JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue scriptFetcher)
+{
+ JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().loadModulePublicName()));
+ CallData callData;
+ CallType callType = JSC::getCallData(function, callData);
+ ASSERT(callType != CallType::None);
+
+ MarkedArgumentBuffer arguments;
+ arguments.append(moduleName);
+ arguments.append(referrer);
+ arguments.append(scriptFetcher);
+
+ return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
+}
+
+JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey, JSValue scriptFetcher)
+{
+ JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().linkAndEvaluateModulePublicName()));
+ CallData callData;
+ CallType callType = JSC::getCallData(function, callData);
+ ASSERT(callType != CallType::None);
+
+ MarkedArgumentBuffer arguments;
+ arguments.append(moduleKey);
+ arguments.append(scriptFetcher);
+
+ return call(exec, function, callType, callData, this, arguments);
+}
+
+JSInternalPromise* JSModuleLoader::requestImportModule(ExecState* exec, const Identifier& moduleKey, JSValue scriptFetcher)
+{
+ auto* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().requestImportModulePublicName()));
+ CallData callData;
+ auto callType = JSC::getCallData(function, callData);
+ ASSERT(callType != CallType::None);
+
+ MarkedArgumentBuffer arguments;
+ arguments.append(jsString(exec, moduleKey.impl()));
+ arguments.append(scriptFetcher);
+
+ return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
+}
+
+JSInternalPromise* JSModuleLoader::importModule(ExecState* exec, JSString* moduleName, const SourceOrigin& referrer)
+{
+ if (Options::dumpModuleLoadingState())
+ dataLog("Loader [import] ", printableModuleKey(exec, moduleName), "\n");
+
+ auto* globalObject = exec->lexicalGlobalObject();
+ VM& vm = globalObject->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ if (globalObject->globalObjectMethodTable()->moduleLoaderImportModule)
+ return globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, exec, this, moduleName, referrer);
+
+ auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
+ auto moduleNameString = moduleName->value(exec);
+ if (UNLIKELY(scope.exception())) {
+ JSValue exception = scope.exception()->value();
+ scope.clearException();
+ deferred->reject(exec, exception);
+ return deferred->promise();
+ }
+ deferred->reject(exec, createError(exec, makeString("Could not import the module '", moduleNameString, "'.")));
+ return deferred->promise();
+}
+
+JSInternalPromise* JSModuleLoader::resolve(ExecState* exec, JSValue name, JSValue referrer, JSValue scriptFetcher)
+{
+ if (Options::dumpModuleLoadingState())
+ dataLog("Loader [resolve] ", printableModuleKey(exec, name), "\n");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ if (globalObject->globalObjectMethodTable()->moduleLoaderResolve)
+ return globalObject->globalObjectMethodTable()->moduleLoaderResolve(globalObject, exec, this, name, referrer, scriptFetcher);
+ JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
+ deferred->resolve(exec, name);
+ return deferred->promise();
+}
+
+JSInternalPromise* JSModuleLoader::fetch(ExecState* exec, JSValue key, JSValue scriptFetcher)
+{
+ if (Options::dumpModuleLoadingState())
+ dataLog("Loader [fetch] ", printableModuleKey(exec, key), "\n");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ VM& vm = globalObject->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ if (globalObject->globalObjectMethodTable()->moduleLoaderFetch)
+ return globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, scriptFetcher);
+ JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
+ String moduleKey = key.toWTFString(exec);
+ if (UNLIKELY(scope.exception())) {
+ JSValue exception = scope.exception()->value();
+ scope.clearException();
+ deferred->reject(exec, exception);
+ return deferred->promise();
+ }
+ deferred->reject(exec, createError(exec, makeString("Could not open the module '", moduleKey, "'.")));
+ return deferred->promise();
+}
+
+JSInternalPromise* JSModuleLoader::instantiate(ExecState* exec, JSValue key, JSValue source, JSValue scriptFetcher)
+{
+ if (Options::dumpModuleLoadingState())
+ dataLog("Loader [instantiate] ", printableModuleKey(exec, key), "\n");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ if (globalObject->globalObjectMethodTable()->moduleLoaderInstantiate)
+ return globalObject->globalObjectMethodTable()->moduleLoaderInstantiate(globalObject, exec, this, key, source, scriptFetcher);
+ JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
+ deferred->resolve(exec, jsUndefined());
+ return deferred->promise();
+}
+
+JSValue JSModuleLoader::evaluate(ExecState* exec, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher)
+{
+ if (Options::dumpModuleLoadingState())
+ dataLog("Loader [evaluate] ", printableModuleKey(exec, key), "\n");
+
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ if (globalObject->globalObjectMethodTable()->moduleLoaderEvaluate)
+ return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, scriptFetcher);
+
+ JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(exec->vm(), moduleRecordValue);
+ if (!moduleRecord)
+ return jsUndefined();
+ return moduleRecord->evaluate(exec);
+}
+
+JSModuleNamespaceObject* JSModuleLoader::getModuleNamespaceObject(ExecState* exec, JSValue moduleRecordValue)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(vm, moduleRecordValue);
+ if (!moduleRecord) {
+ throwTypeError(exec, scope);
+ return nullptr;
+ }
+
+ scope.release();
+ return moduleRecord->getModuleNamespace(exec);
+}
+
+} // namespace JSC