summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-12-09 18:48:25 +0100
committerLinus Groh <mail@linusgroh.de>2022-12-09 18:51:03 +0000
commitfbf9cb338728bdae160655a1e1527f5ce0e1871a (patch)
tree6cc659f9f431338e9a8977b341f98fd1f85a7c22
parent23b07b3408728f5ea184c6fa928729e11b0c4957 (diff)
downloadserenity-fbf9cb338728bdae160655a1e1527f5ce0e1871a.zip
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().
-rw-r--r--Userland/Libraries/LibJS/Interpreter.cpp6
-rw-r--r--Userland/Libraries/LibJS/Interpreter.h2
-rw-r--r--Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.cpp4
-rw-r--r--Userland/Libraries/LibWeb/HTML/Scripting/ClassicScript.h2
-rw-r--r--Userland/Services/WebContent/CMakeLists.txt2
-rw-r--r--Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.cpp120
-rw-r--r--Userland/Services/WebContent/ConsoleGlobalEnvironmentExtensions.h42
-rw-r--r--Userland/Services/WebContent/ConsoleGlobalObject.cpp179
-rw-r--r--Userland/Services/WebContent/ConsoleGlobalObject.h54
-rw-r--r--Userland/Services/WebContent/Forward.h2
-rw-r--r--Userland/Services/WebContent/WebContentConsoleClient.cpp62
-rw-r--r--Userland/Services/WebContent/WebContentConsoleClient.h4
12 files changed, 187 insertions, 292 deletions
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<Value> Interpreter::run(Script& script_record)
+ThrowCompletionOr<Value> Interpreter::run(Script& script_record, JS::GCPtr<Environment> lexical_environment_override)
{
auto& vm = this->vm();
@@ -62,6 +62,10 @@ ThrowCompletionOr<Value> 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<Value> run(Script&);
+ ThrowCompletionOr<Value> run(Script&, JS::GCPtr<Environment> lexical_environment_override = {});
ThrowCompletionOr<Value> 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> 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<JS::Environment> 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<JS::Environment> 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 <atkinssj@serenityos.org>
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "ConsoleGlobalEnvironmentExtensions.h"
+#include <LibJS/Runtime/Array.h>
+#include <LibJS/Runtime/Completion.h>
+#include <LibWeb/Bindings/ExceptionOrUtils.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/NodeList.h>
+#include <LibWeb/HTML/Window.h>
+
+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<ConsoleGlobalEnvironmentExtensions*> get_console(JS::VM& vm)
+{
+ auto this_value = vm.this_value();
+ if (!this_value.is_object() || !is<ConsoleGlobalEnvironmentExtensions>(this_value.as_object()))
+ return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "ConsoleGlobalEnvironmentExtensions");
+
+ return &static_cast<ConsoleGlobalEnvironmentExtensions&>(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<Web::DOM::ParentNode>(element_value.as_object()))) {
+ return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Node");
+ }
+
+ auto& element = static_cast<Web::DOM::ParentNode&>(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<Web::DOM::ParentNode>(element_value.as_object()))) {
+ return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Node");
+ }
+
+ element = static_cast<Web::DOM::ParentNode*>(&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 <atkinssj@serenityos.org>
+ * Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibJS/Forward.h>
+#include <LibJS/Runtime/Completion.h>
+#include <LibWeb/HTML/Window.h>
+
+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<Web::HTML::Window> 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 <atkinssj@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#include "ConsoleGlobalObject.h"
-#include <LibJS/Runtime/Array.h>
-#include <LibJS/Runtime/Completion.h>
-#include <LibWeb/Bindings/ExceptionOrUtils.h>
-#include <LibWeb/DOM/Document.h>
-#include <LibWeb/DOM/NodeList.h>
-#include <LibWeb/HTML/Window.h>
-
-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<JS::Object*> ConsoleGlobalObject::internal_get_prototype_of() const
-{
- return m_window_object->internal_get_prototype_of();
-}
-
-JS::ThrowCompletionOr<bool> ConsoleGlobalObject::internal_set_prototype_of(JS::Object* prototype)
-{
- return m_window_object->internal_set_prototype_of(prototype);
-}
-
-JS::ThrowCompletionOr<bool> ConsoleGlobalObject::internal_is_extensible() const
-{
- return m_window_object->internal_is_extensible();
-}
-
-JS::ThrowCompletionOr<bool> ConsoleGlobalObject::internal_prevent_extensions()
-{
- return m_window_object->internal_prevent_extensions();
-}
-
-JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> 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<bool> 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<bool> 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<JS::Value> 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<bool> 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<bool> ConsoleGlobalObject::internal_delete(JS::PropertyKey const& property_name)
-{
- return m_window_object->internal_delete(property_name);
-}
-
-JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> ConsoleGlobalObject::internal_own_property_keys() const
-{
- return m_window_object->internal_own_property_keys();
-}
-
-static JS::ThrowCompletionOr<ConsoleGlobalObject*> get_console(JS::VM& vm)
-{
- if (!is<ConsoleGlobalObject>(vm.get_global_object()))
- return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "ConsoleGlobalObject");
-
- return static_cast<ConsoleGlobalObject*>(&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<Web::DOM::ParentNode>(element_value.as_object()))) {
- return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Node");
- }
-
- auto& element = static_cast<Web::DOM::ParentNode&>(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<Web::DOM::ParentNode>(element_value.as_object()))) {
- return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "Node");
- }
-
- element = static_cast<Web::DOM::ParentNode*>(&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 <atkinssj@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
-
-#pragma once
-
-#include <LibJS/Forward.h>
-#include <LibJS/Runtime/Completion.h>
-#include <LibJS/Runtime/GlobalObject.h>
-#include <LibWeb/HTML/Window.h>
-
-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<Object*> internal_get_prototype_of() const override;
- virtual JS::ThrowCompletionOr<bool> internal_set_prototype_of(Object* prototype) override;
- virtual JS::ThrowCompletionOr<bool> internal_is_extensible() const override;
- virtual JS::ThrowCompletionOr<bool> internal_prevent_extensions() override;
- virtual JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> internal_get_own_property(JS::PropertyKey const& name) const override;
- virtual JS::ThrowCompletionOr<bool> internal_define_own_property(JS::PropertyKey const& name, JS::PropertyDescriptor const& descriptor) override;
- virtual JS::ThrowCompletionOr<bool> internal_has_property(JS::PropertyKey const& name) const override;
- virtual JS::ThrowCompletionOr<JS::Value> internal_get(JS::PropertyKey const&, JS::Value) const override;
- virtual JS::ThrowCompletionOr<bool> internal_set(JS::PropertyKey const&, JS::Value value, JS::Value receiver) override;
- virtual JS::ThrowCompletionOr<bool> internal_delete(JS::PropertyKey const& name) override;
- virtual JS::ThrowCompletionOr<JS::MarkedVector<JS::Value>> 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 <AK/TemporaryChange.h>
#include <LibJS/Interpreter.h>
#include <LibJS/MarkupGenerator.h>
+#include <LibJS/Runtime/AbstractOperations.h>
+#include <LibJS/Runtime/ObjectEnvironment.h>
#include <LibWeb/HTML/PolicyContainers.h>
#include <LibWeb/HTML/Scripting/ClassicScript.h>
#include <LibWeb/HTML/Scripting/Environments.h>
#include <LibWeb/HTML/Window.h>
-#include <WebContent/ConsoleGlobalObject.h>
+#include <WebContent/ConsoleGlobalEnvironmentExtensions.h>
namespace WebContent {
-class ConsoleEnvironmentSettingsObject final : public Web::HTML::EnvironmentSettingsObject {
- JS_CELL(ConsoleEnvironmentSettingsObject, EnvironmentSettingsObject);
-
-public:
- ConsoleEnvironmentSettingsObject(NonnullOwnPtr<JS::ExecutionContext> execution_context)
- : Web::HTML::EnvironmentSettingsObject(move(execution_context))
- {
- }
-
- virtual ~ConsoleEnvironmentSettingsObject() override = default;
-
- JS::GCPtr<Web::DOM::Document> 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<Web::HTML::Window&>(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<ConsoleGlobalObject>(realm, window);
- return m_console_global_object;
- },
- nullptr));
-
- auto* console_realm = console_execution_context->realm;
- m_console_settings = vm.heap().allocate<ConsoleEnvironmentSettingsObject>(*console_realm, move(console_execution_context));
- auto* intrinsics = vm.heap().allocate<Web::Bindings::Intrinsics>(*console_realm, *console_realm);
- auto host_defined = make<Web::Bindings::HostDefined>(*m_console_settings, *intrinsics);
- console_realm->set_host_defined(move(host_defined));
+ auto& window = verify_cast<Web::HTML::Window>(realm.global_object());
+ m_console_global_environment_extensions = realm.heap().allocate<ConsoleGlobalEnvironmentExtensions>(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());
- // FIXME: Add parse error printouts back once ClassicScript can report parse errors.
+ JS::Environment* with_scope = JS::new_object_environment(*m_console_global_environment_extensions, true, &settings.realm().global_environment());
- auto result = script->run();
+ // FIXME: Add parse error printouts back once ClassicScript can report parse errors.
+ 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<JS::Realm> m_realm;
- JS::GCPtr<class ConsoleEnvironmentSettingsObject> m_console_settings;
- JS::Handle<ConsoleGlobalObject> m_console_global_object;
+ JS::Handle<ConsoleGlobalEnvironmentExtensions> m_console_global_environment_extensions;
void clear_output();
void print_html(DeprecatedString const& line);