Skip to content

Commit

Permalink
Fix issues when using colocated component's with decorators.
Browse files Browse the repository at this point in the history
The changes made in f9053bc added the ability to detect `export { Foo
as default }` along side the ability to detect `export default Foo`.
When ran in isolation (or with the `@babel/plugin-transform-typescript`)
this works fine, but in common scenarios without typescript support it
failed.

The cause of the failure is a bit difficult to grok, but _basically_ it
is because when our `ExportDefaultDeclaration` hook is hit, we add the
`setComponentTemplate` invocation. Then **subsequently** another plugin
changes from `export default Foo` to `export { Foo as default }` (the
combination of `@babel/plugin-proposal-decorators` and
`@babel/plugin-proposal-class-fields` does this), and we run the new
`ExportNamedDeclaration` which causes us to add `setComponentTemplate`
invocation **_again_**.

The fix added here ensures that _only **one**_ `setComponentTemplate`
invocation will be added (even if we see both `export default Foo` and
`export { Foo as default }` during traversal).
  • Loading branch information
rwjblue committed Oct 19, 2019
1 parent 86838c6 commit f903240
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 4 deletions.
6 changes: 4 additions & 2 deletions lib/colocated-babel-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ module.exports = function(babel) {
},

ExportDefaultDeclaration(path, state) {
if (!state.colocatedTemplateFound) {
if (state.colocatedTemplateFound !== true || state.setComponentTemplateInjected === true) {
return;
}

state.setComponentTemplateInjected = true;
let defaultExportDeclaration = path.node.declaration;
let setComponentTemplateMemberExpression = makeSetComponentTemplateMemberExpression();
let colocatedTemplateIdentifier = makeColocatedTemplateIdentifier();
Expand Down Expand Up @@ -63,12 +64,13 @@ module.exports = function(babel) {
},

ExportNamedDeclaration(path, state) {
if (!state.colocatedTemplateFound) {
if (state.colocatedTemplateFound !== true || state.setComponentTemplateInjected === true) {
return;
}

let defaultSpecifier = path.node.specifiers.find(spec => spec.exported.name === 'default');
if (defaultSpecifier) {
state.setComponentTemplateInjected = true;
path.parent.body.push(
t.expressionStatement(
t.callExpression(makeSetComponentTemplateMemberExpression(), [
Expand Down
60 changes: 60 additions & 0 deletions node-tests/colocated-babel-plugin-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,70 @@ const assert = require('assert');
const babel = require('@babel/core');
const { stripIndent } = require('common-tags');
const ColocatedBabelPlugin = require('../lib/colocated-babel-plugin');
const DecoratorsPlugin = [require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }];
const ClassPropertiesPlugin = [
require.resolve('@babel/plugin-proposal-class-properties'),
{ loose: true },
];
const RuntimePlugin = [
require.resolve('@babel/plugin-transform-runtime'),
{
version: require('@babel/runtime/package').version,
regenerator: false,
useESModules: true,
},
];

describe('ColocatedBabelPlugin', function() {
this.slow(500);

it('can be used with decorators', function() {
let { code } = babel.transformSync(
stripIndent`
import Component from '@glimmer/component';
const __COLOCATED_TEMPLATE__ = 'ok';
export default class MyComponent extends Component {
@tracked data = null;
};
`,
{ plugins: [RuntimePlugin, ColocatedBabelPlugin, DecoratorsPlugin, ClassPropertiesPlugin] }
);

assert.strictEqual(
code,
stripIndent`
import _initializerDefineProperty from "@babel/runtime/helpers/esm/initializerDefineProperty";
import _applyDecoratedDescriptor from "@babel/runtime/helpers/esm/applyDecoratedDescriptor";
import _initializerWarningHelper from "@babel/runtime/helpers/esm/initializerWarningHelper";
var _class, _descriptor, _temp;
import Component from '@glimmer/component';
const __COLOCATED_TEMPLATE__ = 'ok';
let MyComponent = (_class = (_temp = class MyComponent extends Component {
constructor(...args) {
super(...args);
_initializerDefineProperty(this, "data", _descriptor, this);
}
}, _temp), (_descriptor = _applyDecoratedDescriptor(_class.prototype, "data", [tracked], {
configurable: true,
enumerable: true,
writable: true,
initializer: function () {
return null;
}
})), _class);
export { MyComponent as default };
;
Ember._setComponentTemplate(__COLOCATED_TEMPLATE__, MyComponent);
`
);
});

it('sets the template for non-class default exports', function() {
let { code } = babel.transformSync(
stripIndent`
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@
},
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-decorators": "^7.6.0",
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/plugin-transform-typescript": "^7.6.3",
"@babel/runtime": "^7.6.3",
"@ember/optional-features": "^1.0.0",
"babel-plugin-debug-macros": "^0.3.3",
"broccoli-merge-trees": "^3.0.2",
Expand Down
21 changes: 19 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -273,15 +273,15 @@
"@babel/helper-remap-async-to-generator" "^7.1.0"
"@babel/plugin-syntax-async-generators" "^7.2.0"

"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.3.4":
"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.3.4", "@babel/plugin-proposal-class-properties@^7.5.5":
version "7.5.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz#a974cfae1e37c3110e71f3c6a2e48b8e71958cd4"
integrity sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A==
dependencies:
"@babel/helper-create-class-features-plugin" "^7.5.5"
"@babel/helper-plugin-utils" "^7.0.0"

"@babel/plugin-proposal-decorators@^7.3.0":
"@babel/plugin-proposal-decorators@^7.3.0", "@babel/plugin-proposal-decorators@^7.6.0":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.6.0.tgz#6659d2572a17d70abd68123e89a12a43d90aa30c"
integrity sha512-ZSyYw9trQI50sES6YxREXKu+4b7MAg6Qx2cvyDDYjP2Hpzd3FleOUwC9cqn1+za8d0A2ZU8SHujxFao956efUg==
Expand Down Expand Up @@ -597,6 +597,16 @@
resolve "^1.8.1"
semver "^5.5.1"

"@babel/plugin-transform-runtime@^7.6.2":
version "7.6.2"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.2.tgz#2669f67c1fae0ae8d8bf696e4263ad52cb98b6f8"
integrity sha512-cqULw/QB4yl73cS5Y0TZlQSjDvNkzDbu0FurTZyHlJpWE5T3PCMdnyV+xXoH1opr1ldyHODe3QAX3OMAii5NxA==
dependencies:
"@babel/helper-module-imports" "^7.0.0"
"@babel/helper-plugin-utils" "^7.0.0"
resolve "^1.8.1"
semver "^5.5.1"

"@babel/plugin-transform-shorthand-properties@^7.2.0":
version "7.2.0"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz#6333aee2f8d6ee7e28615457298934a3b46198f0"
Expand Down Expand Up @@ -731,6 +741,13 @@
dependencies:
regenerator-runtime "^0.13.2"

"@babel/runtime@^7.6.3":
version "7.6.3"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.6.3.tgz#935122c74c73d2240cafd32ddb5fc2a6cd35cf1f"
integrity sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==
dependencies:
regenerator-runtime "^0.13.2"

"@babel/template@^7.1.0", "@babel/template@^7.4.4", "@babel/template@^7.6.0":
version "7.6.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.6.0.tgz#7f0159c7f5012230dad64cca42ec9bdb5c9536e6"
Expand Down

0 comments on commit f903240

Please sign in to comment.