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.
This commit is contained in:
davidot 2022-08-27 14:35:54 +02:00 committed by Linus Groh
parent 12300b7d0b
commit ba5bcb67a5
3 changed files with 87 additions and 11 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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");
};