From 51fed26ac6fb2cbc61ec269c1bb0662417cfa410 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Sat, 3 Oct 2026 23:30:22 +0200 Subject: [PATCH] Fix crash in decorator metadata emit for decorated object literal members --- .../transformers/tstransforms/metadata.go | 10 ++++ ...adataObjectLiteralMethodNoCrash.errors.txt | 30 ++++++++++++ ...ratorMetadataObjectLiteralMethodNoCrash.js | 49 +++++++++++++++++++ ...MetadataObjectLiteralMethodNoCrash.symbols | 44 +++++++++++++++++ ...orMetadataObjectLiteralMethodNoCrash.types | 47 ++++++++++++++++++ ...ratorMetadataObjectLiteralMethodNoCrash.ts | 20 ++++++++ 6 files changed, 200 insertions(+) create mode 100644 tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.js create mode 100644 tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.types create mode 100644 tsc/testdata/tests/cases/compiler/decoratorMetadataObjectLiteralMethodNoCrash.ts diff --git a/tsc/internal/transformers/tstransforms/metadata.go b/tsc/internal/transformers/tstransforms/metadata.go index 8d354747f080e..44f3ed5629a30 100644 --- a/tsc/internal/transformers/tstransforms/metadata.go +++ b/tsc/internal/transformers/tstransforms/metadata.go @@ -41,6 +41,8 @@ func (tx *MetadataTransformer) visit(node *ast.Node) *ast.Node { return tx.visitClassDeclaration(node.AsClassDeclaration()) case ast.KindClassExpression: return tx.visitClassExpression(node.AsClassExpression()) + case ast.KindObjectLiteralExpression: + return tx.visitObjectLiteralExpression(node) case ast.KindPropertyDeclaration: return tx.visitPropertyDeclaration(node.AsPropertyDeclaration()) case ast.KindMethodDeclaration: @@ -76,6 +78,14 @@ func (tx *MetadataTransformer) setCurrentLexicalScope(node *ast.Node) { tx.currentLexicalScope = node } +func (tx *MetadataTransformer) visitObjectLiteralExpression(node *ast.Node) *ast.Node { + oldParent := tx.parent + tx.parent = node + defer tx.setParent(oldParent) + + return tx.Visitor().VisitEachChild(node) +} + func (tx *MetadataTransformer) visitClassExpression(node *ast.ClassExpression) *ast.Node { oldParent := tx.parent tx.parent = node.AsNode() diff --git a/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.errors.txt b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.errors.txt new file mode 100644 index 0000000000000..7a56e54f6f7ff --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.errors.txt @@ -0,0 +1,30 @@ +decoratorMetadataObjectLiteralMethodNoCrash.ts(4,7): error TS1206: Decorators are not valid here. +decoratorMetadataObjectLiteralMethodNoCrash.ts(13,15): error TS1206: Decorators are not valid here. +decoratorMetadataObjectLiteralMethodNoCrash.ts(14,19): error TS1206: Decorators are not valid here. + + +==== decoratorMetadataObjectLiteralMethodNoCrash.ts (3 errors) ==== + declare function dec(...args: any[]): any; + + const o = { + m(@dec x: string) {} + ~ +!!! error TS1206: Decorators are not valid here. + }; + + class C { + @dec + prop!: number; + + method() { + return { + m(@dec x: string) {}, + ~ +!!! error TS1206: Decorators are not valid here. + set s(@dec v: number) {} + ~ +!!! error TS1206: Decorators are not valid here. + }; + } + } + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.js b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.js new file mode 100644 index 0000000000000..5936ad29038a3 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.js @@ -0,0 +1,49 @@ +//// [tests/cases/compiler/decoratorMetadataObjectLiteralMethodNoCrash.ts] //// + +//// [decoratorMetadataObjectLiteralMethodNoCrash.ts] +declare function dec(...args: any[]): any; + +const o = { + m(@dec x: string) {} +}; + +class C { + @dec + prop!: number; + + method() { + return { + m(@dec x: string) {}, + set s(@dec v: number) {} + }; + } +} + + +//// [decoratorMetadataObjectLiteralMethodNoCrash.js] +"use strict"; +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +const o = { + m(x) { } +}; +class C { + prop; + method() { + return { + m(x) { }, + set s(v) { } + }; + } +} +__decorate([ + dec, + __metadata("design:type", Number) +], C.prototype, "prop", void 0); diff --git a/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.symbols b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.symbols new file mode 100644 index 0000000000000..e812f3bf1394c --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.symbols @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/decoratorMetadataObjectLiteralMethodNoCrash.ts] //// + +=== decoratorMetadataObjectLiteralMethodNoCrash.ts === +declare function dec(...args: any[]): any; +>dec : Symbol(dec, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 0, 0)) +>args : Symbol(args, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 0, 21)) + +const o = { +>o : Symbol(o, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 2, 5)) + + m(@dec x: string) {} +>m : Symbol(m, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 2, 11)) +>dec : Symbol(dec, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 0, 0)) +>x : Symbol(x, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 3, 6)) + +}; + +class C { +>C : Symbol(C, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 4, 2)) + + @dec +>dec : Symbol(dec, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 0, 0)) + + prop!: number; +>prop : Symbol(C.prop, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 6, 9)) + + method() { +>method : Symbol(C.method, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 8, 18)) + + return { + m(@dec x: string) {}, +>m : Symbol(m, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 11, 16)) +>dec : Symbol(dec, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 0, 0)) +>x : Symbol(x, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 12, 14)) + + set s(@dec v: number) {} +>s : Symbol(s, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 12, 33)) +>dec : Symbol(dec, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 0, 0)) +>v : Symbol(v, Decl(decoratorMetadataObjectLiteralMethodNoCrash.ts, 13, 18)) + + }; + } +} + diff --git a/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.types b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.types new file mode 100644 index 0000000000000..e21a43b94d91e --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/decoratorMetadataObjectLiteralMethodNoCrash.types @@ -0,0 +1,47 @@ +//// [tests/cases/compiler/decoratorMetadataObjectLiteralMethodNoCrash.ts] //// + +=== decoratorMetadataObjectLiteralMethodNoCrash.ts === +declare function dec(...args: any[]): any; +>dec : (...args: any[]) => any +>args : any[] + +const o = { +>o : { m(x: string): void; } +>{ m(@dec x: string) {}} : { m(x: string): void; } + + m(@dec x: string) {} +>m : (x: string) => void +>dec : (...args: any[]) => any +>x : string + +}; + +class C { +>C : C + + @dec +>dec : (...args: any[]) => any + + prop!: number; +>prop : number + + method() { +>method : () => { m(x: string): void; s: number; } + + return { +>{ m(@dec x: string) {}, set s(@dec v: number) {} } : { m(x: string): void; s: number; } + + m(@dec x: string) {}, +>m : (x: string) => void +>dec : (...args: any[]) => any +>x : string + + set s(@dec v: number) {} +>s : number +>dec : (...args: any[]) => any +>v : number + + }; + } +} + diff --git a/tsc/testdata/tests/cases/compiler/decoratorMetadataObjectLiteralMethodNoCrash.ts b/tsc/testdata/tests/cases/compiler/decoratorMetadataObjectLiteralMethodNoCrash.ts new file mode 100644 index 0000000000000..462cc482a80e7 --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/decoratorMetadataObjectLiteralMethodNoCrash.ts @@ -0,0 +1,20 @@ +// @experimentalDecorators: true +// @emitDecoratorMetadata: true + +declare function dec(...args: any[]): any; + +const o = { + m(@dec x: string) {} +}; + +class C { + @dec + prop!: number; + + method() { + return { + m(@dec x: string) {}, + set s(@dec v: number) {} + }; + } +}