Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support emitDecoratorMetadata use refleact-metadata #509

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/esbuild
/esbuild.exe
/github/
/.devcontainer/
/npm/esbuild-darwin-64/bin/esbuild
/npm/esbuild-freebsd-64/bin/esbuild
/npm/esbuild-freebsd-arm64/bin/esbuild
Expand Down
3 changes: 2 additions & 1 deletion cmd/esbuild/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Advanced options:
--metafile=... Write metadata about the build to a JSON file
--pure:N Mark the name N as a pure function for tree shaking
--inject:F Import the file F into all input files and
automatically replace matching globals with imports
automatically replace matching globals with imports
--tsconfig=... Use this tsconfig.json file instead of other ones
--out-extension:.js=.mjs Use a custom output extension instead of ".js"
--main-fields=... Override the main file order in package.json
Expand All @@ -69,6 +69,7 @@ Advanced options:
--color=... Force use of color terminal escapes (true | false)
--charset=utf8 Do not escape UTF-8 code points
--avoid-tdz An optimization for large bundles in Safari
--reflect-metadata support tsconfig emitDecoratorMetadata

Examples:
# Produces dist/entry_point.js and dist/entry_point.js.map
Expand Down
22 changes: 12 additions & 10 deletions internal/bundler/bundler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1335,10 +1335,11 @@ func (b *Bundle) generateMetadataJSON(results []OutputFile, asciiOnly bool) []by
}

type runtimeCacheKey struct {
MangleSyntax bool
MinifyIdentifiers bool
ES6 bool
Platform config.Platform
MangleSyntax bool
MinifyIdentifiers bool
ES6 bool
UseDecoratorMetadata bool
Platform config.Platform
}

type runtimeCache struct {
Expand All @@ -1354,17 +1355,18 @@ var globalRuntimeCache runtimeCache
func (cache *runtimeCache) parseRuntime(options *config.Options) (source logger.Source, runtimeAST js_ast.AST, ok bool) {
key := runtimeCacheKey{
// All configuration options that the runtime code depends on must go here
MangleSyntax: options.MangleSyntax,
MinifyIdentifiers: options.MinifyIdentifiers,
Platform: options.Platform,
ES6: runtime.CanUseES6(options.UnsupportedJSFeatures),
MangleSyntax: options.MangleSyntax,
MinifyIdentifiers: options.MinifyIdentifiers,
Platform: options.Platform,
UseDecoratorMetadata: options.UseDecoratorMetadata,
ES6: runtime.CanUseES6(options.UnsupportedJSFeatures),
}

// Determine which source to use
if key.ES6 {
source = runtime.ES6Source
source = runtime.ES6Source(options)
} else {
source = runtime.ES5Source
source = runtime.ES5Source(options)
}

// Cache hit?
Expand Down
81 changes: 81 additions & 0 deletions internal/bundler/bundler_ts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -870,3 +870,84 @@ func TestExportTypeIssue379(t *testing.T) {
},
})
}

func TestTypeScriptDecoratorsMetadata(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
import * as AF from './af'
console.log(AF)
`,
"/af.ts": `
export function aaa(aa:AA1):void{
const b:string = "1"
const {a} = aa;
}
export function bbb(bb:BB1):boolean{
const {b} = bb
}

`,
"/test.ts": `
export type Test = Element
`,
},
entryPaths: []string{"/entry.ts"},

options: config.Options{
Mode: config.ModeBundle,
// OutputFormat: config.FormatCommonJS,
AbsOutputFile: "/out.js",
// UseRefleatMetaData
},
})
}

func TestTypeScriptDecoratorsMetadataClass(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
import * as AF from './af'
console.log(AF)
`,
"/af.ts": `
class Abc1{}

@Injectable
export default class Action {
constructor(
public readonly str:String="str",
public readonly middleware1: AA.MiddlewareFactory,
public readonly abc: Abc1,
public readonly def: DEF
):void {
// super(reducer, api, middleware);
}
@loading()
@param()
async fetchList(aa:string):Promise{
// await aa
return aa
}
}

`,
"/metadata.ts": `
export const __metadata=function(){}
`,
"/test.ts": `
export type Test = Element
`,
},
entryPaths: []string{"/entry.ts"},

options: config.Options{
Mode: config.ModeBundle,

// OutputFormat: config.FormatCommonJS,
AbsOutputFile: "/out.js",
UseDecoratorMetadata: true,
// UseRefleatMetaData
},
})
}
27 changes: 27 additions & 0 deletions internal/bundler/bundler_tsconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -634,3 +634,30 @@ func TestTsconfigPreserveTypeImports(t *testing.T) {
},
})
}

