Summary
Object.create(proto, descriptors?) produces an object that is not
instanceof the class whose prototype it was given, even though property
reads and prototype-getter dispatch through the chain work correctly.
Repro
class C { x = 1; }
const a = new C();
console.log(Object.create(Object.getPrototypeOf(a)) instanceof C); // node: true, perry: false
console.log(a instanceof C); // both: true
node: true / true
perry: false / true
The descriptors form diverges the same way:
class TypeLiteral { _tag = "TypeLiteral"; }
const ast = new TypeLiteral();
const clone = Object.create(Object.getPrototypeOf(ast), Object.getOwnPropertyDescriptors(ast));
clone._tag; // perry: "TypeLiteral" ✓ (own prop survives)
clone instanceof TypeLiteral; // node: true, perry: false
Root cause (suspected)
Per #809, Object.create(proto) wires the prototype by allocating a synthetic
class_id mapped into CLASS_PROTOTYPE_OBJECTS and stamping the new object
with it (so missing-prop lookups walk proto). But instanceof matches on the
class-id chain, and a synthetic id isn't linked to the original class's id, so
js_instanceof_dynamic reports false. The property/getter chain works (it walks
the prototype object) while instanceof (which keys off class-id ancestry) does
not.
Why it matters
effect's SchemaAST.annotations clones AST nodes via
Object.create(Object.getPrototypeOf(ast), Object.getOwnPropertyDescriptors(ast)).
A possible contributor to the remaining _tag-of-undefined Schema-init blocker
(#1758) if any downstream path branches on instanceof of a cloned AST node —
though effect's primary dispatch is _tag-based, so this may be orthogonal.
Filing as a standalone, minimal, verified gap.
Found while landing #1804 (Object.getOwnPropertyDescriptors). Refs #1758, #809.
Summary
Object.create(proto, descriptors?)produces an object that is notinstanceofthe class whose prototype it was given, even though propertyreads and prototype-getter dispatch through the chain work correctly.
Repro
The descriptors form diverges the same way:
Root cause (suspected)
Per #809,
Object.create(proto)wires the prototype by allocating a syntheticclass_idmapped intoCLASS_PROTOTYPE_OBJECTSand stamping the new objectwith it (so missing-prop lookups walk
proto). Butinstanceofmatches on theclass-id chain, and a synthetic id isn't linked to the original class's id, so
js_instanceof_dynamicreports false. The property/getter chain works (it walksthe prototype object) while
instanceof(which keys off class-id ancestry) doesnot.
Why it matters
effect's
SchemaAST.annotationsclones AST nodes viaObject.create(Object.getPrototypeOf(ast), Object.getOwnPropertyDescriptors(ast)).A possible contributor to the remaining
_tag-of-undefined Schema-init blocker(#1758) if any downstream path branches on
instanceofof a cloned AST node —though effect's primary dispatch is
_tag-based, so this may be orthogonal.Filing as a standalone, minimal, verified gap.
Found while landing #1804 (Object.getOwnPropertyDescriptors). Refs #1758, #809.