-
-
Notifications
You must be signed in to change notification settings - Fork 21
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
Ensure identifiers are properly re-written. #109
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This reproduces the errors being reported that are ultimately caused by this libraries mutation of `Identifier` nodes to include things like `Ember.Application` (which is fundamentally not a valid identifier value, it is a `MemberExpression`).
The code previously took an identifier and replaced it's `name` value with one that included a string like `Ember.Foo`. This is completely invalid (a string like `Ember.Foo` is actually a MemberExpression), but we got away with it because for the most part Babel happily printed **whatever** value you give it in that spot. Unfortunately, this happy mistake bit us fairly severely due to Babel introducing new plugins that run as part of `@babel/preset-env` (e.g. to make sure that all identifiers would work properly on IE9). This commit changes from doing a `path.scope.rename(importName, globalPathString)` to properly replacing the identifier with a member expression.
fivetanley
added a commit
to fivetanley/babel-plugin-ember-modules-api-polyfill
that referenced
this pull request
May 29, 2020
[ember-cli#109](5de3c79) introduced a safer way to rewrite variable names by generating MemberExpressions to fix code for IE9, but this introduced a regression for packages using `@babel/plugin-transform-typescript`, such as Ember Data. After 109, Babel would throw the following error if `babel-plugin-ember-modules-api-polyfill` attempetd to rewrite a type information node (in this case, `TSQualifiedName`), if the file also used the import in runtime JS code. The code that triggers this looks like: ```javascript import { default as RSVP, Promise } from 'rsvp'; // value must be used to trigger this RSVP.Promise.resolve().then(() => {}); // AND the same import local name must be used as a type as well function scheduleSave(identifier: RecordIdentifier, options: any = {}): RSVP.Promise<null | SingleResourceDocument> { } ``` ``` Property left of TSQualifiedName expected node to be of a type ["TSEntityName"] but instead got "MemberExpression" ``` This was being triggered when `ember-data` was compiled. Examples were taken from Ember Data's codebase: - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L77 This change uses the [isTSQualifiedName helper](https://babeljs.io/docs/en/babel-types#tsqualifiedname) from `@babel/types` if it is available (if on a recent version of babel or if `@babel/plugin-transform-typescript` is loaded as a plugin) to determine whether or not to rewrite the node. Since type information is removed from Babel output, and babel does not do any linting/type checking of transformed Typescript, it seems fine to leave these nodes alone.
fivetanley
added a commit
to fivetanley/babel-plugin-ember-modules-api-polyfill
that referenced
this pull request
May 29, 2020
[ember-cli#109](5de3c79) introduced a safer way to rewrite variable names by generating MemberExpressions to fix code for IE9, but this introduced a regression for packages using `@babel/plugin-transform-typescript`, such as Ember Data. After 109, Babel would throw the following error if `babel-plugin-ember-modules-api-polyfill` attempetd to rewrite a type information node (in this case, `TSQualifiedName`), if the file also used the import in runtime JS code. The code that triggers this looks like: ```javascript import { default as RSVP, Promise } from 'rsvp'; // value must be used to trigger this RSVP.Promise.resolve().then(() => {}); // AND the same import local name must be used as a type as well function scheduleSave(identifier: RecordIdentifier, options: any = {}): RSVP.Promise<null | SingleResourceDocument> { } ``` ``` Property left of TSQualifiedName expected node to be of a type ["TSEntityName"] but instead got "MemberExpression" ``` This was being triggered when `ember-data` was compiled. Examples were taken from Ember Data's codebase: - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L77 This change uses the [isTSQualifiedName helper](https://babeljs.io/docs/en/babel-types#tsqualifiedname) from `@babel/types` if it is available (if on a recent version of babel or if `@babel/plugin-transform-typescript` is loaded as a plugin) to determine whether or not to rewrite the node. Since type information is removed from Babel output, and babel does not do any linting/type checking of transformed Typescript, it seems fine to leave these nodes alone.
fivetanley
added a commit
to fivetanley/babel-plugin-ember-modules-api-polyfill
that referenced
this pull request
May 29, 2020
[ember-cli#109](5de3c79) introduced a safer way to rewrite variable names by generating MemberExpressions to fix code for IE9, but this introduced a regression for packages using `@babel/plugin-transform-typescript`, such as Ember Data. After 109, Babel would throw the following error if `babel-plugin-ember-modules-api-polyfill` attempted to rewrite a type information node (in this case, `TSQualifiedName`), if the file also used the import in runtime JS code. The code that triggers this looks like: ```javascript import { default as RSVP, Promise } from 'rsvp'; // value must be used to trigger this RSVP.Promise.resolve().then(() => {}); // AND the same import local name must be used as a type as well function scheduleSave(identifier: RecordIdentifier, options: any = {}): RSVP.Promise<null | SingleResourceDocument> { } ``` ``` Property left of TSQualifiedName expected node to be of a type ["TSEntityName"] but instead got "MemberExpression" ``` This was being triggered when `ember-data` was compiled. Examples were taken from Ember Data's codebase: - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L77 This change uses the [isTSQualifiedName helper](https://babeljs.io/docs/en/babel-types#tsqualifiedname) from `@babel/types` if it is available (if on a recent version of babel or if `@babel/plugin-transform-typescript` is loaded as a plugin) to determine whether or not to rewrite the node. Since type information is removed from Babel output, and babel does not do any linting/type checking of transformed Typescript, it seems fine to leave these nodes alone.
fivetanley
added a commit
to fivetanley/babel-plugin-ember-modules-api-polyfill
that referenced
this pull request
May 29, 2020
[ember-cli#109](5de3c79) introduced a safer way to rewrite variable names by generating MemberExpressions to fix code for IE9, but this introduced a regression for packages using `@babel/plugin-transform-typescript`, such as Ember Data. After 109, Babel would throw the following error if `babel-plugin-ember-modules-api-polyfill` attempted to rewrite a type information node (in this case, `TSQualifiedName`), if the file also used the import in runtime JS code. The code that triggers this looks like: ```javascript import { default as RSVP, Promise } from 'rsvp'; // value must be used to trigger this RSVP.Promise.resolve().then(() => {}); // AND the same import local name must be used as a type as well function scheduleSave(identifier: RecordIdentifier, options: any = {}): RSVP.Promise<null | SingleResourceDocument> { } ``` ``` Property left of TSQualifiedName expected node to be of a type ["TSEntityName"] but instead got "MemberExpression" ``` This was being triggered when `ember-data` was compiled. Examples were taken from Ember Data's codebase: - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L77 This change uses the [isTSQualifiedName helper](https://babeljs.io/docs/en/babel-types#tsqualifiedname) from `@babel/types` if it is available (if on a recent version of babel or if `@babel/plugin-transform-typescript` is loaded as a plugin) to determine whether or not to rewrite the node. Since type information is removed from Babel output, and babel does not do any linting/type checking of transformed Typescript, it seems fine to leave these nodes alone.
fivetanley
added a commit
to fivetanley/babel-plugin-ember-modules-api-polyfill
that referenced
this pull request
May 29, 2020
[ember-cli#109](5de3c79) introduced a safer way to rewrite variable names by generating MemberExpressions to fix code for IE9, but this introduced a regression for packages using `@babel/plugin-transform-typescript`, such as Ember Data. After 109, Babel would throw the following error if `babel-plugin-ember-modules-api-polyfill` attempted to rewrite a type information node (in this case, `TSQualifiedName`), if the file also used the import in runtime JS code. The code that triggers this looks like: ```javascript import { default as RSVP, Promise } from 'rsvp'; // value must be used to trigger this RSVP.Promise.resolve().then(() => {}); // AND the same import local name must be used as a type as well function scheduleSave(identifier: RecordIdentifier, options: any = {}): RSVP.Promise<null | SingleResourceDocument> { } ``` ``` Property left of TSQualifiedName expected node to be of a type ["TSEntityName"] but instead got "MemberExpression" ``` This was being triggered when `ember-data` was compiled. Examples were taken from Ember Data's codebase: - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L77 This change uses the [isTSQualifiedName helper](https://babeljs.io/docs/en/babel-types#tsqualifiedname) from `@babel/types` if it is available (if on a recent version of babel or if `@babel/plugin-transform-typescript` is loaded as a plugin) to determine whether or not to rewrite the node. Since type information is removed from Babel output, and babel does not do any linting/type checking of transformed Typescript, it seems fine to leave these nodes alone.
fivetanley
added a commit
to fivetanley/babel-plugin-ember-modules-api-polyfill
that referenced
this pull request
May 29, 2020
[ember-cli#109](5de3c79) introduced a safer way to rewrite variable names by generating MemberExpressions to fix code for IE9, but this introduced a regression for packages using `@babel/plugin-transform-typescript`, such as Ember Data. After 109, Babel would throw the following error if `babel-plugin-ember-modules-api-polyfill` attempted to rewrite a type information node (in this case, `TSQualifiedName`), if the file also used the import in runtime JS code. The code that triggers this looks like: ```javascript import { default as RSVP, Promise } from 'rsvp'; // value must be used to trigger this RSVP.Promise.resolve().then(() => {}); // AND the same import local name must be used as a type as well function scheduleSave(identifier: RecordIdentifier, options: any = {}): RSVP.Promise<null | SingleResourceDocument> { } ``` ``` Property left of TSQualifiedName expected node to be of a type ["TSEntityName"] but instead got "MemberExpression" ``` This was being triggered when `ember-data` was compiled. Examples were taken from Ember Data's codebase: - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L124 - https://github.com/emberjs/data/blob/70b0c55e1a950bed1da64d0ecb4eaa0d5df92f9f/packages/store/addon/-private/system/fetch-manager.ts#L77 This change looks at the `type` of the `referencePath.parentNode` to see if it belongs with `TS`, since it seems like all Typescript types in @babel/types are namespaced with `TS`. There's unfortunately no list or API of typescript nodes we could programatically pull this from. Since type information is removed from Babel output, and babel does not do any linting/type checking of transformed Typescript, it seems fine to leave these nodes alone.
rwjblue
added a commit
to emberjs/ember-cli-babel
that referenced
this pull request
Jun 2, 2020
The original fix in ember-cli/babel-plugin-ember-modules-api-polyfill#109 attempted to cache the generated member expressions, so that we didn't do duplicated work for each reference to a given global. Unfortunately, this optimization failed to take into consideration that most babel plugins work by directly mutating the node in question. In practice what that meant was that once _any_ usage of a given global was needed to be transformed (e.g. say you had `computed(...args, function(){})` and are transpiling for IE11), then all usages of that global would be mutated. A more concrete example. ```js // input import { computed } from '@ember/object'; function specialComputed(dependentKeys) { return computed(...dependentKeys, function() {}); } function otherLessSpecialComputed() { return computed('stuff', 'hard', 'coded', function() {}); } ``` In this example, the first method (`specialComputed`) needs to be transpiled to something akin to (most of the changes here are from `@babel/plugin-transform-spread`): ```js function specialComputed(dependentKeys) { return Ember.computed.apply(Ember, dependentKeys.concat([function() {}])); } ``` Unfortunately, since the generated `MemberExpression` for `Ember.computed` is shared, this forced the other `computed` usage to be transpiled to: ```js function otherLessSpecialComputed() { return Ember.computed.apply('stuff', 'hard', 'coded', function() {}); } ``` Which is clearly, **totally** invalid. 🤦
This was referenced Jun 2, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The code previously took an identifier and replaced it's
name
value with one that included a string likeEmber.Foo
. This is completely invalid (a string likeEmber.Foo
is actually a MemberExpression), but we got away with it because for the most part Babel happily printed whatever value you give it in that spot.Unfortunately, this happy mistake bit us fairly severely due to Babel introducing new plugins that run as part of
@babel/preset-env
(e.g. to make sure that all identifiers would work properly on IE9).This commit changes from doing a
path.scope.rename(importName, globalPathString)
to properly replacing the identifier with a member expression.This PR includes the failing test added in #108 (see that PR to confirm the failure mode), and ensures that it passes.
Fixes #64
Closes #108