ember-cli-typescript
ember-cli-typescript copied to clipboard
Babel decorator runtime helper errors for class with overloaded method
Please paste the output of ember -v here
ember-cli: 3.7.1 node: 10.11.0 os: darwin x64
Please paste the output of tsc -v here
Version 3.3.3333
Please paste your tconfig.json and tslint.json or eslint.json (if applicable) below
My tsconfig.json
{ "compilerOptions": { "target": "es2017", "allowJs": true, "moduleResolution": "node", "allowSyntheticDefaultImports": true, "noImplicitAny": true, "noImplicitThis": true, "alwaysStrict": true, "strictNullChecks": true, "strictPropertyInitialization": true, "noFallthroughCasesInSwitch": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noEmitOnError": false, "noEmit": true, "inlineSourceMap": true, "inlineSources": true, "baseUrl": ".", "module": "es6", "experimentalDecorators": true, "paths": { "ember-typescript-overloads-decorators-bug/tests/": [ "tests/" ], "ember-typescript-overloads-decorators-bug/": [ "app/" ], "": [ "types/" ] } }, "include": [ "app//*", "tests//", "types/**/" ] }
What are instructions we can follow to reproduce the issue?
git clone https://github.com/simonihmig/ember-typescript-overloads-decorators-bug
Reproduction Case
See the above reproduction repo.
Now about that bug. What did you expect to see?
Hit http://localhost:4200/ and see the default welcome page.
What happened instead?
Runtime error: Uncaught TypeError: Duplicated element (foo)
This happens when a TS class has at least one decorator and one overloaded method. Seems to be an issue with how the decorators and TS Babel plugins interact AFAICT.
The transpiled output of https://github.com/simonihmig/ember-typescript-overloads-decorators-bug/blob/master/app/controllers/application.ts looks like this:
let ApplicationController = (0, _decorate2.default)(null, function (_initialize, _EmberController) {
class ApplicationController extends _EmberController {
constructor(...args) {
super(...args);
_initialize(this);
}
}
return {
F: ApplicationController,
d: [{
kind: "field",
decorators: [_service.inject],
key: "router",
value: void 0
}, {
kind: "field",
key: "foo",
value: void 0
}, {
kind: "field",
key: "foo",
value: void 0
}, {
kind: "method",
key: "foo",
value: function foo() {// dummy
}
}]
};
}, Ember.Controller);
So the overloaded foo method, which should affect only the typing, not the runtime code, causes multiple foo fields to be defined for the decorator runtime (@babel/runtime/helpers/esm/decorate), which then errors because of this.
Related code in the demo repo: https://github.com/simonihmig/ember-typescript-overloads-decorators-bug/commit/7f3f038e1e5f55b2ed618f479bdf087c14c1947b#diff-96934836c1696c832b0197675373e74f
@simonihmig can you add the ember-cli-typescript version to the writeup there when you get a chance, please?
At first blush this definitely looks like a bug in the intersection of Babel's TS plugin and its class fields plugin… and it doesn't happen if decorators are present? Quite a specific corner if that's the case.
can you add the ember-cli-typescript version to the writeup there when you get a chance, please?
Using 2.0.0-rc.2, same in the reproduction: https://github.com/simonihmig/ember-typescript-overloads-decorators-bug/blob/master/package.json#L45
and it doesn't happen if decorators are present
You probably mean the opposite, so it doesn't happen if decorators are not present. So both condition must be met: overloaded method + decorator used.
Without decorators you don't get this "massively" transpiled structure:
return {
F: ApplicationController,
d: [...]
}
Just a simple ES6 class, with the overloaded type definitions being removed from the final output.
It looks as if the decorator babel plugin runs first before the overloaded type definitions are stripped, and while generating this structure above it interprets the overloaded type definitions as separate methods (all with the same key!), puts them all into this d: [...] array, which causes the runtime decorator helper later to fail. If the TS plugin would have stripped the type definitions first, this would probably not happen. Just my naive interpretation though...
Maybe @pzuraq has some ideas?
We're planning on walking back the decorators transforms to stage 1, so maybe try those transforms and see if it works better? @ember-decorators/babel-transforms@^2.1.0 should work
See the latest revision of https://github.com/emberjs/rfcs/pull/440 for more details
Maybe related to https://github.com/ember-cli/ember-ajax/issues/428
I believe this has been resolved upstream long since; but in any case the goal will be to align with spec decorators (and will not be something fixed in a TS-specific way).