Skip to content

perry: Object.create(proto) result is not instanceof the prototype's class (class-id chain not linked) #1805

Description

@proggeramlug

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regression

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions