tc39 / proposal-record-tuple

ECMAScript proposal for the Record and Tuple value types. | Stage 2: it will change!
https://tc39.es/proposal-record-tuple/
2.48k stars 62 forks source link

using Records where only Objects are currently permitted: [[Prototype]]? #326

Closed michaelficarra closed 2 years ago

michaelficarra commented 2 years ago

264 is trying to allow records to be interchangeable with objects in more places. Currently, there is a guard at the beginning of all mechanisms that assign a value to an object's [[Prototype]] (such as Object.create and Object.setPrototypeOf) that the value is null or an Object. Do we want to change these guards to permit records to be added to the prototype chain? A workaround currently is to just pass the record through Object() first, as in Object.create(Object(record)).

acutmore commented 2 years ago

Hi @michaelficarra - were you suggesting that the object coercion here be implicit? i.e. Object.create(#{}) would be equivalent to Object.create(Object(#{})), or that records could actual be used as the [[Prototype]] directly?

For the implicit conversion, this is different from the implicit conversions added in #264 where the conversion is internal to the methods. e.g. new Error(msg, #{ cause: v }) and JSON.stringify(v, #["a", "b"]) allows records and tuples as inputs so their internal values can be read/extracted by the algorithms; the converted object is not exposed anywhere.

For allowing records to be used as a [[Prototype]] value, this would be observable and impact anywhere that calls [[GetPrototypeOf]] making it a significant change relative to the other changes in #264. Also considering the most common use of prototypes is to share methods, and records can't contain functions, so it may not prove particular valuable to add this change.

michaelficarra commented 2 years ago

were you suggesting that the object coercion here be implicit?

Yes.

the converted object is not exposed anywhere

That's fair, and I would accept that reasoning.

acutmore commented 2 years ago

Thanks @michaelficarra - I'll close this for now as "converting a record to be used as a prototype should be done explicitly". We can always re-open if discussion prompts.

As a side note, I realized I wasn't sure what would happen for __proto__ in a object literal when set to a non-null primitive. Turns out the spec silently ignores it.

const o = {
  __proto__: 42
};
Object.getPrototypeOf(o) === Object.prototype; // true
Reflect.ownKeys(o); // []