tc39 / ecma262

Status, process, and documents for ECMA-262
https://tc39.es/ecma262/
Other
15k stars 1.28k forks source link

Spec convention for branding #354

Open domenic opened 8 years ago

domenic commented 8 years ago

As we write more Ecmaspeak specs (Streams, 402, Loader), we find the way that ES does branding a bit onerous and opaque. That is, it picks a privileged internal slot and says "if you have this internal slot, you can pass go."

I propose the following instead:

Potential variant: use a small badge in the heading of the method/abstract op, like streams does for throw/nothrow, like brandcheck(Map).

Does this sound interesting? If so I could work on a PR, because streams is getting really sick of defining IsStreamWhatever(x) abstract ops and repeating the boilerplate everywhere. Having ES lead the way would be great.

allenwb commented 8 years ago

We intentionally avoiding any "branding" language in the ES6 spec. because the precious use of [[Class]] as a branding mechanism had been too broadly assumed to imply things other than what was actually required by the specification. And somebody thought it was something that actually had to exist as a string value or tried to misuse it in various ways.

Generally, all that we want is to require with the replacement language is that that specified functions that depend upon specific object-level encodings of internal slot data throw an error when applied to objects that do not encode those internal slots.

Another way to describe the [[MapData]] requirement might be to say something like "is an object that was successfully allocated and initialized by invoking the [[Construct]] internal method of a built-in Map constructor" (but can't say "the Map constructor" because of multiple Realms).

I'm not particularly attached to the ES6 language, but I think we should avoid any language that implies anything more than "an object that meets the requirements of this method".

domenic commented 8 years ago

That makes sense. I'd be happy to spell it as HasInternalSlotsOf(o, Class) / RequireInternalSlotsOf or WasConstructedWith(o, Class) / RequireConstructedWith. Would that address your concern?

allenwb commented 8 years ago

I'd probably prefer either of the first two. With WasConstructedWith somebody might misinterpret it to preclude subclass instances even if they had the required slots

zenparsing commented 8 years ago

FWIW, when writing these kinds of tests, I generally just want to say something like:

  1. Assert: generator is an AsyncGenerator instance.

And have that statement be equivalent to saying that the object has all of the internal slots which are associated with (in this case) AsyncGenerator.

ljharb commented 8 years ago

"Perform ? RequireInternalSlotsOf(generator, AsyncGenerator)" or "Perform ! RequireInternalSlotsOf(generator, AsyncGenerator)" (for the assert form) seems like it would work just fine - I think there's lots of places in the spec this construct would be useful.

allenwb commented 8 years ago

@ljharb If don't have any problems with that abstract operation name. But what sort of value is the second argument? Presumably instances of a constructor. But no all constructors have global names. And note that constructor functions can them selves have unique internal slots. Perhaps a section number reference is what you need.

ljharb commented 8 years ago

Yeah that's a good point - I more find value in the ability to concisely repeat these assertions without having to repeat the internal slot names. I'm not attached to the abstract operation name.

annevk commented 8 years ago

A non-require version would be great for the structured cloning algorithm, which does a ton of branching based on potential internal slots.