1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 21:07:34 +00:00

LibJS+LibWeb: Another round of bringing module loading closer to spec

In particular, this patch focuses on:
- Updating the old "import assertions" to the new "import attributes"
- Allowing realms as module import referrer
This commit is contained in:
Andreas Kling 2023-12-02 16:20:01 +01:00
parent 82977ab44b
commit 07f567cd9f
14 changed files with 244 additions and 178 deletions

View file

@ -11,6 +11,7 @@
#include <AK/Optional.h>
#include <AK/Utf16View.h>
#include <LibJS/Bytecode/Interpreter.h>
#include <LibJS/ModuleLoading.h>
#include <LibJS/Parser.h>
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/Accessor.h>
@ -1459,25 +1460,53 @@ Completion dispose_resources(VM& vm, GCPtr<DeclarativeEnvironment> disposable, C
return completion;
}
// https://tc39.es/proposal-import-attributes/#sec-AllImportAttributesSupported
static bool all_import_attributes_supported(VM& vm, Vector<ImportAttribute> const& attributes)
{
// 1. Let supported be HostGetSupportedImportAttributes().
auto supported = vm.host_get_supported_import_attributes();
// 2. For each ImportAttribute Record attribute of attributes, do
for (auto const& attribute : attributes) {
// a. If supported does not contain attribute.[[Key]], return false.
if (!supported.contains_slow(attribute.key))
return false;
}
// 3. Return true.
return true;
}
ThrowCompletionOr<Value> perform_import_call(VM& vm, Value specifier, Value options_value)
{
auto& realm = *vm.current_realm();
// 2.1.1.1 EvaluateImportCall ( specifierExpression [ , optionsExpression ] ), https://tc39.es/proposal-import-assertions/#sec-evaluate-import-call
// 1. Let referencingScriptOrModule be GetActiveScriptOrModule().
auto referencing_script_or_module = vm.get_active_script_or_module();
// 13.3.10.2 EvaluateImportCall ( specifierExpression [ , optionsExpression ] ), https://tc39.es/proposal-import-attributes/#sec-evaluate-import-call
// 1. Let referrer be GetActiveScriptOrModule().
auto referrer = [&]() -> ImportedModuleReferrer {
auto active_script_or_module = vm.get_active_script_or_module();
// 6. Let promiseCapability be ! NewPromiseCapability(%Promise%).
// 2. If referrer is null, set referrer to the current Realm Record.
if (active_script_or_module.has<Empty>())
return NonnullGCPtr<Realm> { realm };
if (active_script_or_module.has<NonnullGCPtr<Script>>())
return active_script_or_module.get<NonnullGCPtr<Script>>();
return NonnullGCPtr<CyclicModule> { verify_cast<CyclicModule>(*active_script_or_module.get<NonnullGCPtr<Module>>()) };
}();
// 7. Let promiseCapability be ! NewPromiseCapability(%Promise%).
auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor()));
// 7. Let specifierString be Completion(ToString(specifier)).
// 8. IfAbruptRejectPromise(specifierString, promiseCapability).
// 8. Let specifierString be Completion(ToString(specifier)).
// 9. IfAbruptRejectPromise(specifierString, promiseCapability).
auto specifier_string = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, specifier.to_deprecated_string(vm));
// 9. Let assertions be a new empty List.
Vector<ModuleRequest::Assertion> assertions;
// 10. Let attributes be a new empty List.
Vector<ImportAttribute> attributes;
// 10. If options is not undefined, then
// 11. If options is not undefined, then
if (!options_value.is_undefined()) {
// a. If Type(options) is not Object,
if (!options_value.is_object()) {
@ -1489,14 +1518,22 @@ ThrowCompletionOr<Value> perform_import_call(VM& vm, Value specifier, Value opti
return Value { promise_capability->promise() };
}
// b. Let assertionsObj be Get(options, "assert").
// c. IfAbruptRejectPromise(assertionsObj, promiseCapability).
auto assertion_object = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, options_value.get(vm, vm.names.assert));
// b. Let attributesObj be Completion(Get(options, "with")).
// c. IfAbruptRejectPromise(attributesObj, promiseCapability).
auto attributes_obj = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, options_value.get(vm, vm.names.with));
// d. If assertionsObj is not undefined,
if (!assertion_object.is_undefined()) {
// i. If Type(assertionsObj) is not Object,
if (!assertion_object.is_object()) {
// d. Normative Optional, Deprecated
// 11. If the host supports the deprecated assert keyword for import attributes and attributesObj is undefined, then
if (attributes_obj.is_undefined()) {
// i. Set attributesObj to Completion(Get(options, "assert")).
// ii. IfAbruptRejectPromise(attributesObj, promiseCapability).
attributes_obj = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, options_value.get(vm, vm.names.assert));
}
// e. If attributesObj is not undefined,
if (!attributes_obj.is_undefined()) {
// i. If Type(attributesObj) is not Object,
if (!attributes_obj.is_object()) {
auto error = TypeError::create(realm, TRY_OR_THROW_OOM(vm, String::formatted(ErrorType::NotAnObject.message(), "ImportOptionsAssertions")));
// 1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
MUST(call(vm, *promise_capability->reject(), js_undefined(), error));
@ -1505,20 +1542,17 @@ ThrowCompletionOr<Value> perform_import_call(VM& vm, Value specifier, Value opti
return Value { promise_capability->promise() };
}
// ii. Let keys be EnumerableOwnPropertyNames(assertionsObj, key).
// iii. IfAbruptRejectPromise(keys, promiseCapability).
auto keys = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, assertion_object.as_object().enumerable_own_property_names(Object::PropertyKind::Key));
// ii. Let entries be Completion(EnumerableOwnProperties(attributesObj, key+value)).
// iii. IfAbruptRejectPromise(entries, promiseCapability).
auto entries = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, attributes_obj.as_object().enumerable_own_property_names(Object::PropertyKind::KeyAndValue));
// iv. Let supportedAssertions be ! HostGetSupportedImportAssertions().
auto supported_assertions = vm.host_get_supported_import_assertions();
// iv. For each entry of entries, do
for (auto const& entry : entries) {
// 1. Let key be ! Get(entry, "0").
auto key = MUST(entry.get(vm, PropertyKey(0)));
// v. For each String key of keys,
for (auto const& key : keys) {
auto property_key = MUST(key.to_property_key(vm));
// 1. Let value be Get(assertionsObj, key).
// 2. IfAbruptRejectPromise(value, promiseCapability).
auto value = TRY_OR_REJECT_WITH_VALUE(vm, promise_capability, assertion_object.get(vm, property_key));
// 2. Let value be ! Get(entry, "1").
auto value = MUST(entry.get(vm, PropertyKey(1)));
// 3. If Type(value) is not String, then
if (!value.is_string()) {
@ -1530,22 +1564,33 @@ ThrowCompletionOr<Value> perform_import_call(VM& vm, Value specifier, Value opti
return Value { promise_capability->promise() };
}
// 4. If supportedAssertions contains key, then
if (supported_assertions.contains_slow(property_key.to_string())) {
// a. Append { [[Key]]: key, [[Value]]: value } to assertions.
assertions.empend(property_key.to_string(), value.as_string().deprecated_string());
}
// 4. Append the ImportAttribute Record { [[Key]]: key, [[Value]]: value } to attributes.
attributes.empend(key.as_string().deprecated_string(), value.as_string().deprecated_string());
}
}
// e. Sort assertions by the code point order of the [[Key]] of each element. NOTE: This sorting is observable only in that hosts are prohibited from distinguishing among assertions by the order they occur in.
// Note: This is done when constructing the ModuleRequest.
// f. If AllImportAttributesSupported(attributes) is false, then
if (!all_import_attributes_supported(vm, attributes)) {
auto error = TypeError::create(realm, TRY_OR_THROW_OOM(vm, String::formatted(ErrorType::NotAnObject.message(), "ImportOptionsAssertions")));
// i. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
MUST(call(vm, *promise_capability->reject(), js_undefined(), error));
// ii. Return promiseCapability.[[Promise]].
return Value { promise_capability->promise() };
}
// g. Sort attributes according to the lexicographic order of their [[Key]] fields,
// treating the value of each such field as a sequence of UTF-16 code unit values.
// NOTE: This sorting is observable only in that hosts are prohibited from
// distinguishing among attributes by the order they occur in.
// NOTE: This is done when constructing the ModuleRequest.
}
// 11. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]: specifierString, [[Assertions]]: assertions }.
ModuleRequest request { specifier_string, assertions };
// 12. Let moduleRequest be a new ModuleRequest Record { [[Specifier]]: specifierString, [[Attributes]]: attributes }.
ModuleRequest request { specifier_string, attributes };
// 12. Perform HostImportModuleDynamically(referencingScriptOrModule, moduleRequest, promiseCapability).
MUST_OR_THROW_OOM(vm.host_import_module_dynamically(referencing_script_or_module, move(request), promise_capability));
// 13. Perform HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability).
MUST_OR_THROW_OOM(vm.host_import_module_dynamically(referrer, move(request), promise_capability));
// 13. Return promiseCapability.[[Promise]].
return Value { promise_capability->promise() };

View file

@ -18,13 +18,14 @@ struct ModuleWithSpecifier {
NonnullGCPtr<Module> module; // [[Module]]
};
// 2.9 ModuleRequest Records, https://tc39.es/proposal-import-assertions/#sec-modulerequest-record
struct ModuleRequest {
struct Assertion {
DeprecatedString key;
DeprecatedString value;
};
// https://tc39.es/proposal-import-attributes/#importattribute-record
struct ImportAttribute {
DeprecatedString key;
DeprecatedString value;
};
// https://tc39.es/proposal-import-attributes/#modulerequest-record
struct ModuleRequest {
ModuleRequest() = default;
explicit ModuleRequest(DeprecatedFlyString specifier)
@ -32,15 +33,15 @@ struct ModuleRequest {
{
}
ModuleRequest(DeprecatedFlyString module_specifier, Vector<Assertion> assertions);
ModuleRequest(DeprecatedFlyString specifier, Vector<ImportAttribute> attributes);
void add_assertion(DeprecatedString key, DeprecatedString value)
void add_attribute(DeprecatedString key, DeprecatedString value)
{
assertions.empend(move(key), move(value));
attributes.empend(move(key), move(value));
}
DeprecatedFlyString module_specifier; // [[Specifier]]
Vector<Assertion> assertions; // [[Assertions]]
Vector<ImportAttribute> attributes; // [[Attributes]]
};
}

View file

@ -233,8 +233,9 @@ ThrowCompletionOr<Value> shadow_realm_import_value(VM& vm, DeprecatedString spec
// 5. Push evalContext onto the execution context stack; evalContext is now the running execution context.
TRY(vm.push_execution_context(eval_context, {}));
// 6. Perform HostImportModuleDynamically(null, specifierString, innerCapability).
MUST_OR_THROW_OOM(vm.host_import_module_dynamically(Empty {}, ModuleRequest { move(specifier_string) }, inner_capability));
// 6. Let referrer be the Realm component of evalContext.
// 7. Perform HostImportModuleDynamically(referrer, specifierString, innerCapability).
MUST_OR_THROW_OOM(vm.host_import_module_dynamically(NonnullGCPtr { *eval_context.realm }, ModuleRequest { move(specifier_string) }, inner_capability));
// 7. Suspend evalContext and remove it from the execution context stack.
// NOTE: We don't support this concept yet.

View file

@ -94,11 +94,11 @@ VM::VM(OwnPtr<CustomData> custom_data, ErrorMessages error_messages)
return make_job_callback(function_object);
};
host_resolve_imported_module = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier) {
return resolve_imported_module(move(referencing_script_or_module), specifier);
host_resolve_imported_module = [&](ImportedModuleReferrer referrer, ModuleRequest const& specifier) {
return resolve_imported_module(referrer, specifier);
};
host_import_module_dynamically = [&](ScriptOrModule, ModuleRequest const&, PromiseCapability const& promise_capability) -> ThrowCompletionOr<void> {
host_import_module_dynamically = [&](ImportedModuleReferrer, ModuleRequest const&, PromiseCapability const& promise_capability) -> ThrowCompletionOr<void> {
// By default, we throw on dynamic imports this is to prevent arbitrary file access by scripts.
VERIFY(current_realm());
auto& realm = *current_realm();
@ -127,8 +127,8 @@ VM::VM(OwnPtr<CustomData> custom_data, ErrorMessages error_messages)
return {};
};
host_finish_dynamic_import = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability const& promise_capability, Promise* promise) {
return finish_dynamic_import(move(referencing_script_or_module), specifier, promise_capability, promise);
host_finish_dynamic_import = [&](ImportedModuleReferrer referrer, ModuleRequest const& specifier, PromiseCapability const& promise_capability, Promise* promise) {
return finish_dynamic_import(referrer, specifier, promise_capability, promise);
};
host_get_import_meta_properties = [&](SourceTextModule const&) -> HashMap<PropertyKey, Value> {
@ -138,7 +138,7 @@ VM::VM(OwnPtr<CustomData> custom_data, ErrorMessages error_messages)
host_finalize_import_meta = [&](Object*, SourceTextModule const&) {
};
host_get_supported_import_assertions = [&] {
host_get_supported_import_attributes = [&] {
return Vector<DeprecatedString> { "type" };
};
@ -183,8 +183,8 @@ String const& VM::error_message(ErrorMessage type) const
void VM::enable_default_host_import_module_dynamically_hook()
{
host_import_module_dynamically = [&](ScriptOrModule referencing_script_or_module, ModuleRequest const& specifier, PromiseCapability const& promise_capability) {
return import_module_dynamically(move(referencing_script_or_module), specifier, promise_capability);
host_import_module_dynamically = [&](ImportedModuleReferrer referrer, ModuleRequest const& specifier, PromiseCapability const& promise_capability) {
return import_module_dynamically(referrer, specifier, promise_capability);
};
}
@ -760,7 +760,7 @@ ScriptOrModule VM::get_active_script_or_module() const
return m_execution_context_stack[0]->script_or_module;
}
VM::StoredModule* VM::get_stored_module(ScriptOrModule const&, DeprecatedString const& filename, DeprecatedString const&)
VM::StoredModule* VM::get_stored_module(ImportedModuleReferrer const&, DeprecatedString const& filename, DeprecatedString const&)
{
// Note the spec says:
// Each time this operation is called with a specific referencingScriptOrModule, specifier pair as arguments
@ -801,7 +801,7 @@ ThrowCompletionOr<void> VM::link_and_eval_module(Module& module)
dbgln("Warning: Using multiple modules as entry point can lead to unexpected results");
m_loaded_modules.empend(
NonnullGCPtr(module),
ImportedModuleReferrer { NonnullGCPtr { verify_cast<CyclicModule>(module) } },
module.filename(),
DeprecatedString {}, // Null type
module,
@ -866,7 +866,7 @@ static DeprecatedString resolve_module_filename(StringView filename, StringView
}
// 16.2.1.7 HostResolveImportedModule ( referencingScriptOrModule, specifier ), https://tc39.es/ecma262/#sec-hostresolveimportedmodule
ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ScriptOrModule referencing_script_or_module, ModuleRequest const& module_request)
ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ImportedModuleReferrer referrer, ModuleRequest const& module_request)
{
// An implementation of HostResolveImportedModule must conform to the following requirements:
// - If it completes normally, the [[Value]] slot of the completion must contain an instance of a concrete subclass of Module Record.
@ -882,18 +882,25 @@ ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ScriptOrModu
// The actual mapping semantic is host-defined but typically a normalization process is applied to specifier as part of the mapping process.
// A typical normalization process would include actions such as alphabetic case folding and expansion of relative and abbreviated path specifiers.
// We only allow "type" as a supported assertion so it is the only valid key that should ever arrive here.
VERIFY(module_request.assertions.is_empty() || (module_request.assertions.size() == 1 && module_request.assertions.first().key == "type"));
auto module_type = module_request.assertions.is_empty() ? DeprecatedString {} : module_request.assertions.first().value;
DeprecatedString module_type;
for (auto& attribute : module_request.attributes) {
if (attribute.key == "type"sv) {
module_type = attribute.value;
break;
}
}
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] module at {} has type {}", module_request.module_specifier, module_type);
StringView base_filename = referencing_script_or_module.visit(
[&](Empty) {
StringView const base_filename = referrer.visit(
[&](NonnullGCPtr<Realm> const&) {
return "."sv;
},
[&](auto& script_or_module) {
return script_or_module->filename();
[&](NonnullGCPtr<Script> const& script) {
return script->filename();
},
[&](NonnullGCPtr<Module> const& module) {
return module->filename();
});
LexicalPath base_path { base_filename };
@ -907,7 +914,7 @@ ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ScriptOrModu
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolved filename: '{}'", filename);
#if JS_MODULE_DEBUG
DeprecatedString referencing_module_string = referencing_script_or_module.visit(
DeprecatedString referencing_module_string = referrer.visit(
[&](Empty) -> DeprecatedString {
return ".";
},
@ -922,7 +929,7 @@ ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ScriptOrModu
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolved {} + {} -> {}", base_path, module_request.module_specifier, filename);
#endif
auto* loaded_module_or_end = get_stored_module(referencing_script_or_module, filename, module_type);
auto* loaded_module_or_end = get_stored_module(referrer, filename, module_type);
if (loaded_module_or_end != nullptr) {
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolve_imported_module({}) already loaded at {}", filename, loaded_module_or_end->module.ptr());
return NonnullGCPtr(*loaded_module_or_end->module);
@ -970,7 +977,7 @@ ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ScriptOrModu
// We have to set it here already in case it references itself.
m_loaded_modules.empend(
referencing_script_or_module,
referrer,
filename,
module_type,
*module,
@ -980,7 +987,7 @@ ThrowCompletionOr<NonnullGCPtr<Module>> VM::resolve_imported_module(ScriptOrModu
}
// 16.2.1.8 HostImportModuleDynamically ( referencingScriptOrModule, specifier, promiseCapability ), https://tc39.es/ecma262/#sec-hostimportmoduledynamically
ThrowCompletionOr<void> VM::import_module_dynamically(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability)
ThrowCompletionOr<void> VM::import_module_dynamically(ImportedModuleReferrer referrer, ModuleRequest module_request, PromiseCapability const& promise_capability)
{
auto& realm = *current_realm();
@ -999,24 +1006,11 @@ ThrowCompletionOr<void> VM::import_module_dynamically(ScriptOrModule referencing
auto promise = Promise::create(realm);
ScopeGuard finish_dynamic_import = [&] {
host_finish_dynamic_import(referencing_script_or_module, module_request, promise_capability, promise);
host_finish_dynamic_import(referrer, module_request, promise_capability, promise);
};
// Generally within ECMA262 we always get a referencing_script_or_module. However, ShadowRealm gives an explicit null.
// To get around this is we attempt to get the active script_or_module otherwise we might start loading "random" files from the working directory.
if (referencing_script_or_module.has<Empty>()) {
referencing_script_or_module = get_active_script_or_module();
// If there is no ScriptOrModule in any of the execution contexts
if (referencing_script_or_module.has<Empty>()) {
// Throw an error for now
promise->reject(InternalError::create(realm, TRY_OR_THROW_OOM(*this, String::formatted(ErrorType::ModuleNotFoundNoReferencingScript.message(), module_request.module_specifier))));
return {};
}
}
// Note: If host_resolve_imported_module returns a module it has been loaded successfully and the next call in finish_dynamic_import will retrieve it again.
auto module_or_error = host_resolve_imported_module(referencing_script_or_module, module_request);
auto module_or_error = host_resolve_imported_module(referrer, module_request);
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] HostImportModuleDynamically(..., {}) -> {}", module_request.module_specifier, module_or_error.is_error() ? "failed" : "passed");
if (module_or_error.is_throw_completion()) {
promise->reject(*module_or_error.throw_completion().value());
@ -1039,19 +1033,19 @@ ThrowCompletionOr<void> VM::import_module_dynamically(ScriptOrModule referencing
}
// 16.2.1.9 FinishDynamicImport ( referencingScriptOrModule, specifier, promiseCapability, innerPromise ), https://tc39.es/ecma262/#sec-finishdynamicimport
void VM::finish_dynamic_import(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability, Promise* inner_promise)
void VM::finish_dynamic_import(ImportedModuleReferrer referrer, ModuleRequest module_request, PromiseCapability const& promise_capability, Promise* inner_promise)
{
dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] finish_dynamic_import on {}", module_request.module_specifier);
auto& realm = *current_realm();
// 1. Let fulfilledClosure be a new Abstract Closure with parameters (result) that captures referencingScriptOrModule, specifier, and promiseCapability and performs the following steps when called:
auto fulfilled_closure = [referencing_script_or_module = move(referencing_script_or_module), module_request = move(module_request), &promise_capability](VM& vm) -> ThrowCompletionOr<Value> {
auto fulfilled_closure = [referrer = move(referrer), module_request = move(module_request), &promise_capability](VM& vm) -> ThrowCompletionOr<Value> {
auto result = vm.argument(0);
// a. Assert: result is undefined.
VERIFY(result.is_undefined());
// b. Let moduleRecord be ! HostResolveImportedModule(referencingScriptOrModule, specifier).
auto module_record = MUST(vm.host_resolve_imported_module(referencing_script_or_module, module_request));
auto module_record = MUST(vm.host_resolve_imported_module(referrer, module_request));
// c. Assert: Evaluate has already been invoked on moduleRecord and successfully completed.
// Note: If HostResolveImportedModule returns a module evaluate will have been called on it.

View file

@ -18,6 +18,7 @@
#include <LibJS/CyclicModule.h>
#include <LibJS/Heap/Heap.h>
#include <LibJS/Heap/MarkedVector.h>
#include <LibJS/ModuleLoading.h>
#include <LibJS/Runtime/CommonPropertyNames.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/Error.h>
@ -230,14 +231,14 @@ public:
// 16.2.1.8 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload ), https://tc39.es/proposal-import-attributes/#sec-HostLoadImportedModule
Function<void(Realm&, Variant<NonnullGCPtr<Script>, NonnullGCPtr<CyclicModule>>, ModuleRequest const&, GCPtr<GraphLoadingState::HostDefined>, GraphLoadingState&)> host_load_imported_module;
Function<ThrowCompletionOr<NonnullGCPtr<Module>>(ScriptOrModule, ModuleRequest const&)> host_resolve_imported_module;
Function<ThrowCompletionOr<void>(ScriptOrModule, ModuleRequest, PromiseCapability const&)> host_import_module_dynamically;
Function<void(ScriptOrModule, ModuleRequest const&, PromiseCapability const&, Promise*)> host_finish_dynamic_import;
Function<ThrowCompletionOr<NonnullGCPtr<Module>>(ImportedModuleReferrer, ModuleRequest const&)> host_resolve_imported_module;
Function<ThrowCompletionOr<void>(ImportedModuleReferrer, ModuleRequest, PromiseCapability const&)> host_import_module_dynamically;
Function<void(ImportedModuleReferrer, ModuleRequest const&, PromiseCapability const&, Promise*)> host_finish_dynamic_import;
Function<HashMap<PropertyKey, Value>(SourceTextModule&)> host_get_import_meta_properties;
Function<void(Object*, SourceTextModule const&)> host_finalize_import_meta;
Function<Vector<DeprecatedString>()> host_get_supported_import_assertions;
Function<Vector<DeprecatedString>()> host_get_supported_import_attributes;
void enable_default_host_import_module_dynamically_hook();
@ -270,11 +271,11 @@ private:
ThrowCompletionOr<void> property_binding_initialization(BindingPattern const& binding, Value value, Environment* environment);
ThrowCompletionOr<void> iterator_binding_initialization(BindingPattern const& binding, IteratorRecord& iterator_record, Environment* environment);
ThrowCompletionOr<NonnullGCPtr<Module>> resolve_imported_module(ScriptOrModule referencing_script_or_module, ModuleRequest const& module_request);
ThrowCompletionOr<NonnullGCPtr<Module>> resolve_imported_module(ImportedModuleReferrer, ModuleRequest const& module_request);
ThrowCompletionOr<void> link_and_eval_module(Module& module);
ThrowCompletionOr<void> import_module_dynamically(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability);
void finish_dynamic_import(ScriptOrModule referencing_script_or_module, ModuleRequest module_request, PromiseCapability const& promise_capability, Promise* inner_promise);
ThrowCompletionOr<void> import_module_dynamically(ImportedModuleReferrer, ModuleRequest module_request, PromiseCapability const& promise_capability);
void finish_dynamic_import(ImportedModuleReferrer, ModuleRequest module_request, PromiseCapability const& promise_capability, Promise* inner_promise);
void set_well_known_symbols(WellKnownSymbols well_known_symbols) { m_well_known_symbols = move(well_known_symbols); }
@ -303,14 +304,14 @@ private:
ErrorMessages m_error_messages;
struct StoredModule {
ScriptOrModule referencing_script_or_module;
ImportedModuleReferrer referrer;
DeprecatedString filename;
DeprecatedString type;
Handle<Module> module;
bool has_once_started_linking { false };
};
StoredModule* get_stored_module(ScriptOrModule const& script_or_module, DeprecatedString const& filename, DeprecatedString const& type);
StoredModule* get_stored_module(ImportedModuleReferrer const& script_or_module, DeprecatedString const& filename, DeprecatedString const& type);
Vector<StoredModule> m_loaded_modules;