summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavidot <davidot@serenityos.org>2022-08-27 14:35:54 +0200
committerLinus Groh <mail@linusgroh.de>2022-08-27 20:33:27 +0100
commitba5bcb67a56389c8949e7691eb112527ee52946f (patch)
treedb8fa04150ea38ad7ed88fca26e543e2ed309b7e
parent12300b7d0b1b3735bb1c413ee5d8ac22163ac385 (diff)
downloadserenity-ba5bcb67a56389c8949e7691eb112527ee52946f.zip
LibWeb: Implement the HostEnsureCanAddPrivateElement JS hook
Also added a local test for ensuring this behavior since it is unique to browsers. Since we don't actually use WindowProxy anywhere yet we just test on location for now.
-rw-r--r--Base/res/html/misc/private-element-test.html63
-rw-r--r--Base/res/html/misc/welcome.html1
-rw-r--r--Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp34
3 files changed, 87 insertions, 11 deletions
diff --git a/Base/res/html/misc/private-element-test.html b/Base/res/html/misc/private-element-test.html
new file mode 100644
index 0000000000..1a9d669298
--- /dev/null
+++ b/Base/res/html/misc/private-element-test.html
@@ -0,0 +1,63 @@
+<html>
+ <body>
+ <span
+ >If passed, the text below should say: "Passed" And the iframe should have loaded</span
+ >
+ <div id="result">Starting up</div>
+ <script>
+ class Base {
+ constructor(o) {
+ return o;
+ }
+ }
+
+ class Stamper extends Base {
+ #x = 10;
+ static hasX(o) {
+ return #x in o;
+ }
+ }
+
+ let failed = false;
+ function status(text, fail = false) {
+ console.log("Status", text, fail, failed);
+ const output = document.getElementById("result");
+ if (fail) {
+ output.innerHTML += "Fail: " + text + "<br />";
+ output.style.color = "red";
+ failed = true;
+ } else if (!failed) {
+ output.innerHTML = text;
+ output.style.color = "blue";
+ }
+ }
+
+ function fail(text) {
+ return status(text, true);
+ }
+
+ status("Running");
+
+ const iframe = document.body.appendChild(document.createElement("iframe"));
+ iframe.src = "file:///res/html/misc/welcome.html";
+ iframe.onload = () => {
+ status("Inside onload", false);
+ // FIXME: Also test on contentWindow itself once that is an actual WindowProxy.
+ const locationObject = iframe.contentWindow.location;
+ try {
+ new Stamper(locationObject);
+ fail("Should have thrown type error!");
+ } catch (e) {
+ if (!(e instanceof TypeError))
+ fail("Should have thrown type error! But threw: " + e);
+ }
+ if (Stamper.hasX(locationObject)) {
+ fail("Stamped #x on Location");
+ } else {
+ status("Passed");
+ }
+ };
+ status("Set src and onload, waiting for onload");
+ </script>
+ </body>
+</html>
diff --git a/Base/res/html/misc/welcome.html b/Base/res/html/misc/welcome.html
index 0ff3d086e8..e3462f0cde 100644
--- a/Base/res/html/misc/welcome.html
+++ b/Base/res/html/misc/welcome.html
@@ -170,6 +170,7 @@
<li><a href="async-js.html">Basic test for async functions and their integration with the LibWeb event loop</a></li>
<li><a href="worker_parent.html">Workers</a></li>
<li><a href="storage.html">Web Storage API</a></li>
+ <li><a href="private-element-test.html">Test for rejecting private elements on special objects</a></li>
<li><h3>Canvas</h3></li>
<li><a href="canvas.html">canvas 2D test</a></li>
<li><a href="canvas-rotate.html">canvas rotate()</a></li>
diff --git a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp
index a78434db19..91c269c46c 100644
--- a/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp
+++ b/Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp
@@ -12,9 +12,11 @@
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Bindings/IDLAbstractOperations.h>
+#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/MutationObserverWrapper.h>
#include <LibWeb/Bindings/MutationRecordWrapper.h>
+#include <LibWeb/Bindings/WindowProxy.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/PromiseRejectionEvent.h>
#include <LibWeb/HTML/Scripting/ClassicScript.h>
@@ -58,9 +60,19 @@ JS::VM& main_thread_vm()
static_cast<WebEngineCustomData*>(vm->custom_data())->event_loop.set_vm(*vm);
- // FIXME: Implement 8.1.5.1 HostEnsureCanCompileStrings(callerRealm, calleeRealm), https://html.spec.whatwg.org/multipage/webappapis.html#hostensurecancompilestrings(callerrealm,-calleerealm)
+ // 8.1.5.1 HostEnsureCanAddPrivateElement(O), https://html.spec.whatwg.org/multipage/webappapis.html#the-hostensurecanaddprivateelement-implementation
+ vm->host_ensure_can_add_private_element = [](JS::Object const& object) -> JS::ThrowCompletionOr<void> {
+ // 1. If O is a WindowProxy object, or implements Location, then return Completion { [[Type]]: throw, [[Value]]: a new TypeError }.
+ if (is<WindowProxy>(object) || is<LocationObject>(object))
+ return vm->throw_completion<JS::TypeError>("Cannot add private elements to window or location object");
- // 8.1.5.2 HostPromiseRejectionTracker(promise, operation), https://html.spec.whatwg.org/multipage/webappapis.html#the-hostpromiserejectiontracker-implementation
+ // 2. Return NormalCompletion(unused).
+ return {};
+ };
+
+ // FIXME: Implement 8.1.5.2 HostEnsureCanCompileStrings(callerRealm, calleeRealm), https://html.spec.whatwg.org/multipage/webappapis.html#hostensurecancompilestrings(callerrealm,-calleerealm)
+
+ // 8.1.5.3 HostPromiseRejectionTracker(promise, operation), https://html.spec.whatwg.org/multipage/webappapis.html#the-hostpromiserejectiontracker-implementation
vm->host_promise_rejection_tracker = [](JS::Promise& promise, JS::Promise::RejectionOperation operation) {
// 1. Let script be the running script.
// The running script is the script in the [[HostDefined]] field in the ScriptOrModule component of the running JavaScript execution context.
@@ -132,7 +144,7 @@ JS::VM& main_thread_vm()
}
};
- // 8.1.5.3.1 HostCallJobCallback(callback, V, argumentsList), https://html.spec.whatwg.org/multipage/webappapis.html#hostcalljobcallback
+ // 8.1.5.4.1 HostCallJobCallback(callback, V, argumentsList), https://html.spec.whatwg.org/multipage/webappapis.html#hostcalljobcallback
vm->host_call_job_callback = [](JS::JobCallback& callback, JS::Value this_value, JS::MarkedVector<JS::Value> arguments_list) {
auto& callback_host_defined = verify_cast<WebEngineCustomJobCallbackData>(*callback.custom_data);
@@ -162,7 +174,7 @@ JS::VM& main_thread_vm()
return result;
};
- // 8.1.5.3.2 HostEnqueueFinalizationRegistryCleanupJob(finalizationRegistry), https://html.spec.whatwg.org/multipage/webappapis.html#hostenqueuefinalizationregistrycleanupjob
+ // 8.1.5.4.2 HostEnqueueFinalizationRegistryCleanupJob(finalizationRegistry), https://html.spec.whatwg.org/multipage/webappapis.html#hostenqueuefinalizationregistrycleanupjob
vm->host_enqueue_finalization_registry_cleanup_job = [](JS::FinalizationRegistry& finalization_registry) mutable {
// 1. Let global be finalizationRegistry.[[Realm]]'s global object.
auto& global = finalization_registry.realm().global_object();
@@ -191,7 +203,7 @@ JS::VM& main_thread_vm()
});
};
- // 8.1.5.3.3 HostEnqueuePromiseJob(job, realm), https://html.spec.whatwg.org/multipage/webappapis.html#hostenqueuepromisejob
+ // 8.1.5.4.3 HostEnqueuePromiseJob(job, realm), https://html.spec.whatwg.org/multipage/webappapis.html#hostenqueuepromisejob
vm->host_enqueue_promise_job = [](Function<JS::ThrowCompletionOr<JS::Value>()> job, JS::Realm* realm) {
// 1. If realm is not null, then let job settings be the settings object for realm. Otherwise, let job settings be null.
HTML::EnvironmentSettingsObject* job_settings { nullptr };
@@ -257,7 +269,7 @@ JS::VM& main_thread_vm()
});
};
- // 8.1.5.3.4 HostMakeJobCallback(callable), https://html.spec.whatwg.org/multipage/webappapis.html#hostmakejobcallback
+ // 8.1.5.4.4 HostMakeJobCallback(callable), https://html.spec.whatwg.org/multipage/webappapis.html#hostmakejobcallback
vm->host_make_job_callback = [](JS::FunctionObject& callable) -> JS::JobCallback {
// 1. Let incumbent settings be the incumbent settings object.
auto& incumbent_settings = HTML::incumbent_settings_object();
@@ -283,12 +295,12 @@ JS::VM& main_thread_vm()
return { JS::make_handle(&callable), move(host_defined) };
};
- // FIXME: Implement 8.1.5.4.1 HostGetImportMetaProperties(moduleRecord), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetimportmetaproperties
- // FIXME: Implement 8.1.5.4.2 HostImportModuleDynamically(referencingScriptOrModule, moduleRequest, promiseCapability), https://html.spec.whatwg.org/multipage/webappapis.html#hostimportmoduledynamically(referencingscriptormodule,-modulerequest,-promisecapability)
- // FIXME: Implement 8.1.5.4.3 HostResolveImportedModule(referencingScriptOrModule, moduleRequest), https://html.spec.whatwg.org/multipage/webappapis.html#hostresolveimportedmodule(referencingscriptormodule,-modulerequest)
- // FIXME: Implement 8.1.5.4.4 HostGetSupportedImportAssertions(), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetsupportedimportassertions
+ // FIXME: Implement 8.1.5.5.1 HostGetImportMetaProperties(moduleRecord), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetimportmetaproperties
+ // FIXME: Implement 8.1.5.5.2 HostImportModuleDynamically(referencingScriptOrModule, moduleRequest, promiseCapability), https://html.spec.whatwg.org/multipage/webappapis.html#hostimportmoduledynamically(referencingscriptormodule,-modulerequest,-promisecapability)
+ // FIXME: Implement 8.1.5.5.3 HostResolveImportedModule(referencingScriptOrModule, moduleRequest), https://html.spec.whatwg.org/multipage/webappapis.html#hostresolveimportedmodule(referencingscriptormodule,-modulerequest)
+ // FIXME: Implement 8.1.5.5.4 HostGetSupportedImportAssertions(), https://html.spec.whatwg.org/multipage/webappapis.html#hostgetsupportedimportassertions
- vm->host_resolve_imported_module = [&](JS::ScriptOrModule, JS::ModuleRequest const&) -> JS::ThrowCompletionOr<NonnullRefPtr<JS::Module>> {
+ vm->host_resolve_imported_module = [](JS::ScriptOrModule, JS::ModuleRequest const&) -> JS::ThrowCompletionOr<NonnullRefPtr<JS::Module>> {
return vm->throw_completion<JS::InternalError>(JS::ErrorType::NotImplemented, "Modules in the browser");
};