@@ -31,16 +31,6 @@ function isDecorator(moduleName, importName) {
3131 }
3232}
3333
34- // what are the odds someone else defines this?
35- const EmberGlobalImportName = '____EMBER_GLOBAL____' ;
36-
37- function emberImport ( t ) {
38- return t . importDeclaration (
39- [ t . importDefaultSpecifier ( t . identifier ( EmberGlobalImportName ) ) ] ,
40- t . stringLiteral ( 'ember' )
41- ) ;
42- }
43-
4434module . exports = function ( babel ) {
4535 const t = babel . types ;
4636
@@ -68,14 +58,17 @@ module.exports = function (babel) {
6858 reverseMapping [ importRoot ] [ importName ] = imported ;
6959 } ) ;
7060
71- function getMemberExpressionFor ( global ) {
61+ function getMemberExpressionFor ( global , emberIdentifier ) {
7262 let parts = global . split ( '.' ) ;
7363
7464 let object = parts . shift ( ) ;
7565 let property = parts . shift ( ) ;
7666
67+ let objectIdentifier =
68+ object === 'Ember' ? emberIdentifier : t . identifier ( object ) ;
69+
7770 let memberExpression = t . MemberExpression (
78- t . identifier ( object ) ,
71+ objectIdentifier ,
7972 t . identifier ( property )
8073 ) ;
8174
@@ -96,23 +89,47 @@ module.exports = function (babel) {
9689 visitor : {
9790 Program ( path , state ) {
9891 let options = state . opts || { } ;
99- let useEmberModule = options . useEmberModule || false ;
100-
101- if ( ! useEmberModule ) return ;
92+ let useEmberModule = Boolean ( options . useEmberModule ) ;
10293
103- let hasEmberImport = path
94+ let preexistingEmberImportDeclaration = path
10495 . get ( 'body' )
10596 . filter ( ( n ) => n . type === 'ImportDeclaration' )
10697 . find ( ( n ) => n . get ( 'source' ) . get ( 'value' ) . node === 'ember' ) ;
10798
108- if ( ! hasEmberImport ) {
109- path . unshiftContainer ( 'body' , emberImport ( t ) ) ;
99+ if (
100+ // an import was found
101+ preexistingEmberImportDeclaration &&
102+ // this accounts for `import from 'ember'` without a local identifier
103+ preexistingEmberImportDeclaration . node . specifiers . length > 0
104+ ) {
105+ state . emberIdentifier =
106+ preexistingEmberImportDeclaration . node . specifiers [ 0 ] . local ;
110107 }
108+
109+ state . ensureEmberImport = ( ) => {
110+ if ( ! useEmberModule ) {
111+ // ensures that we can always assume `state.emberIdentifier` is set
112+ state . emberIdentifier = t . identifier ( 'Ember' ) ;
113+ return ;
114+ }
115+
116+ if ( state . emberIdentifier ) return ;
117+
118+ state . emberIdentifier = path . scope . generateUidIdentifier ( 'Ember' ) ;
119+
120+ let emberImport = t . importDeclaration (
121+ [ t . importDefaultSpecifier ( state . emberIdentifier ) ] ,
122+ t . stringLiteral ( 'ember' )
123+ ) ;
124+
125+ path . unshiftContainer ( 'body' , emberImport ) ;
126+ } ;
111127 } ,
128+
112129 ImportDeclaration ( path , state ) {
113130 let options = state . opts || { } ;
114131 let ignore = options . ignore || [ ] ;
115- let useEmberModule = options . useEmberModule || false ;
132+ let useEmberModule = Boolean ( options . useEmberModule ) ;
116133 let node = path . node ;
117134 let declarations = [ ] ;
118135 let removals = [ ] ;
@@ -133,11 +150,8 @@ module.exports = function (babel) {
133150 if ( specifierPath ) {
134151 let local = specifierPath . node . local ;
135152
136- if ( useEmberModule ) {
137- if ( local . name === 'Ember' ) {
138- path . scope . rename ( EmberGlobalImportName ) ;
139- }
140- } else {
153+ // when `useEmberModule` is set, we don't need to do anything here
154+ if ( ! useEmberModule ) {
141155 if ( local . name !== 'Ember' ) {
142156 path . scope . rename ( local . name , 'Ember' ) ;
143157 }
@@ -202,12 +216,15 @@ module.exports = function (babel) {
202216
203217 removals . push ( specifierPath ) ;
204218
219+ // ensure that the Ember global is imported if needed
220+ state . ensureEmberImport ( ) ;
221+
205222 if (
206223 path . scope . bindings [ local . name ] . referencePaths . find (
207224 ( rp ) => rp . parent . type === 'ExportSpecifier'
208225 )
209226 ) {
210- // not safe to use path.scope.rename directly
227+ // not safe to use path.scope.rename directly when this identifier is being directly re-exported
211228 declarations . push (
212229 t . variableDeclaration ( 'var' , [
213230 t . variableDeclarator (
@@ -249,7 +266,10 @@ module.exports = function (babel) {
249266 // Replace the occurrences of the imported name with the global name.
250267 referencePaths . forEach ( ( referencePath ) => {
251268 if ( ! isTypescriptNode ( referencePath . parentPath ) ) {
252- const memberExpression = getMemberExpressionFor ( global ) ;
269+ const memberExpression = getMemberExpressionFor (
270+ global ,
271+ state . emberIdentifier
272+ ) ;
253273
254274 try {
255275 referencePath . replaceWith ( memberExpression ) ;
@@ -373,5 +393,3 @@ module.exports = function (babel) {
373393// Provide the path to the package's base directory for caching with broccoli
374394// Ref: https://github.com/babel/broccoli-babel-transpiler#caching
375395module . exports . baseDir = ( ) => path . resolve ( __dirname , '..' ) ;
376-
377- module . exports . uniqueishGlobalName = EmberGlobalImportName ;
0 commit comments