-
Notifications
You must be signed in to change notification settings - Fork 79
Description
What is the Problem Being Solved?
Currently harden
is defined as transitively freezing the object, its properties (whether data values, or accessor functions), and each of their prototypes. This can be considered as a new integrity level.
However we would like to attach new behavior to this integrity level:
- Opting hardened objects out of the override mistake (Propose to tc39 without override mistake #105)
- Preventing hardened objects from getting stamped with private fields through return override (GC sensing possible with custom WeakMap/Set Agoric/agoric-sdk#5000)
Currently JavaScript supports 2 integrity levels: Sealed and Frozen. The specification defines those as a non-extensible objects (which is specified as a flag on the object) plus checks on the own property descriptors (non-configurable only for sealed, and also non-writable for data properties of frozen objects).
The specification does not itself check for the integrity level state of an object outside of the 2 intrinsics Object.isSealed
and Object.isFrozen
. While these checks can be memoized / cached for regular objects, they are observable by Proxy exotic objects (the traps are called during the check).
Description of the Design
To make harden efficient, and to allow the spec to check an object for its hardened state as a side effect of other operations, we would like to make the hardened integrity level an explicitly cached state of objects, and disallow exotic proxy objects from observing when that state is checked.
This state can only be applied atomically to a set of objects once they all have been transitively frozen.
Open questions
- Should an object that satisfies all the transitive frozen conditions pass an
isHardened()
predicate?- If no, is it ok if an object is considered hardened only if
harden()
was applied on it (directly or indirectly) - If yes, would it be acceptable for the object to gain the hardened state as a side effect of such a check?
- If no, is it ok if an object is considered hardened only if
- Should the target of a proxy be part of the set of objects being put in a hardened state
- By the proxy invariants, the target has to be frozen if the proxy is frozen, and its own property descriptors have to be the same as the ones returned by the proxy, both for data values and for accessors.
- Note: while the object invariants do not require the stability of the accessor values in the own property descriptor for non-configurable properties, the own property built-ins do not allow those to change over time. In particular, the proxy steps enforce the stability through the target object.
- By the proxy invariants, the target has to be frozen if the proxy is frozen, and its own property descriptors have to be the same as the ones returned by the proxy, both for data values and for accessors.
- Should a proxy be able to deny the application of the hardened state if it allowed a frozen state
- If the target is itself hardened (see above), it would be the only way the proxy can deny the hardening of the target
- Given the invariants enforcement of proxy, a hardened proxy can only answer own property related traps according to the target, throw or cause the proxy steps to throw.
- How is a relaxation of hardened semantics described in Terminate CapTP in non-hardened Realm without SES shim #1686 compatible with a cached integrity level for harden if the definition of an hardened level post-lockdown is stronger than pre-lockdown (the prototypes must pass
isHardened()
check post-lockdown, but not before). Reverting integrity levels during lockdown does not seem appropriate.- One solution may be for pre-lockdown
harden()
to build a weak list of the prototypes encountered, and havelockdown()
fail if not all prototypes have been hardened by then to ensure that lockdown does not rollback the claimed integrity level. More details in Terminate CapTP in non-hardened Realm without SES shim #1686 (comment)
- One solution may be for pre-lockdown