Skip to content

Commit 433bc1e

Browse files
Copilotjakebailey
andauthored
Add BigInt fallback for decorator metadata below ES2020 (#4106)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
1 parent 9874733 commit 433bc1e

9 files changed

Lines changed: 146 additions & 6 deletions

internal/transformers/tstransforms/metadata.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type MetadataTransformer struct {
1515
resolver printer.EmitResolver
1616

1717
serializer *metadataSerializer
18+
languageVersion core.ScriptTarget
1819
strictNullChecks bool
1920
parent *ast.Node
2021
currentLexicalScope *ast.Node
@@ -24,6 +25,7 @@ func NewMetadataTransformer(opt *transformers.TransformOptions) *transformers.Tr
2425
tx := &MetadataTransformer{
2526
legacyDecorators: opt.CompilerOptions.ExperimentalDecorators.IsTrue(),
2627
resolver: opt.EmitResolver,
28+
languageVersion: opt.CompilerOptions.GetEmitScriptTarget(),
2729
strictNullChecks: opt.CompilerOptions.GetStrictOptionValue(opt.CompilerOptions.StrictNullChecks),
2830
}
2931
return tx.NewTransformer(tx.visit, opt.Context)
@@ -52,7 +54,7 @@ func (tx *MetadataTransformer) visit(node *ast.Node) *ast.Node {
5254
defer tx.setParent(nil)
5355
tx.currentLexicalScope = node
5456
defer tx.setCurrentLexicalScope(nil)
55-
tx.serializer = newMetadataSerializer(tx.resolver, tx.Factory(), tx.EmitContext(), tx.strictNullChecks)
57+
tx.serializer = newMetadataSerializer(tx.resolver, tx.Factory(), tx.EmitContext(), tx.languageVersion, tx.strictNullChecks)
5658
updated := tx.Visitor().VisitEachChild(node)
5759
tx.EmitContext().AddEmitHelper(updated, tx.EmitContext().ReadEmitHelpers()...)
5860
return updated

internal/transformers/tstransforms/typeserializer.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ package tstransforms
22

33
import (
44
"github.com/microsoft/typescript-go/internal/ast"
5+
"github.com/microsoft/typescript-go/internal/core"
56
"github.com/microsoft/typescript-go/internal/debug"
67
"github.com/microsoft/typescript-go/internal/printer"
78
"github.com/microsoft/typescript-go/internal/transformers"
89
)
910

1011
type metadataSerializer struct {
1112
resolver printer.EmitResolver
13+
languageVersion core.ScriptTarget
1214
strictNullChecks bool
1315
f *printer.NodeFactory
1416
ec *printer.EmitContext
@@ -21,8 +23,8 @@ type metadataSerializerContext struct {
2123
serializingConditionalTypeBranch bool
2224
}
2325

24-
func newMetadataSerializer(resolver printer.EmitResolver, f *printer.NodeFactory, ec *printer.EmitContext, strictNullChecks bool) *metadataSerializer {
25-
return &metadataSerializer{resolver: resolver, f: f, ec: ec, strictNullChecks: strictNullChecks}
26+
func newMetadataSerializer(resolver printer.EmitResolver, f *printer.NodeFactory, ec *printer.EmitContext, languageVersion core.ScriptTarget, strictNullChecks bool) *metadataSerializer {
27+
return &metadataSerializer{resolver: resolver, languageVersion: languageVersion, f: f, ec: ec, strictNullChecks: strictNullChecks}
2628
}
2729

2830
func (s *metadataSerializer) setContext(ctx metadataSerializerContext) {
@@ -203,7 +205,7 @@ func (s *metadataSerializer) serializeTypeNode(node *ast.Node) *ast.Node {
203205
case ast.KindNumberKeyword:
204206
return s.f.NewIdentifier("Number")
205207
case ast.KindBigIntKeyword:
206-
return s.f.NewIdentifier("BigInt") // !!! todo: fallback for targets < es2020
208+
return s.serializeBigIntConstructor()
207209
case ast.KindSymbolKeyword:
208210
return s.f.NewIdentifier("Symbol")
209211
case ast.KindTypeReference:
@@ -305,7 +307,7 @@ func (s *metadataSerializer) serializeLiteralOfLiteralTypeNode(node *ast.Node) *
305307
case ast.KindNumericLiteral:
306308
return s.f.NewIdentifier("Number")
307309
case ast.KindBigIntLiteral:
308-
return s.f.NewIdentifier("BigInt") // !!! todo: fallback for targets < es2020
310+
return s.serializeBigIntConstructor()
309311
case ast.KindTrueKeyword, ast.KindFalseKeyword:
310312
return s.f.NewIdentifier("Boolean")
311313
case ast.KindNullKeyword:
@@ -352,7 +354,7 @@ func (s *metadataSerializer) serializeTypeReferenceNode(node *ast.TypeReferenceN
352354
return s.f.NewVoidZeroExpression()
353355

354356
case printer.TypeReferenceSerializationKindBigIntLikeType:
355-
return s.f.NewIdentifier("BigInt")
357+
return s.serializeBigIntConstructor()
356358

357359
case printer.TypeReferenceSerializationKindBooleanType:
358360
return s.f.NewIdentifier("Boolean")
@@ -383,6 +385,19 @@ func (s *metadataSerializer) serializeTypeReferenceNode(node *ast.TypeReferenceN
383385
}
384386
}
385387

388+
func (s *metadataSerializer) serializeBigIntConstructor() *ast.Node {
389+
if s.languageVersion >= core.ScriptTargetES2020 {
390+
return s.f.NewIdentifier("BigInt")
391+
}
392+
return s.f.NewConditionalExpression(
393+
s.f.NewTypeCheck(s.f.NewIdentifier("BigInt"), "function"),
394+
s.f.NewToken(ast.KindQuestionToken),
395+
s.f.NewIdentifier("BigInt"),
396+
s.f.NewToken(ast.KindColonToken),
397+
s.f.NewIdentifier("Object"),
398+
)
399+
}
400+
386401
/**
387402
* Serializes an entity name as an expression for decorator type metadata.
388403
* @param node The entity name to serialize.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [tests/cases/compiler/emitDecoratorMetadataBigIntFallback.ts] ////
2+
3+
//// [emitDecoratorMetadataBigIntFallback.ts]
4+
declare function dec(...args: any[]): any;
5+
6+
class C {
7+
@dec prop!: bigint;
8+
}
9+
10+
11+
//// [emitDecoratorMetadataBigIntFallback.js]
12+
"use strict";
13+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
14+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
15+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
16+
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;
17+
return c > 3 && r && Object.defineProperty(target, key, r), r;
18+
};
19+
var __metadata = (this && this.__metadata) || function (k, v) {
20+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
21+
};
22+
class C {
23+
}
24+
__decorate([
25+
dec,
26+
__metadata("design:type", typeof BigInt === "function" ? BigInt : Object)
27+
], C.prototype, "prop", void 0);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [tests/cases/compiler/emitDecoratorMetadataBigIntFallback.ts] ////
2+
3+
=== emitDecoratorMetadataBigIntFallback.ts ===
4+
declare function dec(...args: any[]): any;
5+
>dec : Symbol(dec, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 0))
6+
>args : Symbol(args, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 21))
7+
8+
class C {
9+
>C : Symbol(C, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 42))
10+
11+
@dec prop!: bigint;
12+
>dec : Symbol(dec, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 0))
13+
>prop : Symbol(C.prop, Decl(emitDecoratorMetadataBigIntFallback.ts, 2, 9))
14+
}
15+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [tests/cases/compiler/emitDecoratorMetadataBigIntFallback.ts] ////
2+
3+
=== emitDecoratorMetadataBigIntFallback.ts ===
4+
declare function dec(...args: any[]): any;
5+
>dec : (...args: any[]) => any
6+
>args : any[]
7+
8+
class C {
9+
>C : C
10+
11+
@dec prop!: bigint;
12+
>dec : (...args: any[]) => any
13+
>prop : bigint
14+
}
15+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//// [tests/cases/compiler/emitDecoratorMetadataBigIntFallback.ts] ////
2+
3+
//// [emitDecoratorMetadataBigIntFallback.ts]
4+
declare function dec(...args: any[]): any;
5+
6+
class C {
7+
@dec prop!: bigint;
8+
}
9+
10+
11+
//// [emitDecoratorMetadataBigIntFallback.js]
12+
"use strict";
13+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
14+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
15+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
16+
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;
17+
return c > 3 && r && Object.defineProperty(target, key, r), r;
18+
};
19+
var __metadata = (this && this.__metadata) || function (k, v) {
20+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
21+
};
22+
class C {
23+
}
24+
__decorate([
25+
dec,
26+
__metadata("design:type", BigInt)
27+
], C.prototype, "prop", void 0);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [tests/cases/compiler/emitDecoratorMetadataBigIntFallback.ts] ////
2+
3+
=== emitDecoratorMetadataBigIntFallback.ts ===
4+
declare function dec(...args: any[]): any;
5+
>dec : Symbol(dec, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 0))
6+
>args : Symbol(args, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 21))
7+
8+
class C {
9+
>C : Symbol(C, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 42))
10+
11+
@dec prop!: bigint;
12+
>dec : Symbol(dec, Decl(emitDecoratorMetadataBigIntFallback.ts, 0, 0))
13+
>prop : Symbol(C.prop, Decl(emitDecoratorMetadataBigIntFallback.ts, 2, 9))
14+
}
15+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [tests/cases/compiler/emitDecoratorMetadataBigIntFallback.ts] ////
2+
3+
=== emitDecoratorMetadataBigIntFallback.ts ===
4+
declare function dec(...args: any[]): any;
5+
>dec : (...args: any[]) => any
6+
>args : any[]
7+
8+
class C {
9+
>C : C
10+
11+
@dec prop!: bigint;
12+
>dec : (...args: any[]) => any
13+
>prop : bigint
14+
}
15+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// @target: es2015, es2020
2+
// @experimentalDecorators: true
3+
// @emitDecoratorMetadata: true
4+
5+
declare function dec(...args: any[]): any;
6+
7+
class C {
8+
@dec prop!: bigint;
9+
}

0 commit comments

Comments
 (0)