func TestTsconfigEmitDecoratorMetadata(t *testing.T) {
tsconfig_suite.expectBundled(t, bundled{
files: map[string]string{
"/Users/user/project/src/entry.ts": `
import {x, y} from "./foo"
console.log(1 as x)
`,
"/Users/user/project/src/tsconfig.json": `{
"compilerOptions": {
"importsNotUsedAsValues": "preserve",
"emitDecoratorMetadata": true
}
}`,
},
entryPaths: []string{"/Users/user/project/src/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/Users/user/project/out.js",
ExternalModules: config.ExternalModules{
AbsPaths: map[string]bool{
"/Users/user/project/src/foo": true,
},
},
},
})
}
60 changes: 60 additions & 0 deletions internal/bundler/snapshots/snapshots_ts.txt
Original file line number Diff line number Diff line change
Expand Up @@ -538,3 +538,63 @@ __decorate([

// /entry.js
console.log(all_default, all_computed_default, a, b, c, d, e_default2, f_default, g_default2, h_default, i, j, k_default);

================================================================================
TestTypeScriptDecoratorsMetadata
---------- /out.js ----------
// /af.ts
const af_exports = {};
__export(af_exports, {
aaa: () => aaa,
bbb: () => bbb
});
function aaa(aa) {
const b = "1";
const {a} = aa;
}
function bbb(bb) {
const {b} = bb;
}

// /entry.ts
console.log(af_exports);

================================================================================
TestTypeScriptDecoratorsMetadataClass
---------- /out.js ----------
// /af.ts
const af_exports = {};
__export(af_exports, {
default: () => af_default
});
let Action = class {
constructor(str = "str", middleware1, abc, def) {
this.str = str;
this.middleware1 = middleware1;
this.abc = abc;
this.def = def;
}
async fetchList(aa) {
return aa;
}
};
__decorate([
loading(),
param(),
__metadata("design:type", Function),
__metadata("design:paramtypes", [Object]),
__metadata("design:returntype", Promise)
], Action.prototype, "fetchList", null);
Action = __decorate([
Injectable,
__metadata("design:paramtypes", [
String,
MiddlewareFactory,
Abc1,
DEF
])
], Action);
var af_default = Action;

// /entry.ts
console.log(af_exports);
7 changes: 7 additions & 0 deletions internal/bundler/snapshots/snapshots_tsconfig.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ var baseurl_nested_default = {
// /Users/user/project/entry.ts
console.log(baseurl_dot_default, baseurl_nested_default);

================================================================================
TestTsconfigEmitDecoratorMetadata
---------- /Users/user/project/out.js ----------
// /Users/user/project/src/entry.ts
import "./src/foo";
console.log(1);

================================================================================
TestTsconfigJsonBaseUrl
---------- /Users/user/project/out.js ----------
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ type Options struct {
OmitRuntimeForTests bool
PreserveUnusedImportsTS bool
UseDefineForClassFields bool
UseDecoratorMetadata bool
AvoidTDZ bool
ASCIIOnly bool

Expand Down
25 changes: 13 additions & 12 deletions internal/js_ast/js_ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ type Arg struct {
TSDecorators []Expr
Binding Binding
Default *Expr

Type Ref
// "constructor(public x: boolean) {}"
IsTypeScriptCtorField bool
}
Expand All @@ -305,11 +305,11 @@ type Fn struct {
Args []Arg
Body FnBody
ArgumentsRef Ref

IsAsync bool
IsGenerator bool
HasRestArg bool
HasIfScope bool
ResultType Ref
IsAsync bool
IsGenerator bool
HasRestArg bool
HasIfScope bool
}

type FnBody struct {
Expand Down Expand Up @@ -1290,12 +1290,13 @@ type ScopeMember struct {
}

type Scope struct {
Kind ScopeKind
Parent *Scope
Children []*Scope
Members map[string]ScopeMember
Generated []Ref

Kind ScopeKind
Parent *Scope
Children []*Scope
Members map[string]ScopeMember
Identifiers map[string]string
Generated []Ref
// ArgsIdentifier map[string]string
// This is used to store the ref of the label symbol for ScopeLabel scopes.
LabelRef Ref
LabelStmtIsLoop bool
Expand Down
8 changes: 6 additions & 2 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4106,12 +4106,12 @@ func (p *parser) parseFn(name *js_ast.LocRef, data fnOrArrowDataParse) (fn js_as
value := p.parseExpr(js_ast.LComma)
defaultValue = &value
}

argType := p.newSymbol(js_ast.SymbolHoisted, p.lexer.Identifier)
fn.Args = append(fn.Args, js_ast.Arg{
TSDecorators: tsDecorators,
Binding: arg,
Default: defaultValue,

Type: argType,
// We need to track this because it affects code generation
IsTypeScriptCtorField: isTypeScriptCtorField,
})
Expand Down Expand Up @@ -4141,6 +4141,10 @@ func (p *parser) parseFn(name *js_ast.LocRef, data fnOrArrowDataParse) (fn js_as
if p.TS.Parse && p.lexer.Token == js_lexer.TColon {
p.lexer.Next()
p.skipTypeScriptReturnType()
// println(p.lexer.Identifier)
if p.lexer.Identifier != "" {
fn.ResultType = p.newSymbol(js_ast.SymbolHoisted, p.lexer.Identifier)
}
}

// "function foo(): any;"
Expand Down
Loading