You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Immediately-constructed class expression loses its builtin parent edge: new (class extends Event/EventTarget {})() is parentless #6336
An immediately-constructed class expression — new (class extends Base {})() — never registers its Subclass → Base edge in the class registry when Base is a builtin. The instance comes out parentless: instanceof Base is false, and every inherited native method/field reads as undefined.
The same class expression works fine as soon as it's bound to a name first, which is what makes this a registration-timing hole rather than a class-expression hole.
Repro
// ── builtin parent, immediately constructed: BROKEN ──constev=new(classextendsEvent{})("tick");console.log(evinstanceofEvent,ev.type);// perry: false undefined | node: true tickconstet=new(classextendsEventTarget{})();console.log(etinstanceofEventTarget);// perry: false | node: trueconsole.log(typeofet.addEventListener);// perry: undefined | node: functionet.addEventListener("q",()=>{});// perry: TypeError: value is not a function// ── same shape, USER parent: works ──classBase{hello(){return"hi";}}constp=new(classextendsBase{})();console.log(pinstanceofBase,typeofp.hello);// perry: true function | node: true function// ── builtin parent, bound to a const first: works ──constK=classextendsEventTarget{};console.log(newK()instanceofEventTarget);// perry: true | node: true
Also affected, and worth noting because it's a different symptom of the same area:
constE2=classextendsEvent{};newE2("x");// perry: TypeError: Event is not a function
Expected
All of the above match node --experimental-strip-types: instanceof is true and the inherited surface resolves.
The registry edge for a builtin parent is normally wired at class-definition time by js_register_class_parent_dynamic, which resolves the parent through global_builtin_constructor_class_id (crates/perry-runtime/src/object/instanceof.rs). For a class expression in callee position (new (class … {})()) that definition-time registration appears never to run, so get_parent_class_id(subclass_id) returns nothing and every chain walk (class_chain_is_event_target, is_event_instance, instanceof) bails.
Consequence: any feature that identifies a receiver by class chain silently degrades to "not a member of the base" for this shape. That's the shared failure mode behind both the Event and EventTarget rows above.
Found while verifying a review finding on #6311 (EventTarget subclassing); filing separately rather than growing that PR's scope, since it equally affects Event on main.
Activity
fix(codegen): resolve a native base class by class CHAIN, not by exte…