diff --git a/src/js_parser.zig b/src/js_parser.zig index df5c842940554..3c706b1bb248d 100644 --- a/src/js_parser.zig +++ b/src/js_parser.zig @@ -18146,10 +18146,20 @@ fn NewParser_( data.default_name = createDefaultName(p, stmt.loc) catch unreachable; } + // We only inject a name into classes when there is a decorator + if (class.class.has_decorators) { + if (class.class.class_name == null or + class.class.class_name.?.ref == null) + { + class.class.class_name = data.default_name; + } + } + + // This is to handle TS decorators, mostly. var class_stmts = p.lowerClass(.{ .stmt = s2 }); + std.debug.assert(class_stmts[0].data == .s_class); if (class_stmts.len > 1) { - std.debug.assert(class_stmts[0].data == .s_class); data.value.stmt = class_stmts[0]; stmts.append(stmt.*) catch {}; stmts.appendSlice(class_stmts[1..]) catch {}; diff --git a/test/transpiler/decorator-export-default-class-fixture-anon.ts b/test/transpiler/decorator-export-default-class-fixture-anon.ts new file mode 100644 index 0000000000000..bf81afa2c27c0 --- /dev/null +++ b/test/transpiler/decorator-export-default-class-fixture-anon.ts @@ -0,0 +1,10 @@ +function decorator(target: any, propertyKey: any) { + target[propertyKey + "decorated"] = true; +} + +export default class { + @decorator + method() { + return 42; + } +} diff --git a/test/transpiler/decorators.test.ts b/test/transpiler/decorators.test.ts index ad09809308c5f..100ecc3bc9d43 100644 --- a/test/transpiler/decorators.test.ts +++ b/test/transpiler/decorators.test.ts @@ -1,6 +1,7 @@ // @ts-nocheck import { test, expect, describe } from "bun:test"; import DecoratedClass from "./decorator-export-default-class-fixture"; +import DecoratedAnonClass from "./decorator-export-default-class-fixture-anon"; test("decorator order of evaluation", () => { let counter = 0; @@ -990,6 +991,10 @@ describe("constructor statements", () => { }); }); -test("export default class works", () => { +test("export default class Named works", () => { expect(new DecoratedClass()["methoddecorated"]).toBe(true); }); + +test("export default class works (anonymous name)", () => { + expect(new DecoratedAnonClass()["methoddecorated"]).toBe(true); +}); diff --git a/test/transpiler/export-default-with-static-initializer.js b/test/transpiler/export-default-with-static-initializer.js new file mode 100644 index 0000000000000..2d390b0082d64 --- /dev/null +++ b/test/transpiler/export-default-with-static-initializer.js @@ -0,0 +1,5 @@ +export default class { + static { + this.boop = "boop"; + } +} diff --git a/test/transpiler/export-default.test.js b/test/transpiler/export-default.test.js new file mode 100644 index 0000000000000..e557ffe00cddd --- /dev/null +++ b/test/transpiler/export-default.test.js @@ -0,0 +1,6 @@ +import WithStatic from "./export-default-with-static-initializer"; +import { test, expect } from "bun:test"; + +test("static initializer", () => { + expect(WithStatic.boop).toBe("boop"); +});