Skip to content

Commit

Permalink
LibWeb: Hook up the HostInitializeShadowRealm callback
Browse files Browse the repository at this point in the history
This is enough for a basic shadow realm to work :^)

There is more that we still need to implement here such as module
loading and fixing up the global object, but this is enough to get some
basic usage working.
  • Loading branch information
shannonbooth committed Nov 5, 2024
1 parent 320b478 commit 5cda02c
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
PASS: Exception thrown 'TypeError: Wrapped value must be primitive or a function object, got [object Promise]'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Shadow realm evaluation returned: 2
13 changes: 13 additions & 0 deletions Tests/LibWeb/Text/input/HTML/shadow-realm-async-evaluate.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script src="../include.js"></script>
<script>
test(() => {
const realm = new ShadowRealm()
const aSync = realm.evaluate(`async () => 1 + 1`);
try {
aSync();
println('Fail! No exception thrown');
} catch (e) {
println(`PASS: Exception thrown '${e}'`);
}
})
</script>
8 changes: 8 additions & 0 deletions Tests/LibWeb/Text/input/HTML/shadow-realm-sync-evaluate.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script src="../include.js"></script>
<script>
test(() => {
const realm = new ShadowRealm();
const result = realm.evaluate(`() => 1 + 1`)();
println(`Shadow realm evaluation returned: ${result}`);
});
</script>
3 changes: 3 additions & 0 deletions Userland/Libraries/LibJS/Runtime/Realm.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ class Realm final : public Cell {
static ThrowCompletionOr<NonnullOwnPtr<ExecutionContext>> initialize_host_defined_realm(VM&, Function<Object*(Realm&)> create_global_object, Function<Object*(Realm&)> create_global_this_value);

[[nodiscard]] Object& global_object() const { return *m_global_object; }
void set_global_object(NonnullGCPtr<Object> global) { m_global_object = global; }

[[nodiscard]] GlobalEnvironment& global_environment() const { return *m_global_environment; }
void set_global_environment(NonnullGCPtr<GlobalEnvironment> environment) { m_global_environment = environment; }

[[nodiscard]] Intrinsics const& intrinsics() const { return *m_intrinsics; }
[[nodiscard]] Intrinsics& intrinsics() { return *m_intrinsics; }
Expand Down
44 changes: 44 additions & 0 deletions Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
#include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/Environment.h>
#include <LibJS/Runtime/FinalizationRegistry.h>
#include <LibJS/Runtime/GlobalEnvironment.h>
#include <LibJS/Runtime/ModuleRequest.h>
#include <LibJS/Runtime/NativeFunction.h>
#include <LibJS/Runtime/ShadowRealm.h>
#include <LibJS/Runtime/VM.h>
#include <LibJS/SourceTextModule.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/SyntheticHostDefined.h>
#include <LibWeb/Bindings/WindowExposedInterfaces.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/MutationType.h>
Expand All @@ -35,7 +38,9 @@
#include <LibWeb/HTML/Scripting/Fetching.h>
#include <LibWeb/HTML/Scripting/ModuleScript.h>
#include <LibWeb/HTML/Scripting/Script.h>
#include <LibWeb/HTML/Scripting/SyntheticRealmSettings.h>
#include <LibWeb/HTML/Scripting/TemporaryExecutionContext.h>
#include <LibWeb/HTML/ShadowRealmGlobalScope.h>
#include <LibWeb/HTML/TagNames.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/HTML/WindowProxy.h>
Expand Down Expand Up @@ -560,6 +565,45 @@ ErrorOr<void> initialize_main_thread_vm(HTML::EventLoop::Type type)
HTML::fetch_single_imported_module_script(*module_map_realm, url.release_value(), *fetch_client, destination, fetch_options, *module_map_realm, fetch_referrer, module_request, perform_fetch, on_single_fetch_complete);
};

// https://whatpr.org/html/9893/webappapis.html#hostinitializeshadowrealm(realm,-context,-o)
// 8.1.6.8 HostInitializeShadowRealm(realm, context, O)
s_main_thread_vm->host_initialize_shadow_realm = [](JS::Realm& realm, NonnullOwnPtr<JS::ExecutionContext> context, JS::ShadowRealm& object) -> JS::ThrowCompletionOr<void> {
// FIXME: 1. Set realm's is global prototype chain mutable to true.https://watpr.org/html/9893/webappapis.html#hostinitializeshadowrealm(realm,-context,-o)h

// 2. Let globalObject be a new ShadowRealmGlobalScope object with realm.
auto global_object = HTML::ShadowRealmGlobalScope::create(realm);

// 3. Let settings be a new synthetic realm settings object that this algorithm will subsequently initialize.
auto settings = HTML::SyntheticRealmSettings {
// 4. Set settings's execution context to context.
.execution_context = move(context),

// 5. Set settings's principal realm to O's associated realm
.principal_realm = object.shape().realm(),

// 6. Set settings's underlying realm to realm.
.underlying_realm = realm,

// 7. Set settings's module map to a new module map, initially empty.
.module_map = realm.heap().allocate<HTML::ModuleMap>(realm),
};

// 8. Set realm.[[HostDefined]] to settings.
realm.set_host_defined(make<Bindings::SyntheticHostDefined>(move(settings)));

// 9. Set realm.[[GlobalObject]] to globalObject.
realm.set_global_object(global_object);

// 10. Set realm.[[GlobalEnv]] to NewGlobalEnvironment(globalObject, globalObject).
realm.set_global_environment(realm.vm().heap().allocate_without_realm<JS::GlobalEnvironment>(global_object, global_object));

// 11. Perform ? SetDefaultGlobalBindings(realm).
set_default_global_bindings(realm);

// 12. Return NormalCompletion(unused).
return {};
};

s_main_thread_vm->host_unrecognized_date_string = [](StringView date) {
dbgln("Unable to parse date string: \"{}\"", date);
};
Expand Down

0 comments on commit 5cda02c

Please sign in to comment.