diff --git a/Libraries/LibJS/Runtime/JSONObject.cpp b/Libraries/LibJS/Runtime/JSONObject.cpp index be036bc7041..4c7205bfb08 100644 --- a/Libraries/LibJS/Runtime/JSONObject.cpp +++ b/Libraries/LibJS/Runtime/JSONObject.cpp @@ -419,22 +419,57 @@ JS_DEFINE_NATIVE_FUNCTION(JSONObject::parse) { auto& realm = *vm.current_realm(); - auto string = TRY(vm.argument(0).to_string(vm)); + auto text = vm.argument(0); auto reviver = vm.argument(1); - auto json = JsonValue::from_string(string); - if (json.is_error()) - return vm.throw_completion(ErrorType::JsonMalformed); - Value unfiltered = parse_json_value(vm, json.value()); + // 1. Let jsonString be ? ToString(text). + auto json_string = TRY(text.to_string(vm)); + + // 2. Let unfiltered be ? ParseJSON(jsonString). + auto unfiltered = TRY(parse_json(vm, json_string)); + + // 3. If IsCallable(reviver) is true, then if (reviver.is_function()) { + // a. Let root be OrdinaryObjectCreate(%Object.prototype%). auto root = Object::create(realm, realm.intrinsics().object_prototype()); - auto root_name = String {}; + + // b. Let rootName be the empty String. + String root_name; + + // c. Perform ! CreateDataPropertyOrThrow(root, rootName, unfiltered). MUST(root->create_data_property_or_throw(root_name, unfiltered)); + + // d. Return ? InternalizeJSONProperty(root, rootName, reviver). return internalize_json_property(vm, root, root_name, reviver.as_function()); } + // 4. Else, + // a. Return unfiltered. return unfiltered; } +// 25.5.1.1 ParseJSON ( text ), https://tc39.es/ecma262/#sec-ParseJSON +ThrowCompletionOr JSONObject::parse_json(VM& vm, StringView text) +{ + auto json = JsonValue::from_string(text); + + // 1. If StringToCodePoints(text) is not a valid JSON text as specified in ECMA-404, throw a SyntaxError exception. + if (json.is_error()) + return vm.throw_completion(ErrorType::JsonMalformed); + + // 2. Let scriptString be the string-concatenation of "(", text, and ");". + // 3. Let script be ParseText(scriptString, Script). + // 4. NOTE: The early error rules defined in 13.2.5.1 have special handling for the above invocation of ParseText. + // 5. Assert: script is a Parse Node. + // 6. Let result be ! Evaluation of script. + auto result = JSONObject::parse_json_value(vm, json.value()); + + // 7. NOTE: The PropertyDefinitionEvaluation semantics defined in 13.2.5.5 have special handling for the above evaluation. + // 8. Assert: result is either a String, a Number, a Boolean, an Object that is defined by either an ArrayLiteral or an ObjectLiteral, or null. + + // 9. Return result. + return result; +} + Value JSONObject::parse_json_value(VM& vm, JsonValue const& value) { if (value.is_object()) @@ -448,7 +483,7 @@ Value JSONObject::parse_json_value(VM& vm, JsonValue const& value) if (value.is_string()) return PrimitiveString::create(vm, value.as_string()); if (value.is_bool()) - return Value(static_cast(value.as_bool())); + return Value(value.as_bool()); VERIFY_NOT_REACHED(); } diff --git a/Libraries/LibJS/Runtime/JSONObject.h b/Libraries/LibJS/Runtime/JSONObject.h index 03a1c8cccf3..d390fbdfa30 100644 --- a/Libraries/LibJS/Runtime/JSONObject.h +++ b/Libraries/LibJS/Runtime/JSONObject.h @@ -22,6 +22,7 @@ public: // test-js to communicate between the JS tests and the C++ test runner. static ThrowCompletionOr> stringify_impl(VM&, Value value, Value replacer, Value space); + static ThrowCompletionOr parse_json(VM&, StringView text); static Value parse_json_value(VM&, JsonValue const&); private: diff --git a/Libraries/LibJS/Runtime/VM.cpp b/Libraries/LibJS/Runtime/VM.cpp index a7c462ede47..c6ff8bcbf30 100644 --- a/Libraries/LibJS/Runtime/VM.cpp +++ b/Libraries/LibJS/Runtime/VM.cpp @@ -525,10 +525,9 @@ VM::StoredModule* VM::get_stored_module(ImportedModuleReferrer const&, ByteStrin // FinishLoadingImportedModule(referrer, specifier, payload, result) where result is a normal completion, // then it must perform FinishLoadingImportedModule(referrer, specifier, payload, result) with the same result each time. - // Editor's Note from https://tc39.es/proposal-json-modules/#sec-hostresolveimportedmodule - // The above text implies that is recommended but not required that hosts do not use moduleRequest.[[Assertions]] - // as part of the module cache key. In either case, an exception thrown from an import with a given assertion list - // does not rule out success of another import with the same specifier but a different assertion list. + // Editor's Note from https://tc39.es/ecma262/#sec-hostresolveimportedmodule + // The above text requires that hosts support JSON modules when imported with type: "json" (and HostLoadImportedModule + // completes normally), but it does not prohibit hosts from supporting JSON modules when imported without type: "json". // FIXME: This should probably check referrer as well. auto end_or_module = m_loaded_modules.find_if([&](StoredModule const& stored_module) { @@ -612,6 +611,9 @@ void VM::load_imported_module(ImportedModuleReferrer referrer, ModuleRequest con // - If this operation is called multiple times with the same (referrer, specifier) pair and it performs // FinishLoadingImportedModule(referrer, specifier, payload, result) where result is a normal completion, // then it must perform FinishLoadingImportedModule(referrer, specifier, payload, result) with the same result each time. + // - If moduleRequest.[[Attributes]] has an entry entry such that entry.[[Key]] is "type" and entry.[[Value]] is "json", + // when the host environment performs FinishLoadingImportedModule(referrer, moduleRequest, payload, result), result + // must either be the Completion Record returned by an invocation of ParseJSONModule or a throw completion. // - The operation must treat payload as an opaque value to be passed through to FinishLoadingImportedModule. // // The actual process performed is host-defined, but typically consists of performing whatever I/O operations are necessary to @@ -680,10 +682,9 @@ void VM::load_imported_module(ImportedModuleReferrer referrer, ModuleRequest con dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] resolved {} + {} -> {}", base_path, module_request.module_specifier, filename); #endif - 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] load_imported_module({}) already loaded at {}", filename, loaded_module_or_end->module.ptr()); - finish_loading_imported_module(referrer, module_request, payload, *loaded_module_or_end->module); + if (auto* loaded_module = get_stored_module(referrer, filename, module_type)) { + dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] load_imported_module({}) already loaded at {}", filename, loaded_module->module.ptr()); + finish_loading_imported_module(referrer, module_request, payload, *loaded_module->module); return; } @@ -710,12 +711,13 @@ void VM::load_imported_module(ImportedModuleReferrer referrer, ModuleRequest con StringView const content_view { file_content_or_error.value().bytes() }; - auto module = [&]() -> ThrowCompletionOr> { - // If assertions has an entry entry such that entry.[[Key]] is "type", let type be entry.[[Value]]. The following requirements apply: - // If type is "json", then this algorithm must either invoke ParseJSONModule and return the resulting Completion Record, or throw an exception. + auto module = [&, content = file_content_or_error.release_value()]() -> ThrowCompletionOr> { + // If moduleRequest.[[Attributes]] has an entry entry such that entry.[[Key]] is "type" and entry.[[Value]] is "json", + // when the host environment performs FinishLoadingImportedModule(referrer, moduleRequest, payload, result), result + // must either be the Completion Record returned by an invocation of ParseJSONModule or a throw completion. if (module_type == "json"sv) { dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] reading and parsing JSON module {}", filename); - return parse_json_module(content_view, *current_realm(), filename); + return parse_json_module(*current_realm(), content_view, filename); } dbgln_if(JS_MODULE_DEBUG, "[JS MODULE] reading and parsing as SourceTextModule module {}", filename); @@ -727,16 +729,17 @@ void VM::load_imported_module(ImportedModuleReferrer referrer, ModuleRequest con return throw_completion(module_or_errors.error().first().to_byte_string()); } - auto module = module_or_errors.release_value(); + return module_or_errors.release_value(); + }(); + + if (!module.is_error()) { m_loaded_modules.empend( referrer, - module->filename(), + module.value()->filename(), String {}, // Null type - make_root(*module), + make_root(module.value()), true); - - return module; - }(); + } finish_loading_imported_module(referrer, module_request, payload, module); } diff --git a/Libraries/LibJS/SyntheticModule.cpp b/Libraries/LibJS/SyntheticModule.cpp index 2763bd424c6..6021257a1ba 100644 --- a/Libraries/LibJS/SyntheticModule.cpp +++ b/Libraries/LibJS/SyntheticModule.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -17,23 +18,94 @@ namespace JS { GC_DEFINE_ALLOCATOR(SyntheticModule); -// 1.2.1 CreateSyntheticModule ( exportNames, evaluationSteps, realm, hostDefined ), https://tc39.es/proposal-json-modules/#sec-createsyntheticmodule -SyntheticModule::SyntheticModule(Vector export_names, SyntheticModule::EvaluationFunction evaluation_steps, Realm& realm, StringView filename) - : Module(realm, filename) +SyntheticModule::SyntheticModule(Realm& realm, Vector export_names, SyntheticModule::EvaluationFunction evaluation_steps, ByteString filename) + : Module(realm, move(filename)) , m_export_names(move(export_names)) - , m_evaluation_steps(move(evaluation_steps)) + , m_evaluation_steps(evaluation_steps) { - // 1. Return Synthetic Module Record { [[Realm]]: realm, [[Environment]]: undefined, [[Namespace]]: undefined, [[HostDefined]]: hostDefined, [[ExportNames]]: exportNames, [[EvaluationSteps]]: evaluationSteps }. } -// 1.2.3.1 GetExportedNames( exportStarSet ), https://tc39.es/proposal-json-modules/#sec-smr-getexportednames +void SyntheticModule::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_evaluation_steps); +} + +// 16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport ), https://tc39.es/ecma262/#sec-create-default-export-synthetic-module +GC::Ref SyntheticModule::create_default_export_synthetic_module(Realm& realm, Value default_export, ByteString filename) +{ + // 1. Let realm be the current Realm Record. + + // 2. Let setDefaultExport be a new Abstract Closure with parameters (module) that captures defaultExport and + // performs the following steps when called: + auto set_default_export = GC::create_function(realm.heap(), [default_export](SyntheticModule& module) -> ThrowCompletionOr { + // a. Perform SetSyntheticModuleExport(module, "default", defaultExport). + TRY(module.set_synthetic_module_export("default"_fly_string, default_export)); + + // b. Return NormalCompletion(UNUSED). + return {}; + }); + + // 2. Return the Synthetic Module Record { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }. + return realm.heap().allocate(realm, Vector { "default"_fly_string }, set_default_export, move(filename)); +} + +// 16.2.1.8.2 ParseJSONModule ( source ), https://tc39.es/ecma262/#sec-create-default-export-synthetic-module +ThrowCompletionOr> parse_json_module(Realm& realm, StringView source_text, ByteString filename) +{ + auto& vm = realm.vm(); + + // 1. Let json be ? ParseJSON(source). + auto json = TRY(JSONObject::parse_json(vm, source_text)); + + // 3. Return CreateDefaultExportSyntheticModule(json). + return SyntheticModule::create_default_export_synthetic_module(realm, json, move(filename)); +} + +// 16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue ), https://tc39.es/ecma262/#sec-setsyntheticmoduleexport +ThrowCompletionOr SyntheticModule::set_synthetic_module_export(FlyString const& export_name, Value export_value) +{ + auto& vm = this->vm(); + + // 1. Assert: module.[[ExportNames]] contains exportName. + VERIFY(m_export_names.contains_slow(export_name)); + + // 2. Let envRec be module.[[Environment]]. + auto environment_record = environment(); + + // 3. Assert: envRec is not EMPTY. + VERIFY(environment_record); + + // 4. Perform envRec.SetMutableBinding(exportName, exportValue, true). + TRY(environment_record->set_mutable_binding(vm, export_name, export_value, true)); + + // 5. Return UNUSED. + return {}; +} + +// 16.2.1.8.4.1 LoadRequestedModules ( ), https://tc39.es/ecma262/#sec-smr-LoadRequestedModules +PromiseCapability& SyntheticModule::load_requested_modules(GC::Ptr) +{ + auto& realm = this->realm(); + auto& vm = realm.vm(); + + // 1. Return ! PromiseResolve(%Promise%, undefined). + auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor())); + (void)MUST(call(vm, *promise_capability->resolve(), js_undefined(), js_undefined())); + + // NOTE: We need to return a PromiseCapability, rather than a Promise, so we flatten PromiseResolve here. + // This is likely a spec bug, see https://matrixlogs.bakkot.com/WHATWG/2023-02-13#L1 + return promise_capability; +} + +// 16.2.1.8.4.2 GetExportedNames ( ), https://tc39.es/ecma262/#sec-smr-getexportednames Vector SyntheticModule::get_exported_names(VM&, HashTable&) { // 1. Return module.[[ExportNames]]. return m_export_names; } -// 1.2.3.2 ResolveExport( exportName, resolveSet ), https://tc39.es/proposal-json-modules/#sec-smr-resolveexport +// 16.2.1.8.4.3 ResolveExport ( exportName ), https://tc39.es/ecma262/#sec-smr-resolveexport ResolvedBinding SyntheticModule::resolve_export(VM&, FlyString const& export_name, Vector) { // 1. If module.[[ExportNames]] does not contain exportName, return null. @@ -44,132 +116,78 @@ ResolvedBinding SyntheticModule::resolve_export(VM&, FlyString const& export_nam return ResolvedBinding { ResolvedBinding::BindingName, this, export_name }; } -// 1.2.3.3 Link ( ), https://tc39.es/proposal-json-modules/#sec-smr-instantiate +// 16.2.1.8.4.4 Link ( ), https://tc39.es/ecma262/#sec-smr-Link ThrowCompletionOr SyntheticModule::link(VM& vm) { - // Note: Has some changes from PR: https://github.com/tc39/proposal-json-modules/pull/13. - // Which includes renaming it from Instantiate ( ) to Link ( ). - // 1. Let realm be module.[[Realm]]. - // 2. Assert: realm is not undefined. - // Note: This must be true because we use a reference. + auto& realm = this->realm(); - // 3. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]). - auto environment = vm.heap().allocate(&realm().global_environment()); + // 2. Let env be NewModuleEnvironment(realm.[[GlobalEnv]]). + auto environment = vm.heap().allocate(&realm.global_environment()); - // 4. Set module.[[Environment]] to env. + // 3. Set module.[[Environment]] to env. set_environment(environment); - // 5. For each exportName in module.[[ExportNames]], - for (auto& export_name : m_export_names) { - // a. Perform ! envRec.CreateMutableBinding(exportName, false). + // 4. For each String exportName of module.[[ExportNames]], do + for (auto const& export_name : m_export_names) { + // a. Perform ! env.CreateMutableBinding(exportName, false). MUST(environment->create_mutable_binding(vm, export_name, false)); - // b. Perform ! envRec.InitializeBinding(exportName, undefined, normal). + // b. Perform ! env.InitializeBinding(exportName, undefined). MUST(environment->initialize_binding(vm, export_name, js_undefined(), Environment::InitializeBindingHint::Normal)); } - // 6. Return unused. + // 5. Return NormalCompletion(unused). return {}; } -// 1.2.3.4 Evaluate ( ), https://tc39.es/proposal-json-modules/#sec-smr-Evaluate +// 16.2.1.8.4.5 Evaluate ( ), https://tc39.es/ecma262/#sec-smr-Evaluate ThrowCompletionOr> SyntheticModule::evaluate(VM& vm) { - // Note: Has some changes from PR: https://github.com/tc39/proposal-json-modules/pull/13. - // 1. Suspend the currently running execution context. - // NOTE: Done by the push on step 8. + auto& realm = this->realm(); - // 2. Let moduleContext be a new ECMAScript code execution context. + // 1. Let moduleContext be a new ECMAScript code execution context. + // 2. Set the Function of moduleContext to null. ExecutionContext* module_context = nullptr; ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(module_context, 0, 0); - // 3. Set the Function of moduleContext to null. - // Note: This is the default value. + // 3. Set the Realm of moduleContext to module.[[Realm]]. + module_context->realm = &realm; - // 4. Set the Realm of moduleContext to module.[[Realm]]. - module_context->realm = &realm(); - - // 5. Set the ScriptOrModule of moduleContext to module. + // 4. Set the ScriptOrModule of moduleContext to module. module_context->script_or_module = GC::Ref(*this); - // 6. Set the VariableEnvironment of moduleContext to module.[[Environment]]. + // 5. Set the VariableEnvironment of moduleContext to module.[[Environment]]. module_context->variable_environment = environment(); - // 7. Set the LexicalEnvironment of moduleContext to module.[[Environment]]. + // 6. Set the LexicalEnvironment of moduleContext to module.[[Environment]]. module_context->lexical_environment = environment(); - // 8. Push moduleContext on to the execution context stack; moduleContext is now the running execution context. + // 7. Suspend the running execution context. + // 8. Push moduleContext onto the execution context stack; moduleContext is now the running execution context. TRY(vm.push_execution_context(*module_context, {})); - // 9. Let result be the result of performing module.[[EvaluationSteps]](module). - auto result = m_evaluation_steps(*this); + // 9. Let steps be module.[[EvaluationSteps]]. + // 10. Let result be Completion(steps(module)). + auto result = m_evaluation_steps->function()(*this); - // 10. Suspend moduleContext and remove it from the execution context stack. + // 11. Suspend moduleContext and remove it from the execution context stack. + // 12. Resume the context that is now on the top of the execution context stack as the running execution context. vm.pop_execution_context(); - // 11. Resume the context that is now on the top of the execution context stack as the running execution context. + // 13. Let pc be ! NewPromiseCapability(%Promise%). + auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor())); - // 12. Return Completion(result). - // Note: Because we expect it to return a promise we convert this here. - auto promise = Promise::create(realm()); - if (result.is_error()) { - promise->reject(result.throw_completion().value()); - } else { - // Note: This value probably isn't visible to JS code? But undefined is fine anyway. - promise->fulfill(js_undefined()); - } + // 14. IfAbruptRejectPromise(result, pc). + if (result.is_error()) + MUST(call(vm, *promise_capability->reject(), JS::js_undefined(), result.release_error().value())); - return promise; -} + // 15. Perform ! Call(pc.[[Resolve]], undefined, « undefined »). + else + MUST(call(vm, *promise_capability->resolve(), js_undefined(), js_undefined())); -// 1.2.2 SetSyntheticModuleExport ( module, exportName, exportValue ), https://tc39.es/proposal-json-modules/#sec-setsyntheticmoduleexport -ThrowCompletionOr SyntheticModule::set_synthetic_module_export(FlyString const& export_name, Value export_value) -{ - auto& vm = this->realm().vm(); - - // Note: Has some changes from PR: https://github.com/tc39/proposal-json-modules/pull/13. - // 1. Return ? module.[[Environment]].SetMutableBinding(name, value, true). - return environment()->set_mutable_binding(vm, export_name, export_value, true); -} - -// 1.3 CreateDefaultExportSyntheticModule ( defaultExport ), https://tc39.es/proposal-json-modules/#sec-create-default-export-synthetic-module -GC::Ref SyntheticModule::create_default_export_synthetic_module(Value default_export, Realm& realm, StringView filename) -{ - // Note: Has some changes from PR: https://github.com/tc39/proposal-json-modules/pull/13. - // 1. Let closure be the a Abstract Closure with parameters (module) that captures defaultExport and performs the following steps when called: - auto closure = [default_export = make_root(default_export)](SyntheticModule& module) -> ThrowCompletionOr { - // a. Return ? module.SetSyntheticExport("default", defaultExport). - return module.set_synthetic_module_export("default"_fly_string, default_export.value()); - }; - - // 2. Return CreateSyntheticModule("default", closure, realm) - return realm.heap().allocate(Vector { "default"_fly_string }, move(closure), realm, filename); -} - -// 1.4 ParseJSONModule ( source ), https://tc39.es/proposal-json-modules/#sec-parse-json-module -ThrowCompletionOr> parse_json_module(StringView source_text, Realm& realm, StringView filename) -{ - auto& vm = realm.vm(); - - // 1. Let jsonParse be realm's intrinsic object named "%JSON.parse%". - auto json_parse = realm.intrinsics().json_parse_function(); - - // 2. Let json be ? Call(jsonParse, undefined, « sourceText »). - auto json = TRY(call(vm, *json_parse, js_undefined(), PrimitiveString::create(realm.vm(), source_text))); - - // 3. Return CreateDefaultExportSyntheticModule(json, realm, hostDefined). - return SyntheticModule::create_default_export_synthetic_module(json, realm, filename); -} - -// 1.2.3.1 LoadRequestedModules ( ), https://tc39.es/proposal-json-modules/#sec-smr-LoadRequestedModules -PromiseCapability& SyntheticModule::load_requested_modules(GC::Ptr) -{ - // 1. Return ! PromiseResolve(%Promise%, undefined). - auto& constructor = *vm().current_realm()->intrinsics().promise_constructor(); - auto promise_capability = MUST(new_promise_capability(vm(), &constructor)); - MUST(call(vm(), *promise_capability->resolve(), js_undefined(), js_undefined())); - return promise_capability; + // 16. Return pc.[[Promise]]. + return static_cast(*promise_capability->promise()); } } diff --git a/Libraries/LibJS/SyntheticModule.h b/Libraries/LibJS/SyntheticModule.h index 1433c703941..64efe6ba7e0 100644 --- a/Libraries/LibJS/SyntheticModule.h +++ b/Libraries/LibJS/SyntheticModule.h @@ -6,35 +6,39 @@ #pragma once +#include +#include #include namespace JS { -// 1.2 Synthetic Module Records, https://tc39.es/proposal-json-modules/#sec-synthetic-module-records +// 16.2.1.8 Synthetic Module Records, https://tc39.es/ecma262/#sec-synthetic-module-records class SyntheticModule final : public Module { GC_CELL(SyntheticModule, Module); GC_DECLARE_ALLOCATOR(SyntheticModule); public: - using EvaluationFunction = Function(SyntheticModule&)>; + using EvaluationFunction = GC::Ref(SyntheticModule&)>>; - static GC::Ref create_default_export_synthetic_module(Value default_export, Realm& realm, StringView filename); + static GC::Ref create_default_export_synthetic_module(Realm& realm, Value default_export, ByteString filename); ThrowCompletionOr set_synthetic_module_export(FlyString const& export_name, Value export_value); - virtual ThrowCompletionOr link(VM& vm) override; - virtual ThrowCompletionOr> evaluate(VM& vm) override; + virtual PromiseCapability& load_requested_modules(GC::Ptr) override; virtual Vector get_exported_names(VM& vm, HashTable& export_star_set) override; virtual ResolvedBinding resolve_export(VM& vm, FlyString const& export_name, Vector resolve_set) override; - virtual PromiseCapability& load_requested_modules(GC::Ptr) override; + virtual ThrowCompletionOr link(VM& vm) override; + virtual ThrowCompletionOr> evaluate(VM& vm) override; private: - SyntheticModule(Vector export_names, EvaluationFunction evaluation_steps, Realm& realm, StringView filename); + SyntheticModule(Realm& realm, Vector export_names, EvaluationFunction evaluation_steps, ByteString filename); + + virtual void visit_edges(Cell::Visitor&) override; Vector m_export_names; // [[ExportNames]] EvaluationFunction m_evaluation_steps; // [[EvaluationSteps]] }; -ThrowCompletionOr> parse_json_module(StringView source_text, Realm& realm, StringView filename); +ThrowCompletionOr> parse_json_module(Realm& realm, StringView source_text, ByteString filename); }