Skip to content

Property decorators receive the CLASS where the spec hands Class.prototype — compensated by C.constructor === C #9467

Description

@proggeramlug

Two divergences that cancel, discovered when fixing #9404 broke NestJS decorator metadata (PR #9465 has the story):

  1. A property decorator on an instance member receives the class itself as target; the spec (and node with experimentalDecorators) hands Class.prototype.
  2. C.constructor === C in perry; node says C.constructor === Function (a constructor object's own chain does not carry a constructor back-edge to itself).

NestJS-style code does Reflect.defineMetadata(k, v, target.constructor) — with both divergences it lands metadata on C exactly as node does with target = C.prototype, target.constructor = C. Fixing either divergence alone breaks decorator metadata; the parity suite's test_decorators_nest_common_canary and test_decorators_legacy_property_metadata are the tripwires (they caught the first attempted #9404 fix within one suite run).

The cancellation is now documented in code at the point that depends on it (the class_instance_has_member gate in resolve_proto_chain_field), so the next person who fixes one half has a pointer to the other.

Fix shape

Both halves in one change: hand decorators the reflective C.prototype object, and stop mirroring constructor as an own field answering C on the constructor side. Then run the decorator canaries plus fixtures asserting C.constructor === Function, p.constructor === C for an instance, and Reflect.getMetadata round-trips through both target and target.constructor.

Found while fixing #9404 (PR #9465).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions