codehag / documenting-invariants

Proposal to document design invariants in TC39

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Invariant: Primitives

ljharb opened this issue · comments

  • A primitive is any x where Object(x) !== x (code on the web relies on this to branch between objects and primitives)
  • null and undefined are "nullish", and are special in that they are not object-coercible (code on the web relies on this to branch on null/undefined, as well as to avoid exceptions from navigating into a value)
  • every non-nullish primitive x can be "boxed" or "wrapped" in an object with Object(x) (code on the web relies on this to be able to determine primitiveness/objectness, and to make mutable wrappers of unboxable primitives to decorate with metadata)
  • every such boxed primitive ends up with a [[Prototype]] in the current realm (ie, "this realm"'s Boolean.prototype, for Object(true), etc) (this ensures that passing a primitive across realms/membranes does not expose the sending side's prototype objects)
  • every such boxed primitive provides a mechanism - a prototype method or a constructor method (often .valueOf on the prototype) to determine:
  • both of the previous mechanisms use internal slots, and thus work across realms (code on the web relies on doing this with iframes)
commented

Sorry for the late reply. What is the purpose for each listed point? Can you add the motivations of each?

Sure, i’ll update it later today - but they’re an invariant regardless of the motivation, because they happen to be true.

commented

hmm. The goal of this document is not to record what is currently true about the language, but what is defended. A defense should have a motivation, specifically, why something should not change.

Per the readme

Part of the work that we do at TC39 is ensuring that as the language changes, certain properties of the language remain.

but, i believe what you posted above is probably stuff that we want to protect. Part of the process with invariants will also be deprecating them when a motivation no longer holds true, so having it present is important.

Not everything here necessarily needs to be "always true". it can also be points that are upheld in committee as things that we should deprecate in our practice or not repeat. Those are also worth documenting, along with their motivation.

The list of what invariants are defended is a subset of the broader list of invariants - we have to document the latter before we can achieve consensus on the former, no?

I've updated the OP with some parentheticals to provide motivation.

commented

Reading through, it seems like your concern here is around the behavior of boxing values (and testing for "primitiveness"), not the behavior of primitives themselves (which I thought was the initial goal of this post). Maybe that is the invariant you are trying to point out here? (i think i misunderstood the intention of your original post when I asked you for motivations for each.)

This might be multiple items still. It wasn't immediately clear to me what this should be (a single post or multiple).

we have to document the latter before we can achieve consensus on the former, no?

If we do this exhaustively we will have a reverse engineered copy of the specification, along with its entire error space. I think this will end up drowning out the goal here, which is to record what is not written down but is treated as though it is, namely -- why we don't want to change certain properties of the language. For example, the coercion properties you list in bullet 2 are written down (https://tc39.es/ecma262/#sec-toobject), so maybe it doesn't make sense to write that down again in isolation -- but, as part of a description of "we want to enable boxing" this makes sense as supplementary info.

commented

I've created issue templates to hopefully make this process a bit easier.

If i recall, i filed this issue in response to some Record and Tuple discussions.

My hope is that “things that are currently true, and ideally will forever remain so” are eventually documented such that we never change them in the future, so that arbitrary delegates don’t have to be present in order to maintain those invariants.

commented

My hope is that “things that are currently true, and ideally will forever remain so” are eventually documented such that we never change them in the future, so that arbitrary delegates don’t have to be present in order to maintain those invariants.

thats precisely the goal here! sorry if my questions here have been frustrating. If you are happy with this being split into two parts

  1. Ability to detect primitives via the object constructor when called as a function
  2. Ability to box primitives

then I will go ahead and post it. Does that work ?

Sure, sounds great!