Skip to content

Crash: class-level decorator on an anonymous class panics during ES decorator emit #63962

Description

🔎 Search Terms

anonymous class decorator crash, "A class declaration that is not a default export must have a name", esDecorator visitClassDeclaration, ChildIsDecorated, typescript-go#3891, DecSoft Utils (@dec) class {}

🕗 Version & Regression Information

  • This is a crash
  • Also crashes TypeScript 6.0.3 (JS) with the same assert.
  • Reproduced on 7.1.0-dev (main) with emit and --target es2022 (also es5 / es2015 / es2021). --target esnext and --noEmit do not crash.

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=6.0.0-dev.20260416#code/CYUwxgNghgTiAEA3W9RgFzygOwJ4G4AoAATUMigGdL4BvQgXyA

💻 Code

declare var dec: any;
@dec
class {
}

🙁 Actual behavior

panic: Debug failure. False expression: A class declaration that is not a default export must have a name. [recovered, repanicked]

goroutine 107 [running]:
sync.(*WaitGroup).Go.func1.1()
        sync/waitgroup.go:251 +0x48
panic({0x105ea58e0?, 0x11e74b992390?})
        runtime/panic.go:860 +0x12c
github.com/microsoft/TypeScript/tsc/internal/debug.Fail(...)
        github.com/microsoft/TypeScript/tsc/internal/debug/debug.go:14
github.com/microsoft/TypeScript/tsc/internal/debug.assertSlow(...)
        github.com/microsoft/TypeScript/tsc/internal/debug/debug.go:60 +0x5c
github.com/microsoft/TypeScript/tsc/internal/debug.Assert(...)
        github.com/microsoft/TypeScript/tsc/internal/debug/debug.go:49
github.com/microsoft/TypeScript/tsc/internal/transformers/estransforms.(*esDecoratorTransformer).visitClassDeclaration(...)
        github.com/microsoft/TypeScript/tsc/internal/transformers/estransforms/esdecorator.go:1071 +0x5ec
github.com/microsoft/TypeScript/tsc/internal/transformers/estransforms.(*esDecoratorTransformer).visit(...)
        github.com/microsoft/TypeScript/tsc/internal/transformers/estransforms/esdecorator.go:318 +0x35c
github.com/microsoft/TypeScript/tsc/internal/ast.(*NodeVisitor).VisitSlice(...)
        github.com/microsoft/TypeScript/tsc/internal/ast/visitor.go:148 +0xa0
github.com/microsoft/TypeScript/tsc/internal/ast.(*NodeVisitor).VisitNodes(...)
        github.com/microsoft/TypeScript/tsc/internal/ast/visitor.go:99 +0x3c
github.com/microsoft/TypeScript/tsc/internal/printer.(*EmitContext).VisitVariableEnvironment(...)
        github.com/microsoft/TypeScript/tsc/internal/printer/emitcontext.go:796 +0x17c
... 42 lines truncated ...
github.com/microsoft/TypeScript/tsc/internal/compiler.(*emitter).emitJSFile(...)
        github.com/microsoft/TypeScript/tsc/internal/compiler/emitter.go:200 +0x198
github.com/microsoft/TypeScript/tsc/internal/compiler.(*emitter).emit(...)
        github.com/microsoft/TypeScript/tsc/internal/compiler/emitter.go:50 +0xec
github.com/microsoft/TypeScript/tsc/internal/compiler.(*Program).Emit.func2()
        github.com/microsoft/TypeScript/tsc/internal/compiler/program.go:1851 +0x1c0

🙂 Expected behavior

The compiler should not crash 🙂

Additional information about the issue

Disclosure: This crash was found with a custom mutation fuzzer and AI assistance (Kimi K3). The input was minimized and then verified by hand against TypeScript 7.1.0-dev (main) and TypeScript 6.0.3.

This appears to be a leftover of the fix for typescript-go#3891 / typescript-go#3926 (commit 710928bdf2). That fix covers an anonymous class with a member decorator (class { @x m() {} }). It does not cover a class-level decorator (@dec class {}).

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions