A class whose parent is a runtime value (a member expression such as ns.Base, or a local alias) calls the parent constructor from super() with new.target === undefined. So a parent constructor that builds its own receiver (return setup(Object.create(new.target.prototype))) throws, and the subclass never gets constructed. whatwg-url's generated wrappers use this pattern. The pattern is common in any webidl2js output.
Repro (no packages)
const ns: any = {
Base: class Base {
constructor() { console.log("new.target is", typeof new.target, new.target === undefined ? "undefined" : new.target.name); }
},
};
class P extends ns.Base {}
new P();
class E extends ns.Base { constructor() { super(); } }
new E();
const Alias = ns.Base;
class L extends Alias {}
new L();
Node 26.5.1:
new.target is function P
new.target is function E
new.target is function L
Perry origin/main 36892b7 (perry-dev, Linux x64, PERRY_NO_AUTO_OPTIMIZE=1, both .ts and .cts):
new.target is undefined undefined
new.target is undefined undefined
new.target is undefined undefined
The dynamic-parent super() goes through js_fetch_or_value_super (perry-runtime/src/object/global_this/fetch_globals.rs). For a closure or class-object parent, that function calls it bound to this without publishing the subclass as new.target. Only the uncallable-builtin arm passes a newTarget.
mongodb's real ConnectionString does not hit this: the parent there is whatwg-url's class from another module, which resolves through a different path. #11146 (#11139) works with it as-is. It does break the same wrapper shape when the class lives in the same module as the subclass.
A class whose parent is a runtime value (a member expression such as
ns.Base, or a local alias) calls the parent constructor fromsuper()withnew.target === undefined. So a parent constructor that builds its own receiver (return setup(Object.create(new.target.prototype))) throws, and the subclass never gets constructed. whatwg-url's generated wrappers use this pattern. The pattern is common in any webidl2js output.Repro (no packages)
Node 26.5.1:
Perry
origin/main36892b7 (perry-dev, Linux x64,PERRY_NO_AUTO_OPTIMIZE=1, both.tsand.cts):The dynamic-parent
super()goes throughjs_fetch_or_value_super(perry-runtime/src/object/global_this/fetch_globals.rs). For a closure or class-object parent, that function calls it bound tothiswithout publishing the subclass asnew.target. Only the uncallable-builtin arm passes a newTarget.mongodb's real
ConnectionStringdoes not hit this: the parent there is whatwg-url's class from another module, which resolves through a different path. #11146 (#11139) works with it as-is. It does break the same wrapper shape when the class lives in the same module as the subclass.