tc39 / proposal-shadowrealm

ECMAScript Proposal, specs, and reference implementation for Realms
https://tc39.es/proposal-shadowrealm/
1.44k stars 67 forks source link

Assert that the global object inside the Shadow Realm is ordinary. #413

Open Ms2ger opened 1 week ago

Ms2ger commented 1 week ago

@mhofman: please let me know if there's any requirements this doesn't capture.

mhofman commented 3 days ago

If this is something we can actually assert, that would work for me. In this case we should likely also assert that the object is extensible and that all own properties are configurable.

I suppose the editor note for HostInitializeShadowRealm also needs updating.

nicolo-ribaudo commented 3 days ago

I don't think an assertion is the right tool here. Assertions are just editorial notes that explicitly state properties are an algorithm that are already true due to the algorithm itself. They are purely informative, and removing all assertions from the spec should not change its meaning.

Instead, we should pass a boolean requireOrdinaryGlobal (or isShadowRealm) to InitializeHostDefinedRealm(), and replace step 12 with

12. If _requireOrginaryGlobal_ is false and the host requires use of an exotic object to serve as realm's global object, then
   a. Let global be such an object created in a host-defined manner.
13. Else,
   a. If the host requires that the global object's prototype is not %Object.prototype%,
      i. Let _globalPrototype_ the object to use as the global object's prototype, created in a host-defined manner.
   b. Else,
       i. Let _globalPrototype_ be _realm_.[[Intrinsics]].[[%Object.prototype%]].
   c. Let _global_ be OrdinaryObjectCreate(_globalPrototype_).

By doing so we are actually requiring the host to create an ordinary object, rather than just asserting that it does without enforcing it, and we still allow the global to inherit from EventTarget.

nicolo-ribaudo commented 3 days ago

Actually, looking at the HTML integration this would be easier for layering:

12. If the host requires use of a custom object to serve as _realm_'s global object, then
    a. If _requireOrdinaryGlobal_ is **false**, let _global_ be an object created for such purpose in a host-defined manner.
    b. Else, let _global_ be an ordinary object created for such purpose in a host-defined manner.
14. Else,
   c. Let _global_ be OrdinaryObjectCreate(_realm_.[[Intrinsics]].[[%Object.prototype%]]).

Also, note that the current proposed HTML integration defines the ShadowRealm global to behave exactly like an ordinary object, but it's not an ordinary object. Specifically, the [[SetPrototypeOf]] implementation is exotic and defined at https://webidl.spec.whatwg.org/#platform-object-setprototypeof. It however happens to behave exactly as the ordinary one, because is global prototype chain mutable returns true.

The reason this layering is simpler is because it's much easier for HTML to create a new object (for which it can use the WebIDL machinery) rather than to define new properties on an existing one.

mhofman commented 2 days ago

the current proposed HTML integration defines the ShadowRealm global to behave exactly like an ordinary object, but it's not an ordinary object.

As I mentioned in #411, that's fine:

To clarify, while the host must not be allowed to observably use an exotic object, that requirement does not prevent an implementation to actually use an exotic object as global object, as long as the exotic behavior is observably indistinguishable from a regular object behavior.

The spec deals in observable behaviors. An implementation is always free to deviate from the letter of the spec as long as JS programs can never observe the deviation.

Assertions are just editorial notes that explicitly state properties are an algorithm that are already true due to the algorithm itself. They are purely informative, and removing all assertions from the spec should not change its meaning.

How do you recommend we constrain hosts on only adding configurable properties to the global object? In general how do we enforce invariants on host hooks?

nicolo-ribaudo commented 2 days ago

How do you recommend we constrain hosts on only adding configurable properties to the global object? In general how do we enforce invariants on host hooks?

By not putting the "Assert:" annotation in front of it :stuck_out_tongue: Normally for host hooks we say "the host must do X, Y and Z" rather than not stating requirements on what the host can do and then assert that when we previously called into the host it did X, Y and Z.

Ms2ger commented 1 day ago

Also, note that the current proposed HTML integration defines the ShadowRealm global to behave exactly like an ordinary object, but it's not an ordinary object. Specifically, the [[SetPrototypeOf]] implementation is exotic and defined at https://webidl.spec.whatwg.org/#platform-object-setprototypeof. It however happens to behave exactly as the ordinary one, because is global prototype chain mutable returns true.

Fwiw, this is fixed in https://github.com/whatwg/webidl/pull/1437