Skip to content

Commit

Permalink
fix #3177: experimental decorators + mangle props
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jun 17, 2023
1 parent 2455820 commit 3af5d3b
Show file tree
Hide file tree
Showing 5 changed files with 457 additions and 14 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
new Foo().foo = Foo.bar;
```

* Fix TypeScript experimental decorators combined with `--mangle-props` ([#3177](https://github.com/evanw/esbuild/issues/3177))

Previously using TypeScript experimental decorators combined with the `--mangle-props` setting could result in a crash, as the experimental decorator transform was not expecting a mangled property as a class member. This release fixes the crash so you can now combine both of these features together safely.

## 0.18.4

* Bundling no longer unnecessarily transforms class syntax ([#1360](https://github.com/evanw/esbuild/issues/1360), [#1328](https://github.com/evanw/esbuild/issues/1328), [#1524](https://github.com/evanw/esbuild/issues/1524), [#2416](https://github.com/evanw/esbuild/issues/2416))
Expand Down
173 changes: 173 additions & 0 deletions internal/bundler_tests/bundler_ts_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bundler_tests

import (
"regexp"
"testing"

"github.com/evanw/esbuild/internal/compat"
Expand Down Expand Up @@ -2470,3 +2471,175 @@ func TestTSPreferJSOverTSInsideNodeModules(t *testing.T) {
},
})
}

func TestTSExperimentalDecoratorsManglePropsDefineSemantics(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
class Foo {
@dec(1) prop1 = null
@dec(2) prop2_ = null
@dec(3) ['prop3'] = null
@dec(4) ['prop4_'] = null
@dec(5) [/* @__KEY__ */ 'prop5'] = null
@dec(6) [/* @__KEY__ */ 'prop6_'] = null
}
`,
"/tsconfig.json": `{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": true,
},
}`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
MangleProps: regexp.MustCompile("_$"),
},
})
}

func TestTSExperimentalDecoratorsManglePropsAssignSemantics(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
class Foo {
@dec(1) prop1 = null
@dec(2) prop2_ = null
@dec(3) ['prop3'] = null
@dec(4) ['prop4_'] = null
@dec(5) [/* @__KEY__ */ 'prop5'] = null
@dec(6) [/* @__KEY__ */ 'prop6_'] = null
}
`,
"/tsconfig.json": `{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
},
}`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
MangleProps: regexp.MustCompile("_$"),
},
})
}

func TestTSExperimentalDecoratorsManglePropsMethods(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
class Foo {
@dec(1) prop1() {}
@dec(2) prop2_() {}
@dec(3) ['prop3']() {}
@dec(4) ['prop4_']() {}
@dec(5) [/* @__KEY__ */ 'prop5']() {}
@dec(6) [/* @__KEY__ */ 'prop6_']() {}
}
`,
"/tsconfig.json": `{
"compilerOptions": {
"experimentalDecorators": true,
},
}`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
MangleProps: regexp.MustCompile("_$"),
},
})
}

func TestTSExperimentalDecoratorsManglePropsStaticDefineSemantics(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
class Foo {
@dec(1) static prop1 = null
@dec(2) static prop2_ = null
@dec(3) static ['prop3'] = null
@dec(4) static ['prop4_'] = null
@dec(5) static [/* @__KEY__ */ 'prop5'] = null
@dec(6) static [/* @__KEY__ */ 'prop6_'] = null
}
`,
"/tsconfig.json": `{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": true,
},
}`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
MangleProps: regexp.MustCompile("_$"),
},
})
}

func TestTSExperimentalDecoratorsManglePropsStaticAssignSemantics(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
class Foo {
@dec(1) static prop1 = null
@dec(2) static prop2_ = null
@dec(3) static ['prop3'] = null
@dec(4) static ['prop4_'] = null
@dec(5) static [/* @__KEY__ */ 'prop5'] = null
@dec(6) static [/* @__KEY__ */ 'prop6_'] = null
}
`,
"/tsconfig.json": `{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
},
}`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
MangleProps: regexp.MustCompile("_$"),
},
})
}

func TestTSExperimentalDecoratorsManglePropsStaticMethods(t *testing.T) {
ts_suite.expectBundled(t, bundled{
files: map[string]string{
"/entry.ts": `
class Foo {
@dec(1) static prop1() {}
@dec(2) static prop2_() {}
@dec(3) static ['prop3']() {}
@dec(4) static ['prop4_']() {}
@dec(5) static [/* @__KEY__ */ 'prop5']() {}
@dec(6) static [/* @__KEY__ */ 'prop6_']() {}
}
`,
"/tsconfig.json": `{
"compilerOptions": {
"experimentalDecorators": true,
},
}`,
},
entryPaths: []string{"/entry.ts"},
options: config.Options{
Mode: config.ModeBundle,
AbsOutputFile: "/out.js",
MangleProps: regexp.MustCompile("_$"),
},
})
}

0 comments on commit 3af5d3b

Please sign in to comment.