Repro (two files)
lib.ts
export class Decl { m() { return 1; } }
export let Expr = class { m() { return 2; } };
export const Anon = class Named { m() { return 3; } };
export function localProbe() {
return [typeof Decl.prototype, typeof Expr.prototype, typeof Anon.prototype].join(",");
}
main.ts
import { Decl, Expr, Anon, localProbe } from "./lib";
console.log("in-defining-module=" + localProbe());
console.log("importer-Decl=" + typeof Decl.prototype);
console.log("importer-Expr=" + typeof Expr.prototype);
console.log("importer-Anon=" + typeof Anon.prototype);
node : in-defining-module=object,object,object
importer-Decl=object importer-Expr=object importer-Anon=object
perry: in-defining-module=object,object,object
importer-Decl=object importer-Expr=undefined importer-Anon=undefined
Scope
| shape |
read in defining module |
read in importing module |
export class Decl {} (declaration) |
ok |
ok |
export let Expr = class {} (expression) |
ok |
undefined |
export const Anon = class Named {} (named expression) |
ok |
undefined |
So it is specifically a class expression, read across a module boundary. The same read inside the defining module is correct, and the class is otherwise fully functional through the importer — new Decl().m is a function, Object.getPrototypeOf(instance) is an object, instances work. It is the .prototype property access on the imported binding that answers undefined.
Not a regression: identical on 83754818e (#9242) and a03be729c (#9336).
Why this one matters
This is the shape at the heart of #9341. The diagnostic there shows cc --help dying on Object.defineProperty(undefined, "getContentType", …), and the undefined is z in axios:
kU6 = class { … static accessor(q){ … let z = this.prototype; … xp5(z, A) … } … };
kU6.accessor(["Content-Type", …]);
sH = kU6;
kU6 is a class expression, which is exactly the shape above. A reduction of that accessor across two modules reproduces prototype=undefined on both the green and the broken build — so this bug is the machinery #9341's regression is landing on, even though the trigger for when the bundle takes this path is a separate change inside 83754818e..main.
Three other .prototype defects turned up in the same sweep, all pre-existing: #9365 (a statically-named o.prototype = v store silently dropped after a computed-key write), #9362 (util.inherits with a class ctor), #9364 (SIGSEGV on a chained class D extends <param> factory). Taken together, .prototype handling has several ordinary shapes that silently answer undefined, and silence is what makes them expensive: #9341 cost three wrong attributions and two unnecessary reverts before anyone saw the receiver.
Repro (two files)
lib.tsmain.tsScope
export class Decl {}(declaration)export let Expr = class {}(expression)undefinedexport const Anon = class Named {}(named expression)undefinedSo it is specifically a class expression, read across a module boundary. The same read inside the defining module is correct, and the class is otherwise fully functional through the importer —
new Decl().mis a function,Object.getPrototypeOf(instance)is an object, instances work. It is the.prototypeproperty access on the imported binding that answersundefined.Not a regression: identical on
83754818e(#9242) anda03be729c(#9336).Why this one matters
This is the shape at the heart of #9341. The diagnostic there shows
cc --helpdying onObject.defineProperty(undefined, "getContentType", …), and theundefinediszin axios:kU6is a class expression, which is exactly the shape above. A reduction of that accessor across two modules reproducesprototype=undefinedon both the green and the broken build — so this bug is the machinery #9341's regression is landing on, even though the trigger for when the bundle takes this path is a separate change inside83754818e..main.Three other
.prototypedefects turned up in the same sweep, all pre-existing: #9365 (a statically-namedo.prototype = vstore silently dropped after a computed-key write), #9362 (util.inheritswith a class ctor), #9364 (SIGSEGV on a chainedclass D extends <param>factory). Taken together,.prototypehandling has several ordinary shapes that silently answerundefined, and silence is what makes them expensive: #9341 cost three wrong attributions and two unnecessary reverts before anyone saw the receiver.