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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions