1/*
2 * Copyright (C) 2015-2018 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2016 Yusuke Suzuki <[email protected]>.
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 "CatchScope.h"
32#include "CodeProfiling.h"
33#include "Error.h"
34#include "Exception.h"
35#include "JSCInlines.h"
36#include "JSGlobalObjectFunctions.h"
37#include "JSInternalPromise.h"
38#include "JSInternalPromiseDeferred.h"
39#include "JSMap.h"
40#include "JSModuleEnvironment.h"
41#include "JSModuleNamespaceObject.h"
42#include "JSModuleRecord.h"
43#include "JSSourceCode.h"
44#include "ModuleAnalyzer.h"
45#include "Nodes.h"
46#include "ObjectConstructor.h"
47#include "Parser.h"
48#include "ParserError.h"
49#include "WebAssemblyPrototype.h"
50
51namespace JSC {
52
53static EncodedJSValue JSC_HOST_CALL moduleLoaderParseModule(ExecState*);
54static EncodedJSValue JSC_HOST_CALL moduleLoaderRequestedModules(ExecState*);
55static EncodedJSValue JSC_HOST_CALL moduleLoaderEvaluate(ExecState*);
56static EncodedJSValue JSC_HOST_CALL moduleLoaderModuleDeclarationInstantiation(ExecState*);
57static EncodedJSValue JSC_HOST_CALL moduleLoaderResolve(ExecState*);
58static EncodedJSValue JSC_HOST_CALL moduleLoaderResolveSync(ExecState*);
59static EncodedJSValue JSC_HOST_CALL moduleLoaderFetch(ExecState*);
60static EncodedJSValue JSC_HOST_CALL moduleLoaderGetModuleNamespaceObject(ExecState*);
61
62}
63
64#include "JSModuleLoader.lut.h"
65
66namespace JSC {
67
68STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSModuleLoader);
69
70const ClassInfo JSModuleLoader::s_info = { "ModuleLoader", &Base::s_info, &moduleLoaderTable, nullptr, CREATE_METHOD_TABLE(JSModuleLoader) };
71
72/* Source for JSModuleLoader.lut.h
73@begin moduleLoaderTable
74 ensureRegistered JSBuiltin DontEnum|Function 1
75 forceFulfillPromise JSBuiltin DontEnum|Function 2
76 fulfillFetch JSBuiltin DontEnum|Function 2
77 requestFetch JSBuiltin DontEnum|Function 3
78 requestInstantiate JSBuiltin DontEnum|Function 3
79 requestSatisfy JSBuiltin DontEnum|Function 3
80 link JSBuiltin DontEnum|Function 2
81 moduleDeclarationInstantiation moduleLoaderModuleDeclarationInstantiation DontEnum|Function 2
82 moduleEvaluation JSBuiltin DontEnum|Function 2
83 evaluate moduleLoaderEvaluate DontEnum|Function 3
84 provideFetch JSBuiltin DontEnum|Function 2
85 loadAndEvaluateModule JSBuiltin DontEnum|Function 3
86 loadModule JSBuiltin DontEnum|Function 3
87 linkAndEvaluateModule JSBuiltin DontEnum|Function 2
88 requestImportModule JSBuiltin DontEnum|Function 3
89 getModuleNamespaceObject moduleLoaderGetModuleNamespaceObject DontEnum|Function 1
90 parseModule moduleLoaderParseModule DontEnum|Function 2
91 requestedModules moduleLoaderRequestedModules DontEnum|Function 1
92 resolve moduleLoaderResolve DontEnum|Function 2
93 resolveSync moduleLoaderResolveSync DontEnum|Function 2
94 fetch moduleLoaderFetch DontEnum|Function 3
95@end
96*/
97
98JSModuleLoader::JSModuleLoader(VM& vm, Structure* structure)
99 : JSNonFinalObject(vm, structure)
100{
101}
102
103void JSModuleLoader::finishCreation(ExecState* exec, VM& vm, JSGlobalObject* globalObject)
104{
105 auto scope = DECLARE_CATCH_SCOPE(vm);
106
107 Base::finishCreation(vm);
108 ASSERT(inherits(vm, info()));
109 JSMap* map = JSMap::create(exec, vm, globalObject->mapStructure());
110 scope.releaseAssertNoException();
111 putDirect(vm, Identifier::fromString(&vm, "registry"), map);
112}
113
114// ------------------------------ Functions --------------------------------
115
116static String printableModuleKey(ExecState* exec, JSValue key)
117{
118 VM& vm = exec->vm();
119 auto scope = DECLARE_THROW_SCOPE(vm);
120 if (key.isString() || key.isSymbol()) {
121 auto propertyName = key.toPropertyKey(exec);
122 scope.assertNoException(); // This is OK since this function is just for debugging purpose.
123 return propertyName.impl();
124 }
125 return vm.propertyNames->emptyIdentifier.impl();
126}
127
128JSValue JSModuleLoader::provideFetch(ExecState* exec, JSValue key, const SourceCode& sourceCode)
129{
130 VM& vm = exec->vm();
131 auto scope = DECLARE_THROW_SCOPE(vm);
132
133 JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().provideFetchPublicName()));
134 RETURN_IF_EXCEPTION(scope, { });
135 CallData callData;
136 CallType callType = JSC::getCallData(vm, function, callData);
137 ASSERT(callType != CallType::None);
138
139 SourceCode source { sourceCode };
140 MarkedArgumentBuffer arguments;
141 arguments.append(key);
142 arguments.append(JSSourceCode::create(vm, WTFMove(source)));
143 ASSERT(!arguments.hasOverflowed());
144
145 RELEASE_AND_RETURN(scope, call(exec, function, callType, callData, this, arguments));
146}
147
148JSInternalPromise* JSModuleLoader::loadAndEvaluateModule(ExecState* exec, JSValue moduleName, JSValue parameters, JSValue scriptFetcher)
149{
150 VM& vm = exec->vm();
151 auto scope = DECLARE_THROW_SCOPE(vm);
152
153 JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().loadAndEvaluateModulePublicName()));
154 RETURN_IF_EXCEPTION(scope, nullptr);
155 CallData callData;
156 CallType callType = JSC::getCallData(vm, function, callData);
157 ASSERT(callType != CallType::None);
158
159 MarkedArgumentBuffer arguments;
160 arguments.append(moduleName);
161 arguments.append(parameters);
162 arguments.append(scriptFetcher);
163 ASSERT(!arguments.hasOverflowed());
164
165 JSValue promise = call(exec, function, callType, callData, this, arguments);
166 RETURN_IF_EXCEPTION(scope, nullptr);
167 return jsCast<JSInternalPromise*>(promise);
168}
169
170JSInternalPromise* JSModuleLoader::loadModule(ExecState* exec, JSValue moduleName, JSValue parameters, JSValue scriptFetcher)
171{
172 VM& vm = exec->vm();
173 auto scope = DECLARE_THROW_SCOPE(vm);
174
175 JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().loadModulePublicName()));
176 RETURN_IF_EXCEPTION(scope, nullptr);
177 CallData callData;
178 CallType callType = JSC::getCallData(vm, function, callData);
179 ASSERT(callType != CallType::None);
180
181 MarkedArgumentBuffer arguments;
182 arguments.append(moduleName);
183 arguments.append(parameters);
184 arguments.append(scriptFetcher);
185 ASSERT(!arguments.hasOverflowed());
186
187 JSValue promise = call(exec, function, callType, callData, this, arguments);
188 RETURN_IF_EXCEPTION(scope, nullptr);
189 return jsCast<JSInternalPromise*>(promise);
190}
191
192JSValue JSModuleLoader::linkAndEvaluateModule(ExecState* exec, JSValue moduleKey, JSValue scriptFetcher)
193{
194 VM& vm = exec->vm();
195 auto scope = DECLARE_THROW_SCOPE(vm);
196
197 JSObject* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().linkAndEvaluateModulePublicName()));
198 RETURN_IF_EXCEPTION(scope, { });
199 CallData callData;
200 CallType callType = JSC::getCallData(vm, function, callData);
201 ASSERT(callType != CallType::None);
202
203 MarkedArgumentBuffer arguments;
204 arguments.append(moduleKey);
205 arguments.append(scriptFetcher);
206 ASSERT(!arguments.hasOverflowed());
207
208 RELEASE_AND_RETURN(scope, call(exec, function, callType, callData, this, arguments));
209}
210
211JSInternalPromise* JSModuleLoader::requestImportModule(ExecState* exec, const Identifier& moduleKey, JSValue parameters, JSValue scriptFetcher)
212{
213 VM& vm = exec->vm();
214 auto scope = DECLARE_THROW_SCOPE(vm);
215
216 auto* function = jsCast<JSObject*>(get(exec, vm.propertyNames->builtinNames().requestImportModulePublicName()));
217 RETURN_IF_EXCEPTION(scope, nullptr);
218 CallData callData;
219 auto callType = JSC::getCallData(vm, function, callData);
220 ASSERT(callType != CallType::None);
221
222 MarkedArgumentBuffer arguments;
223 arguments.append(jsString(exec, moduleKey.impl()));
224 arguments.append(parameters);
225 arguments.append(scriptFetcher);
226 ASSERT(!arguments.hasOverflowed());
227
228 JSValue promise = call(exec, function, callType, callData, this, arguments);
229 RETURN_IF_EXCEPTION(scope, nullptr);
230 return jsCast<JSInternalPromise*>(promise);
231}
232
233JSInternalPromise* JSModuleLoader::importModule(ExecState* exec, JSString* moduleName, JSValue parameters, const SourceOrigin& referrer)
234{
235 if (Options::dumpModuleLoadingState())
236 dataLog("Loader [import] ", printableModuleKey(exec, moduleName), "\n");
237
238 auto* globalObject = exec->lexicalGlobalObject();
239 VM& vm = globalObject->vm();
240 auto throwScope = DECLARE_THROW_SCOPE(vm);
241
242 if (globalObject->globalObjectMethodTable()->moduleLoaderImportModule)
243 RELEASE_AND_RETURN(throwScope, globalObject->globalObjectMethodTable()->moduleLoaderImportModule(globalObject, exec, this, moduleName, parameters, referrer));
244
245 auto* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
246 RETURN_IF_EXCEPTION(throwScope, nullptr);
247
248 auto catchScope = DECLARE_CATCH_SCOPE(vm);
249 auto moduleNameString = moduleName->value(exec);
250 if (UNLIKELY(catchScope.exception())) {
251 JSValue exception = catchScope.exception()->value();
252 catchScope.clearException();
253 deferred->reject(exec, exception);
254 catchScope.clearException();
255 return deferred->promise();
256 }
257 deferred->reject(exec, createError(exec, makeString("Could not import the module '", moduleNameString, "'.")));
258 catchScope.clearException();
259 return deferred->promise();
260}
261
262Identifier JSModuleLoader::resolveSync(ExecState* exec, JSValue name, JSValue referrer, JSValue scriptFetcher)
263{
264 if (Options::dumpModuleLoadingState())
265 dataLog("Loader [resolve] ", printableModuleKey(exec, name), "\n");
266
267 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
268 if (globalObject->globalObjectMethodTable()->moduleLoaderResolve)
269 return globalObject->globalObjectMethodTable()->moduleLoaderResolve(globalObject, exec, this, name, referrer, scriptFetcher);
270 return name.toPropertyKey(exec);
271}
272
273JSInternalPromise* JSModuleLoader::resolve(ExecState* exec, JSValue name, JSValue referrer, JSValue scriptFetcher)
274{
275 VM& vm = exec->vm();
276 auto throwScope = DECLARE_THROW_SCOPE(vm);
277
278 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, exec->lexicalGlobalObject());
279 RETURN_IF_EXCEPTION(throwScope, nullptr);
280
281 auto catchScope = DECLARE_CATCH_SCOPE(vm);
282
283 const Identifier moduleKey = resolveSync(exec, name, referrer, scriptFetcher);
284 if (UNLIKELY(catchScope.exception())) {
285 JSValue exception = catchScope.exception();
286 catchScope.clearException();
287 auto result = deferred->reject(exec, exception);
288 catchScope.clearException();
289 return result;
290 }
291 auto result = deferred->resolve(exec, identifierToJSValue(vm, moduleKey));
292 catchScope.clearException();
293 return result;
294}
295
296JSInternalPromise* JSModuleLoader::fetch(ExecState* exec, JSValue key, JSValue parameters, JSValue scriptFetcher)
297{
298 if (Options::dumpModuleLoadingState())
299 dataLog("Loader [fetch] ", printableModuleKey(exec, key), "\n");
300
301 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
302 VM& vm = globalObject->vm();
303 auto throwScope = DECLARE_THROW_SCOPE(vm);
304
305 if (globalObject->globalObjectMethodTable()->moduleLoaderFetch)
306 RELEASE_AND_RETURN(throwScope, globalObject->globalObjectMethodTable()->moduleLoaderFetch(globalObject, exec, this, key, parameters, scriptFetcher));
307
308 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, globalObject);
309 RETURN_IF_EXCEPTION(throwScope, nullptr);
310
311 auto catchScope = DECLARE_CATCH_SCOPE(vm);
312
313 String moduleKey = key.toWTFString(exec);
314 if (UNLIKELY(catchScope.exception())) {
315 JSValue exception = catchScope.exception()->value();
316 catchScope.clearException();
317 deferred->reject(exec, exception);
318 catchScope.clearException();
319 return deferred->promise();
320 }
321 deferred->reject(exec, createError(exec, makeString("Could not open the module '", moduleKey, "'.")));
322 catchScope.clearException();
323 return deferred->promise();
324}
325
326JSObject* JSModuleLoader::createImportMetaProperties(ExecState* exec, JSValue key, JSModuleRecord* moduleRecord, JSValue scriptFetcher)
327{
328 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
329 if (globalObject->globalObjectMethodTable()->moduleLoaderCreateImportMetaProperties)
330 return globalObject->globalObjectMethodTable()->moduleLoaderCreateImportMetaProperties(globalObject, exec, this, key, moduleRecord, scriptFetcher);
331 return constructEmptyObject(exec, exec->lexicalGlobalObject()->nullPrototypeObjectStructure());
332}
333
334JSValue JSModuleLoader::evaluate(ExecState* exec, JSValue key, JSValue moduleRecordValue, JSValue scriptFetcher)
335{
336 if (Options::dumpModuleLoadingState())
337 dataLog("Loader [evaluate] ", printableModuleKey(exec, key), "\n");
338
339 JSGlobalObject* globalObject = exec->lexicalGlobalObject();
340 if (globalObject->globalObjectMethodTable()->moduleLoaderEvaluate)
341 return globalObject->globalObjectMethodTable()->moduleLoaderEvaluate(globalObject, exec, this, key, moduleRecordValue, scriptFetcher);
342
343 return evaluateNonVirtual(exec, key, moduleRecordValue, scriptFetcher);
344}
345
346JSValue JSModuleLoader::evaluateNonVirtual(ExecState* exec, JSValue, JSValue moduleRecordValue, JSValue)
347{
348 if (auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(exec->vm(), moduleRecordValue))
349 return moduleRecord->evaluate(exec);
350 return jsUndefined();
351}
352
353JSModuleNamespaceObject* JSModuleLoader::getModuleNamespaceObject(ExecState* exec, JSValue moduleRecordValue)
354{
355 VM& vm = exec->vm();
356 auto scope = DECLARE_THROW_SCOPE(vm);
357
358 auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(vm, moduleRecordValue);
359 if (!moduleRecord) {
360 throwTypeError(exec, scope);
361 return nullptr;
362 }
363
364 RELEASE_AND_RETURN(scope, moduleRecord->getModuleNamespace(exec));
365}
366
367// ------------------------------ Functions --------------------------------
368
369EncodedJSValue JSC_HOST_CALL moduleLoaderParseModule(ExecState* exec)
370{
371 VM& vm = exec->vm();
372 auto throwScope = DECLARE_THROW_SCOPE(vm);
373
374 JSInternalPromiseDeferred* deferred = JSInternalPromiseDeferred::tryCreate(exec, exec->lexicalGlobalObject());
375 RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
376
377 auto catchScope = DECLARE_CATCH_SCOPE(vm);
378 auto reject = [&] (JSValue rejectionReason) {
379 catchScope.clearException();
380 auto result = deferred->reject(exec, rejectionReason);
381 catchScope.clearException();
382 return JSValue::encode(result);
383 };
384
385 const Identifier moduleKey = exec->argument(0).toPropertyKey(exec);
386 if (UNLIKELY(catchScope.exception()))
387 return reject(catchScope.exception());
388
389 JSValue source = exec->argument(1);
390 auto* jsSourceCode = jsCast<JSSourceCode*>(source);
391 SourceCode sourceCode = jsSourceCode->sourceCode();
392
393#if ENABLE(WEBASSEMBLY)
394 if (sourceCode.provider()->sourceType() == SourceProviderSourceType::WebAssembly)
395 return JSValue::encode(WebAssemblyPrototype::instantiate(exec, deferred, moduleKey, jsSourceCode));
396#endif
397
398 CodeProfiling profile(sourceCode);
399
400 ParserError error;
401 std::unique_ptr<ModuleProgramNode> moduleProgramNode = parse<ModuleProgramNode>(
402 &vm, sourceCode, Identifier(), JSParserBuiltinMode::NotBuiltin,
403 JSParserStrictMode::Strict, JSParserScriptMode::Module, SourceParseMode::ModuleAnalyzeMode, SuperBinding::NotNeeded, error);
404 if (error.isValid())
405 return reject(error.toErrorObject(exec->lexicalGlobalObject(), sourceCode));
406 ASSERT(moduleProgramNode);
407
408 ModuleAnalyzer moduleAnalyzer(exec, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
409 if (UNLIKELY(catchScope.exception()))
410 return reject(catchScope.exception());
411
412 auto result = deferred->resolve(exec, moduleAnalyzer.analyze(*moduleProgramNode));
413 catchScope.clearException();
414 return JSValue::encode(result);
415}
416
417EncodedJSValue JSC_HOST_CALL moduleLoaderRequestedModules(ExecState* exec)
418{
419 VM& vm = exec->vm();
420 auto scope = DECLARE_THROW_SCOPE(vm);
421 auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(vm, exec->argument(0));
422 if (!moduleRecord)
423 RELEASE_AND_RETURN(scope, JSValue::encode(constructEmptyArray(exec, nullptr)));
424
425 JSArray* result = constructEmptyArray(exec, nullptr, moduleRecord->requestedModules().size());
426 RETURN_IF_EXCEPTION(scope, encodedJSValue());
427 size_t i = 0;
428 for (auto& key : moduleRecord->requestedModules()) {
429 result->putDirectIndex(exec, i++, jsString(exec, key.get()));
430 RETURN_IF_EXCEPTION(scope, encodedJSValue());
431 }
432 return JSValue::encode(result);
433}
434
435EncodedJSValue JSC_HOST_CALL moduleLoaderModuleDeclarationInstantiation(ExecState* exec)
436{
437 VM& vm = exec->vm();
438 auto scope = DECLARE_THROW_SCOPE(vm);
439 auto* moduleRecord = jsDynamicCast<AbstractModuleRecord*>(vm, exec->argument(0));
440 if (!moduleRecord)
441 return JSValue::encode(jsUndefined());
442
443 if (Options::dumpModuleLoadingState())
444 dataLog("Loader [link] ", moduleRecord->moduleKey(), "\n");
445
446 moduleRecord->link(exec, exec->argument(1));
447 RETURN_IF_EXCEPTION(scope, encodedJSValue());
448
449 return JSValue::encode(jsUndefined());
450}
451
452// ------------------------------ Hook Functions ---------------------------
453
454EncodedJSValue JSC_HOST_CALL moduleLoaderResolve(ExecState* exec)
455{
456 VM& vm = exec->vm();
457 // Hook point, Loader.resolve.
458 // https://whatwg.github.io/loader/#browser-resolve
459 // Take the name and resolve it to the unique identifier for the resource location.
460 // For example, take the "jquery" and return the URL for the resource.
461 JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue());
462 if (!loader)
463 return JSValue::encode(jsUndefined());
464 return JSValue::encode(loader->resolve(exec, exec->argument(0), exec->argument(1), exec->argument(2)));
465}
466
467EncodedJSValue JSC_HOST_CALL moduleLoaderResolveSync(ExecState* exec)
468{
469 VM& vm = exec->vm();
470 auto scope = DECLARE_THROW_SCOPE(vm);
471
472 JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue());
473 if (!loader)
474 return JSValue::encode(jsUndefined());
475 auto result = loader->resolveSync(exec, exec->argument(0), exec->argument(1), exec->argument(2));
476 RETURN_IF_EXCEPTION(scope, encodedJSValue());
477 return JSValue::encode(identifierToJSValue(vm, result));
478}
479
480EncodedJSValue JSC_HOST_CALL moduleLoaderFetch(ExecState* exec)
481{
482 VM& vm = exec->vm();
483 // Hook point, Loader.fetch
484 // https://whatwg.github.io/loader/#browser-fetch
485 // Take the key and fetch the resource actually.
486 // For example, JavaScriptCore shell can provide the hook fetching the resource
487 // from the local file system.
488 JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue());
489 if (!loader)
490 return JSValue::encode(jsUndefined());
491 return JSValue::encode(loader->fetch(exec, exec->argument(0), exec->argument(1), exec->argument(2)));
492}
493
494EncodedJSValue JSC_HOST_CALL moduleLoaderGetModuleNamespaceObject(ExecState* exec)
495{
496 VM& vm = exec->vm();
497 auto scope = DECLARE_THROW_SCOPE(vm);
498
499 auto* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue());
500 if (!loader)
501 return JSValue::encode(jsUndefined());
502 auto* moduleNamespaceObject = loader->getModuleNamespaceObject(exec, exec->argument(0));
503 RETURN_IF_EXCEPTION(scope, encodedJSValue());
504 return JSValue::encode(moduleNamespaceObject);
505}
506
507// ------------------- Additional Hook Functions ---------------------------
508
509EncodedJSValue JSC_HOST_CALL moduleLoaderEvaluate(ExecState* exec)
510{
511 // To instrument and retrieve the errors raised from the module execution,
512 // we inserted the hook point here.
513
514 VM& vm = exec->vm();
515 JSModuleLoader* loader = jsDynamicCast<JSModuleLoader*>(vm, exec->thisValue());
516 if (!loader)
517 return JSValue::encode(jsUndefined());
518 return JSValue::encode(loader->evaluate(exec, exec->argument(0), exec->argument(1), exec->argument(2)));
519}
520
521} // namespace JSC
522