LibJS: Initialize ShadowRealm internal slots through setters

This allows us to align our implementation in the same order as the
specification.

No functional change with the current implementation of this AO.

However, this change is required in order to correctly implement a
proposed update of the shadow realm proposal for integration with
the HTML spec host bindings in order to give the ShadowRealm
object the correct 'intrinsic' realm.

This is due to that proposed change adding a step which manipulates the
currently executing Javascript execution context, making the ordering
important.
This commit is contained in:
Shannon Booth 2024-10-23 17:27:20 +13:00 committed by Andrew Kaster
commit 0ec8af5b70
Notes: github-actions[bot] 2024-10-23 17:31:05 +00:00
3 changed files with 17 additions and 11 deletions

View file

@ -22,10 +22,8 @@ namespace JS {
JS_DEFINE_ALLOCATOR(ShadowRealm);
ShadowRealm::ShadowRealm(Realm& shadow_realm, NonnullOwnPtr<ExecutionContext> execution_context, Object& prototype)
ShadowRealm::ShadowRealm(Object& prototype)
: Object(ConstructWithPrototypeTag::Tag, prototype)
, m_shadow_realm(shadow_realm)
, m_execution_context(move(execution_context))
{
}

View file

@ -20,19 +20,22 @@ class ShadowRealm final : public Object {
public:
virtual ~ShadowRealm() override = default;
[[nodiscard]] Realm const& shadow_realm() const { return m_shadow_realm; }
[[nodiscard]] Realm& shadow_realm() { return m_shadow_realm; }
[[nodiscard]] Realm const& shadow_realm() const { return *m_shadow_realm; }
[[nodiscard]] Realm& shadow_realm() { return *m_shadow_realm; }
void set_shadow_realm(NonnullGCPtr<Realm> realm) { m_shadow_realm = realm; }
[[nodiscard]] ExecutionContext const& execution_context() const { return *m_execution_context; }
[[nodiscard]] ExecutionContext& execution_context() { return *m_execution_context; }
void set_execution_context(NonnullOwnPtr<ExecutionContext> context) { m_execution_context = move(context); }
private:
ShadowRealm(Realm&, NonnullOwnPtr<ExecutionContext>, Object& prototype);
ShadowRealm(Object& prototype);
virtual void visit_edges(Visitor&) override;
// 3.5 Properties of ShadowRealm Instances, https://tc39.es/proposal-shadowrealm/#sec-properties-of-shadowrealm-instances
NonnullGCPtr<Realm> m_shadow_realm; // [[ShadowRealm]]
NonnullOwnPtr<ExecutionContext> m_execution_context; // [[ExecutionContext]]
GCPtr<Realm> m_shadow_realm; // [[ShadowRealm]]
OwnPtr<ExecutionContext> m_execution_context; // [[ExecutionContext]]
};
ThrowCompletionOr<void> copy_name_and_length(VM&, FunctionObject& function, FunctionObject& target, Optional<StringView> prefix = {}, Optional<unsigned> arg_count = {});

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021-2023, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2024, Shannon Booth <shannon@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -43,9 +44,15 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ShadowRealmConstructor::construct(Functi
{
auto& vm = this->vm();
// 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ShadowRealm.prototype%", « [[ShadowRealm]], [[ExecutionContext]] »).
auto object = TRY(ordinary_create_from_constructor<ShadowRealm>(vm, new_target, &Intrinsics::shadow_realm_prototype));
// 3. Let realmRec be CreateRealm().
auto realm = MUST_OR_THROW_OOM(Realm::create(vm));
// 4. Set O.[[ShadowRealm]] to realmRec.
object->set_shadow_realm(realm);
// 5. Let context be a new execution context.
auto context = ExecutionContext::create();
@ -58,10 +65,8 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ShadowRealmConstructor::construct(Functi
// 8. Set the ScriptOrModule of context to null.
// Note: This is already the default value.
// 2. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%ShadowRealm.prototype%", « [[ShadowRealm]], [[ExecutionContext]] »).
// 4. Set O.[[ShadowRealm]] to realmRec.
// 9. Set O.[[ExecutionContext]] to context.
auto object = TRY(ordinary_create_from_constructor<ShadowRealm>(vm, new_target, &Intrinsics::shadow_realm_prototype, *realm, move(context)));
object->set_execution_context(move(context));
// 10. Perform ? SetRealmGlobalObject(realmRec, undefined, undefined).
realm->set_global_object(nullptr, nullptr);