c00fdc0fdc162c0212244e25b33af015c2c24d10
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSModuleLoader.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2016 Yusuke Suzuki <utatane.tea@gmail.com>.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "config.h"
28 #include "JSModuleLoader.h"
29
30 #include "BuiltinNames.h"
31 #include "CodeProfiling.h"
32 #include "Error.h"
33 #include "Exception.h"
34 #include "JSCInlines.h"
35 #include "JSGlobalObjectFunctions.h"
36 #include "JSInternalPromise.h"
37 #include "JSInternalPromiseDeferred.h"
38 #include "JSMap.h"
39 #include "JSModuleEnvironment.h"
40 #include "JSModuleRecord.h"
41 #include "JSSourceCode.h"
42 #include "ModuleAnalyzer.h"
43 #include "ModuleLoaderPrototype.h"
44 #include "Nodes.h"
45 #include "Parser.h"
46 #include "ParserError.h"
47
48 namespace JSC {
49
50 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSModuleLoader);
51
52 const ClassInfo JSModuleLoader::s_info = { "ModuleLoader", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSModuleLoader) };
53
54 JSModuleLoader::JSModuleLoader(VM& vm, Structure* structure)
55     : JSNonFinalObject(vm, structure)
56 {
57 }
58
59 void JSModuleLoader::finishCreation(ExecState* exec, VM& vm, JSGlobalObject* globalObject)
60 {
61     auto scope = DECLARE_CATCH_SCOPE(vm);
62
63     Base::finishCreation(vm);
64     ASSERT(inherits(info()));
65     JSMap* map = JSMap::create(exec, vm, globalObject->mapStructure());
66     RELEASE_ASSERT(!scope.exception());
67     putDirect(vm, Identifier::fromString(&vm, "registry"), map);
68 }
69
70 // ------------------------------ Functions --------------------------------
71
72 static String printableModuleKey(ExecState* exec, JSValue key)
73 {
74     if (key.isString() || key.isSymbol())
75         return key.toPropertyKey(exec).impl();
76     return exec->propertyNames().emptyIdentifier.impl();
77 }
78
79 JSValue JSModuleLoader::provide(ExecState* exec, JSValue key, Status status, const SourceCode& sourceCode)
80 {
81     VM& vm = exec->vm();
82     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().providePublicName()));
83     CallData callData;
84     CallType callType = JSC::getCallData(function, callData);
85     ASSERT(callType != CallType::None);
86
87     SourceCode source { sourceCode };
88     MarkedArgumentBuffer arguments;
89     arguments.append(key);
90     arguments.append(jsNumber(status));
91     arguments.append(JSSourceCode::create(vm, WTFMove(source)));
92
93     return call(exec, function, callType, callData, this, arguments);
94 }
95
96 JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue initiator)
97 {
98     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().loadAndEvaluateModulePublicName()));
99     CallData callData;
100     CallType callType = JSC::getCallData(function, callData);
101     ASSERT(callType != CallType::None);
102
103     MarkedArgumentBuffer arguments;
104     arguments.append(moduleName);
105     arguments.append(referrer);
106     arguments.append(initiator);
107
108     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
109 }
110
111 JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleName, JSValue referrer, JSValue initiator)
112 {
113     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().loadModulePublicName()));
114     CallData callData;
115     CallType callType = JSC::getCallData(function, callData);
116     ASSERT(callType != CallType::None);
117
118     MarkedArgumentBuffer arguments;
119     arguments.append(moduleName);
120     arguments.append(referrer);
121     arguments.append(initiator);
122
123     return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
124 }
125
126 JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey, JSValue initiator)
127 {
128     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().linkAndEvaluateModulePublicName()));
129     CallData callData;
130     CallType callType = JSC::getCallData(function, callData);
131     ASSERT(callType != CallType::None);
132
133     MarkedArgumentBuffer arguments;
134     arguments.append(moduleKey);
135     arguments.append(initiator);
136
137     return call(exec, function, callType, callData, this, arguments);
138 }
139
140 JSInternalPromise* JSModuleLoader::importModule(ExecState* exec, JSString* moduleName, const SourceOrigin& referrer)
141 {
142     if (Options::dumpModuleLoadingState())
143         dataLog("Loader [import] ", printableModuleKey(exec, moduleName), "\n");
144
145     auto* globalObject = exec->lexicalGlobalObject();
146     VM& vm = globalObject->vm();
147     auto scope = DECLARE_CATCH_SCOPE(vm);
148
149     if (globalObject->globalObjectMethodTable()->moduleLoaderImportModule)
150         return globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, exec, this, moduleName, referrer);
151
152     auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
153     auto moduleNameString = moduleName->value(exec);
154     if (UNLIKELY(scope.exception())) {
155         JSValue exception = scope.exception()->value();
156         scope.clearException();
157         deferred->reject(exec, exception);
158         return deferred->promise();
159     }
160     deferred->reject(exec, createError(exec, makeString("Could not import the module '", moduleNameString, "'.")));
161     return deferred->promise();
162 }
163
164 JSInternalPromise* JSModuleLoader::resolve(ExecState* exec, JSValue name, JSValue referrer, JSValue initiator)
165 {
166     if (Options::dumpModuleLoadingState())
167         dataLog("Loader [resolve] ", printableModuleKey(exec, name), "\n");
168
169     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
170     if (globalObject->globalObjectMethodTable()->moduleLoaderResolve)
171         return globalObject->globalObjectMethodTable()->moduleLoaderResolve(globalObject, exec, this, name, referrer, initiator);
172     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
173     deferred->resolve(exec, name);
174     return deferred->promise();
175 }
176
177 JSInternalPromise* JSModuleLoader::fetch(ExecState* exec, JSValue key, JSValue initiator)
178 {
179     if (Options::dumpModuleLoadingState())
180         dataLog("Loader [fetch] ", printableModuleKey(exec, key), "\n");
181
182     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
183     VM& vm = globalObject->vm();
184     auto scope = DECLARE_CATCH_SCOPE(vm);
185     if (globalObject->globalObjectMethodTable()->moduleLoaderFetch)
186         return globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, initiator);
187     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
188     String moduleKey = key.toWTFString(exec);
189     if (UNLIKELY(scope.exception())) {
190         JSValue exception = scope.exception()->value();
191         scope.clearException();
192         deferred->reject(exec, exception);
193         return deferred->promise();
194     }
195     deferred->reject(exec, createError(exec, makeString("Could not open the module '", moduleKey, "'.")));
196     return deferred->promise();
197 }
198
199 JSInternalPromise* JSModuleLoader::instantiate(ExecState* exec, JSValue key, JSValue source, JSValue initiator)
200 {
201     if (Options::dumpModuleLoadingState())
202         dataLog("Loader [instantiate] ", printableModuleKey(exec, key), "\n");
203
204     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
205     if (globalObject->globalObjectMethodTable()->moduleLoaderInstantiate)
206         return globalObject->globalObjectMethodTable()->moduleLoaderInstantiate(globalObject, exec, this, key, source, initiator);
207     JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
208     deferred->resolve(exec, jsUndefined());
209     return deferred->promise();
210 }
211
212 JSValue JSModuleLoader::evaluate(ExecState* exec, JSValue key, JSValue moduleRecordValue, JSValue initiator)
213 {
214     if (Options::dumpModuleLoadingState())
215         dataLog("Loader [evaluate] ", printableModuleKey(exec, key), "\n");
216
217     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
218     if (globalObject->globalObjectMethodTable()->moduleLoaderEvaluate)
219         return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, initiator);
220
221     JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(moduleRecordValue);
222     if (!moduleRecord)
223         return jsUndefined();
224     return moduleRecord->evaluate(exec);
225 }
226
227 JSModuleNamespaceObject* JSModuleLoader::getModuleNamespaceObject(ExecState* exec, JSValue moduleRecordValue)
228 {
229     VM& vm = exec->vm();
230     auto scope = DECLARE_THROW_SCOPE(vm);
231
232     auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(moduleRecordValue);
233     if (!moduleRecord) {
234         throwTypeError(exec, scope);
235         return nullptr;
236     }
237
238     scope.release();
239     return moduleRecord->getModuleNamespace(exec);
240 }
241
242 } // namespace JSC