From fbf9cb338728bdae160655a1e1527f5ce0e1871a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 9 Dec 2022 18:48:25 +0100 Subject: [PATCH] WebContent+LibWeb+LibJS: Simplify injection of JS console globals Instead of creating a new global object and proxying everything through it, we now evaluate console inputs inside a `with` environment. This seems to match the behavior of WebKit and Gecko in my basic testing, and removes the ConsoleGlobalObject which has been a source of confusion and invalid downcasts. The globals now live in a class called ConsoleGlobalObjectExtensions (renamed from ConsoleGlobalObject since it's no longer a global object). To make this possible, I had to add a way to override the initial lexical environment when calling JS::Interpreter::run(). This is plumbed via Web::HTML::ClassicScript::run(). --- Userland/Libraries/LibJS/Interpreter.cpp | 6 +- Userland/Libraries/LibJS/Interpreter.h | 2 +- .../LibWeb/HTML/Scripting/ClassicScript.cpp | 4 +- .../LibWeb/HTML/Scripting/ClassicScript.h | 2 +- Userland/Services/WebContent/CMakeLists.txt | 2 +- .../ConsoleGlobalEnvironmentExtensions.cpp | 120 ++++++++++++ .../ConsoleGlobalEnvironmentExtensions.h | 42 ++++ .../WebContent/ConsoleGlobalObject.cpp | 179 ------------------ .../Services/WebContent/ConsoleGlobalObject.h | 54 ------ Userland/Services/WebContent/Forward.h | 2 +- .../WebContent/WebContentConsoleClient.cpp | 62 ++---- .../WebContent/WebContentConsoleClient.h | 4 +- 12 files changed, 187 insertions(+), 292 deletions(-) create mode 100644 Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.cpp create mode 100644 Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.h delete mode 100644 Userland/Services/WebContent/ConsoleGlobalObject.cpp delete mode 100644 Userland/Services/WebContent/ConsoleGlobalObject.h diff --git a/Userland/Libraries/LibJS/Interpreter.cpp b/Userland/Libraries/LibJS/Interpreter.cpp index 20bdc1bc86..2dc3be1e19 100644 --- a/Userland/Libraries/LibJS/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Interpreter.cpp @@ -35,7 +35,7 @@ Interpreter::Interpreter(VM& vm) } // 16.1.6 ScriptEvaluation ( scriptRecord ), https://tc39.es/ecma262/#sec-runtime-semantics-scriptevaluation -ThrowCompletionOr Interpreter::run(Script& script_record) +ThrowCompletionOr Interpreter::run(Script& script_record, JS::GCPtr lexical_environment_override) { auto& vm = this->vm(); @@ -62,6 +62,10 @@ ThrowCompletionOr Interpreter::run(Script& script_record) // 7. Set the LexicalEnvironment of scriptContext to globalEnv. script_context.lexical_environment = &global_environment; + // Non-standard: Override the lexical environment if requested. + if (lexical_environment_override) + script_context.lexical_environment = lexical_environment_override; + // 8. Set the PrivateEnvironment of scriptContext to null. // NOTE: This isn't in the spec, but we require it. diff --git a/Userland/Libraries/LibJS/Interpreter.h b/Userland/Libraries/LibJS/Interpreter.h index e5937c86bc..d84e93ff3b 100644 --- a/Userland/Libraries/LibJS/Interpreter.h +++ b/Userland/Libraries/LibJS/Interpreter.h @@ -66,7 +66,7 @@ public: ~Interpreter() = default; - ThrowCompletionOr run(Script&); + ThrowCompletionOr run(Script&, JS::GCPtr lexical_environment_override = {}); ThrowCompletionOr run(SourceTextModule&); Realm& realm(); diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.cpp b/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.cpp index 2fdc908821..d4dedf47a5 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.cpp +++ b/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.cpp @@ -71,7 +71,7 @@ JS::NonnullGCPtr ClassicScript::create(DeprecatedString filename, } // https://html.spec.whatwg.org/multipage/webappapis.html#run-a-classic-script -JS::Completion ClassicScript::run(RethrowErrors rethrow_errors) +JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, JS::GCPtr lexical_environment_override) { auto& vm = settings_object().realm().vm(); @@ -97,7 +97,7 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors) // 6. Otherwise, set evaluationStatus to ScriptEvaluation(script's record). auto interpreter = JS::Interpreter::create_with_existing_realm(m_script_record->realm()); - evaluation_status = interpreter->run(*m_script_record); + evaluation_status = interpreter->run(*m_script_record, lexical_environment_override); // FIXME: If ScriptEvaluation does not complete because the user agent has aborted the running script, leave evaluationStatus as null. diff --git a/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.h b/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.h index 9f1ef9c2ab..3d602f1d66 100644 --- a/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.h +++ b/Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.h @@ -32,7 +32,7 @@ public: No, Yes, }; - JS::Completion run(RethrowErrors = RethrowErrors::No); + JS::Completion run(RethrowErrors = RethrowErrors::No, JS::GCPtr lexical_environment_override = {}); MutedErrors muted_errors() const { return m_muted_errors; } diff --git a/Userland/Services/WebContent/CMakeLists.txt b/Userland/Services/WebContent/CMakeLists.txt index 3ea9a981eb..c5c0e30247 100644 --- a/Userland/Services/WebContent/CMakeLists.txt +++ b/Userland/Services/WebContent/CMakeLists.txt @@ -12,7 +12,7 @@ compile_ipc(WebDriverServer.ipc WebDriverServerEndpoint.h) set(SOURCES ConnectionFromClient.cpp - ConsoleGlobalObject.cpp + ConsoleGlobalEnvironmentExtensions.cpp ImageCodecPluginSerenity.cpp PageHost.cpp WebContentConsoleClient.cpp diff --git a/Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.cpp b/Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.cpp new file mode 100644 index 0000000000..3377b1a4fe --- /dev/null +++ b/Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "ConsoleGlobalEnvironmentExtensions.h" +#include +#include +#include +#include +#include +#include + +namespace WebContent { + +ConsoleGlobalEnvironmentExtensions::ConsoleGlobalEnvironmentExtensions(JS::Realm& realm, Web::HTML::Window& window) + : Object(realm, nullptr) + , m_window_object(window) +{ +} + +void ConsoleGlobalEnvironmentExtensions::initialize(JS::Realm& realm) +{ + Base::initialize(realm); + + define_native_accessor(realm, "$0", $0_getter, nullptr, 0); + define_native_accessor(realm, "$_", $__getter, nullptr, 0); + define_native_function(realm, "$", $_function, 2, JS::default_attributes); + define_native_function(realm, "$$", $$_function, 2, JS::default_attributes); +} + +void ConsoleGlobalEnvironmentExtensions::visit_edges(Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_window_object); +} + +static JS::ThrowCompletionOr get_console(JS::VM& vm) +{ + auto this_value = vm.this_value(); + if (!this_value.is_object() || !is(this_value.as_object())) + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "ConsoleGlobalEnvironmentExtensions"); + + return &static_cast(this_value.as_object()); +} + +JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalEnvironmentExtensions::$0_getter) +{ + auto* console_global_object = TRY(get_console(vm)); + auto& window = *console_global_object->m_window_object; + auto* inspected_node = window.associated_document().inspected_node(); + if (!inspected_node) + return JS::js_undefined(); + + return inspected_node; +} + +JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalEnvironmentExtensions::$__getter) +{ + auto* console_global_object = TRY(get_console(vm)); + return console_global_object->m_most_recent_result; +} + +JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalEnvironmentExtensions::$_function) +{ + auto* console_global_object = TRY(get_console(vm)); + auto& window = *console_global_object->m_window_object; + + auto selector = TRY(vm.argument(0).to_string(vm)); + + if (vm.argument_count() > 1) { + auto element_value = vm.argument(1); + if (!(element_value.is_object() && is(element_value.as_object()))) { + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "Node"); + } + + auto& element = static_cast(element_value.as_object()); + return TRY(Web::Bindings::throw_dom_exception_if_needed(vm, [&]() { + return element.query_selector(selector); + })); + } + + return TRY(Web::Bindings::throw_dom_exception_if_needed(vm, [&]() { + return window.associated_document().query_selector(selector); + })); +} + +JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalEnvironmentExtensions::$$_function) +{ + auto* console_global_object = TRY(get_console(vm)); + auto& window = *console_global_object->m_window_object; + + auto selector = TRY(vm.argument(0).to_string(vm)); + + Web::DOM::ParentNode* element = &window.associated_document(); + + if (vm.argument_count() > 1) { + auto element_value = vm.argument(1); + if (!(element_value.is_object() && is(element_value.as_object()))) { + return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "Node"); + } + + element = static_cast(&element_value.as_object()); + } + + auto node_list = TRY(Web::Bindings::throw_dom_exception_if_needed(vm, [&]() { + return element->query_selector_all(selector); + })); + + auto* array = TRY(JS::Array::create(*vm.current_realm(), node_list->length())); + for (auto i = 0u; i < node_list->length(); ++i) { + TRY(array->create_data_property_or_throw(i, node_list->item_value(i))); + } + + return array; +} + +} diff --git a/Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.h b/Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.h new file mode 100644 index 0000000000..476000ad85 --- /dev/null +++ b/Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-2022, Sam Atkins + * Copyright (c) 2022, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include + +namespace WebContent { + +class ConsoleGlobalEnvironmentExtensions final : public JS::Object { + JS_OBJECT(ConsoleGlobalEnvironmentExtensions, JS::Object); + +public: + ConsoleGlobalEnvironmentExtensions(JS::Realm&, Web::HTML::Window&); + virtual void initialize(JS::Realm&) override; + virtual ~ConsoleGlobalEnvironmentExtensions() override = default; + + void set_most_recent_result(JS::Value result) { m_most_recent_result = move(result); } + +private: + virtual void visit_edges(Visitor&) override; + + // $0, the DOM node currently selected in the inspector + JS_DECLARE_NATIVE_FUNCTION($0_getter); + // $_, the value of the most recent expression entered into the console + JS_DECLARE_NATIVE_FUNCTION($__getter); + // $(selector, element), equivalent to `(element || document).querySelector(selector)` + JS_DECLARE_NATIVE_FUNCTION($_function); + // $$(selector, element), equivalent to `(element || document).querySelectorAll(selector)` + JS_DECLARE_NATIVE_FUNCTION($$_function); + + JS::NonnullGCPtr m_window_object; + JS::Value m_most_recent_result { JS::js_undefined() }; +}; + +} diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.cpp b/Userland/Services/WebContent/ConsoleGlobalObject.cpp deleted file mode 100644 index 8082698fa7..0000000000 --- a/Userland/Services/WebContent/ConsoleGlobalObject.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2021-2022, Sam Atkins - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "ConsoleGlobalObject.h" -#include -#include -#include -#include -#include -#include - -namespace WebContent { - -ConsoleGlobalObject::ConsoleGlobalObject(JS::Realm& realm, Web::HTML::Window& parent_object) - : GlobalObject(realm) - , m_window_object(&parent_object) -{ -} - -void ConsoleGlobalObject::initialize(JS::Realm& realm) -{ - Base::initialize(realm); - - define_native_accessor(realm, "$0", $0_getter, nullptr, 0); - define_native_accessor(realm, "$_", $__getter, nullptr, 0); - define_native_function(realm, "$", $_function, 2, JS::default_attributes); - define_native_function(realm, "$$", $$_function, 2, JS::default_attributes); -} - -void ConsoleGlobalObject::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_window_object); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_get_prototype_of() const -{ - return m_window_object->internal_get_prototype_of(); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_set_prototype_of(JS::Object* prototype) -{ - return m_window_object->internal_set_prototype_of(prototype); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_is_extensible() const -{ - return m_window_object->internal_is_extensible(); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_prevent_extensions() -{ - return m_window_object->internal_prevent_extensions(); -} - -JS::ThrowCompletionOr> ConsoleGlobalObject::internal_get_own_property(JS::PropertyKey const& property_name) const -{ - if (auto result = TRY(m_window_object->internal_get_own_property(property_name)); result.has_value()) - return result; - - return Base::internal_get_own_property(property_name); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_define_own_property(JS::PropertyKey const& property_name, JS::PropertyDescriptor const& descriptor) -{ - return m_window_object->internal_define_own_property(property_name, descriptor); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_has_property(JS::PropertyKey const& property_name) const -{ - return TRY(Object::internal_has_property(property_name)) || TRY(m_window_object->internal_has_property(property_name)); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_get(JS::PropertyKey const& property_name, JS::Value receiver) const -{ - if (TRY(m_window_object->has_own_property(property_name))) - return m_window_object->internal_get(property_name, (receiver == this) ? m_window_object : receiver); - - return Base::internal_get(property_name, receiver); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_set(JS::PropertyKey const& property_name, JS::Value value, JS::Value receiver) -{ - return m_window_object->internal_set(property_name, value, (receiver == this) ? m_window_object : receiver); -} - -JS::ThrowCompletionOr ConsoleGlobalObject::internal_delete(JS::PropertyKey const& property_name) -{ - return m_window_object->internal_delete(property_name); -} - -JS::ThrowCompletionOr> ConsoleGlobalObject::internal_own_property_keys() const -{ - return m_window_object->internal_own_property_keys(); -} - -static JS::ThrowCompletionOr get_console(JS::VM& vm) -{ - if (!is(vm.get_global_object())) - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "ConsoleGlobalObject"); - - return static_cast(&vm.get_global_object()); -} - -JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalObject::$0_getter) -{ - auto* console_global_object = TRY(get_console(vm)); - auto& window = *console_global_object->m_window_object; - auto* inspected_node = window.associated_document().inspected_node(); - if (!inspected_node) - return JS::js_undefined(); - - return inspected_node; -} - -JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalObject::$__getter) -{ - auto* console_global_object = TRY(get_console(vm)); - return console_global_object->m_most_recent_result; -} - -JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalObject::$_function) -{ - auto* console_global_object = TRY(get_console(vm)); - auto& window = *console_global_object->m_window_object; - - auto selector = TRY(vm.argument(0).to_string(vm)); - - if (vm.argument_count() > 1) { - auto element_value = vm.argument(1); - if (!(element_value.is_object() && is(element_value.as_object()))) { - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "Node"); - } - - auto& element = static_cast(element_value.as_object()); - return TRY(Web::Bindings::throw_dom_exception_if_needed(vm, [&]() { - return element.query_selector(selector); - })); - } - - return TRY(Web::Bindings::throw_dom_exception_if_needed(vm, [&]() { - return window.associated_document().query_selector(selector); - })); -} - -JS_DEFINE_NATIVE_FUNCTION(ConsoleGlobalObject::$$_function) -{ - auto* console_global_object = TRY(get_console(vm)); - auto& window = *console_global_object->m_window_object; - - auto selector = TRY(vm.argument(0).to_string(vm)); - - Web::DOM::ParentNode* element = &window.associated_document(); - - if (vm.argument_count() > 1) { - auto element_value = vm.argument(1); - if (!(element_value.is_object() && is(element_value.as_object()))) { - return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "Node"); - } - - element = static_cast(&element_value.as_object()); - } - - auto node_list = TRY(Web::Bindings::throw_dom_exception_if_needed(vm, [&]() { - return element->query_selector_all(selector); - })); - - auto* array = TRY(JS::Array::create(*vm.current_realm(), node_list->length())); - for (auto i = 0u; i < node_list->length(); ++i) { - TRY(array->create_data_property_or_throw(i, node_list->item_value(i))); - } - - return array; -} - -} diff --git a/Userland/Services/WebContent/ConsoleGlobalObject.h b/Userland/Services/WebContent/ConsoleGlobalObject.h deleted file mode 100644 index 75d13ad4c5..0000000000 --- a/Userland/Services/WebContent/ConsoleGlobalObject.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2021-2022, Sam Atkins - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include - -namespace WebContent { - -class ConsoleGlobalObject final : public JS::GlobalObject { - JS_OBJECT(ConsoleGlobalObject, JS::GlobalObject); - -public: - ConsoleGlobalObject(JS::Realm&, Web::HTML::Window&); - virtual void initialize(JS::Realm&) override; - virtual ~ConsoleGlobalObject() override = default; - - virtual JS::ThrowCompletionOr internal_get_prototype_of() const override; - virtual JS::ThrowCompletionOr internal_set_prototype_of(Object* prototype) override; - virtual JS::ThrowCompletionOr internal_is_extensible() const override; - virtual JS::ThrowCompletionOr internal_prevent_extensions() override; - virtual JS::ThrowCompletionOr> internal_get_own_property(JS::PropertyKey const& name) const override; - virtual JS::ThrowCompletionOr internal_define_own_property(JS::PropertyKey const& name, JS::PropertyDescriptor const& descriptor) override; - virtual JS::ThrowCompletionOr internal_has_property(JS::PropertyKey const& name) const override; - virtual JS::ThrowCompletionOr internal_get(JS::PropertyKey const&, JS::Value) const override; - virtual JS::ThrowCompletionOr internal_set(JS::PropertyKey const&, JS::Value value, JS::Value receiver) override; - virtual JS::ThrowCompletionOr internal_delete(JS::PropertyKey const& name) override; - virtual JS::ThrowCompletionOr> internal_own_property_keys() const override; - - void set_most_recent_result(JS::Value result) { m_most_recent_result = move(result); } - -private: - virtual void visit_edges(Visitor&) override; - - // $0, the DOM node currently selected in the inspector - JS_DECLARE_NATIVE_FUNCTION($0_getter); - // $_, the value of the most recent expression entered into the console - JS_DECLARE_NATIVE_FUNCTION($__getter); - // $(selector, element), equivalent to `(element || document).querySelector(selector)` - JS_DECLARE_NATIVE_FUNCTION($_function); - // $$(selector, element), equivalent to `(element || document).querySelectorAll(selector)` - JS_DECLARE_NATIVE_FUNCTION($$_function); - - Web::HTML::Window* m_window_object; - JS::Value m_most_recent_result { JS::js_undefined() }; -}; - -} diff --git a/Userland/Services/WebContent/Forward.h b/Userland/Services/WebContent/Forward.h index b5fedefa07..160588a103 100644 --- a/Userland/Services/WebContent/Forward.h +++ b/Userland/Services/WebContent/Forward.h @@ -9,7 +9,7 @@ namespace WebContent { class ConnectionFromClient; -class ConsoleGlobalObject; +class ConsoleGlobalEnvironmentExtensions; class PageHost; class WebContentConsoleClient; class WebDriverConnection; diff --git a/Userland/Services/WebContent/WebContentConsoleClient.cpp b/Userland/Services/WebContent/WebContentConsoleClient.cpp index 649cbeceab..0afd762d69 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.cpp +++ b/Userland/Services/WebContent/WebContentConsoleClient.cpp @@ -7,78 +7,42 @@ */ #include "WebContentConsoleClient.h" +#include #include #include +#include +#include #include #include #include #include -#include +#include namespace WebContent { -class ConsoleEnvironmentSettingsObject final : public Web::HTML::EnvironmentSettingsObject { - JS_CELL(ConsoleEnvironmentSettingsObject, EnvironmentSettingsObject); - -public: - ConsoleEnvironmentSettingsObject(NonnullOwnPtr execution_context) - : Web::HTML::EnvironmentSettingsObject(move(execution_context)) - { - } - - virtual ~ConsoleEnvironmentSettingsObject() override = default; - - JS::GCPtr responsible_document() override { return nullptr; } - DeprecatedString api_url_character_encoding() override { return m_api_url_character_encoding; } - AK::URL api_base_url() override { return m_url; } - Web::HTML::Origin origin() override { return m_origin; } - Web::HTML::PolicyContainer policy_container() override { return m_policy_container; } - Web::HTML::CanUseCrossOriginIsolatedAPIs cross_origin_isolated_capability() override { return Web::HTML::CanUseCrossOriginIsolatedAPIs::Yes; } - -private: - DeprecatedString m_api_url_character_encoding; - AK::URL m_url; - Web::HTML::Origin m_origin; - Web::HTML::PolicyContainer m_policy_container; -}; - WebContentConsoleClient::WebContentConsoleClient(JS::Console& console, JS::Realm& realm, ConnectionFromClient& client) : ConsoleClient(console) , m_client(client) - , m_realm(realm) { - JS::DeferGC defer_gc(realm.heap()); - - auto& vm = realm.vm(); - auto& window = static_cast(realm.global_object()); - - auto console_execution_context = MUST(JS::Realm::initialize_host_defined_realm( - vm, [&](JS::Realm& realm) { - m_console_global_object = vm.heap().allocate_without_realm(realm, window); - return m_console_global_object; - }, - nullptr)); - - auto* console_realm = console_execution_context->realm; - m_console_settings = vm.heap().allocate(*console_realm, move(console_execution_context)); - auto* intrinsics = vm.heap().allocate(*console_realm, *console_realm); - auto host_defined = make(*m_console_settings, *intrinsics); - console_realm->set_host_defined(move(host_defined)); + auto& window = verify_cast(realm.global_object()); + m_console_global_environment_extensions = realm.heap().allocate(realm, realm, window); } void WebContentConsoleClient::handle_input(DeprecatedString const& js_source) { - if (!m_realm) + if (!m_console_global_environment_extensions) return; - auto script = Web::HTML::ClassicScript::create("(console)", js_source, *m_console_settings, m_console_settings->api_base_url()); + auto& settings = Web::HTML::relevant_settings_object(*m_console_global_environment_extensions); + auto script = Web::HTML::ClassicScript::create("(console)", js_source, settings, settings.api_base_url()); + + JS::Environment* with_scope = JS::new_object_environment(*m_console_global_environment_extensions, true, &settings.realm().global_environment()); // FIXME: Add parse error printouts back once ClassicScript can report parse errors. - - auto result = script->run(); + auto result = script->run(Web::HTML::ClassicScript::RethrowErrors::No, with_scope); if (result.value().has_value()) { - m_console_global_object->set_most_recent_result(result.value().value()); + m_console_global_environment_extensions->set_most_recent_result(result.value().value()); print_html(JS::MarkupGenerator::html_from_value(*result.value()).release_value_but_fixme_should_propagate_errors().to_deprecated_string()); } } diff --git a/Userland/Services/WebContent/WebContentConsoleClient.h b/Userland/Services/WebContent/WebContentConsoleClient.h index 9ab581d222..208e8a5399 100644 --- a/Userland/Services/WebContent/WebContentConsoleClient.h +++ b/Userland/Services/WebContent/WebContentConsoleClient.h @@ -35,9 +35,7 @@ private: } ConnectionFromClient& m_client; - WeakPtr m_realm; - JS::GCPtr m_console_settings; - JS::Handle m_console_global_object; + JS::Handle m_console_global_environment_extensions; void clear_output(); void print_html(DeprecatedString const& line);