@@ -2,13 +2,15 @@ const nodePath = require('path')
22const t = require ( '@babel/types' )
33const template = require ( '@babel/template' ) . default
44const { GLOBAL_NAME , LOCAL_NAME } = require ( '@cssxjs/runtime/constants' )
5+ const { addNamed } = require ( '@babel/helper-module-imports' )
56
67const COMPILERS = [ 'css' , 'styl' , 'pug' ] // used in rn-stylename-inline. TODO: move to a shared place
78const RUNTIME_LIBRARY = 'cssxjs/runtime'
89const STYLE_NAME_REGEX = / (?: ^ s | S ) t y l e N a m e $ /
910const STYLE_REGEX = / (?: ^ s | S ) t y l e $ /
1011const ROOT_STYLE_PROP_NAME = 'style'
11- const RUNTIME_PROCESS_NAME = 'cssx'
12+ const RUNTIME_IMPORT_NAME = 'runtime'
13+ const RUNTIME_FRIENDLY_NAME = 'cssx'
1214const OPTIONS_CACHE = [ 'teamplay' ]
1315const OPTIONS_REACT_TYPES = [ 'react-native' , 'web' ]
1416const DEFAULT_MAGIC_IMPORTS = [ 'cssxjs' , 'startupjs' ]
@@ -19,30 +21,52 @@ const buildSafeVar = template.expression(`
1921 typeof %%variable%% !== 'undefined' && %%variable%%
2022` )
2123
22- const buildImport = template ( `
23- import %%name%% from %%runtimePath%%
24- ` )
25-
26- const buildRequire = template ( `
27- const %%name%% = require(%%runtimePath%%)
28- ` )
29-
3024const buildJsonParse = template ( `
3125 const %%name%% = JSON.parse(%%jsonStyle%%)
3226` )
3327
28+ const buildRuntimeVar = template ( `
29+ const %%name%% = %%imported%%
30+ ` )
31+
3432module . exports = function ( babel ) {
3533 let styleHash = { }
3634 let cssIdentifier
3735 let hasObserver
3836 let $program
3937 let usedCompilers
38+ let runtime
39+
40+ function getOrCreateRuntime ( state ) {
41+ if ( runtime ) return runtime
42+ const runtimePath = getRuntimePath ( $program , state , hasObserver )
43+ // when using addDefault for some reason Expo doesn't keep the imported variable correctly,
44+ // because of this we hack it by importing first and then assigning to a const with the final name
45+ // used later in the code to call the runtime function.
46+ const imported = addNamedImport ( $program , RUNTIME_IMPORT_NAME , runtimePath )
47+ runtime = $program . scope . generateUidIdentifier ( RUNTIME_FRIENDLY_NAME )
48+
49+ const expression = buildRuntimeVar ( {
50+ name : runtime ,
51+ imported
52+ } )
53+ const lastImport = $program
54+ . get ( 'body' )
55+ . filter ( p => p . isImportDeclaration ( ) )
56+ . pop ( )
57+ if ( lastImport ) {
58+ lastImport . insertAfter ( expression )
59+ } else {
60+ $program . unshiftContainer ( 'body' , expression )
61+ }
62+
63+ return runtime
64+ }
4065
4166 function getStyleFromExpression ( expression , state ) {
42- state . hasTransformedClassName = true
4367 const cssStyles = cssIdentifier . name
4468 const processCall = t . callExpression (
45- state . reqName ,
69+ getOrCreateRuntime ( state ) ,
4670 [ expression , t . identifier ( cssStyles ) ]
4771 )
4872 return processCall
@@ -153,9 +177,8 @@ module.exports = function (babel) {
153177 }
154178
155179 // Create a `process` function call
156- state . hasTransformedClassName = true
157180 const processCall = t . callExpression (
158- state . reqName ,
181+ getOrCreateRuntime ( state ) ,
159182 [
160183 styleName
161184 ? (
@@ -246,14 +269,14 @@ module.exports = function (babel) {
246269 hasObserver = undefined
247270 $program = undefined
248271 usedCompilers = undefined
272+ runtime = undefined
249273 } ,
250274 visitor : {
251275 Program : {
252276 // TODO: Refactor this to move the sub-visitor out into getVisitor() function
253277 enter ( $this , state ) {
254278 // 1. Init
255279 usedCompilers = getUsedCompilers ( $this , state )
256- state . reqName = $this . scope . generateUidIdentifier ( RUNTIME_PROCESS_NAME )
257280 $program = $this
258281
259282 // 2. Run early traversal of everything
@@ -364,9 +387,8 @@ module.exports = function (babel) {
364387 if ( ! $callee . isIdentifier ( ) ) return
365388 if ( ! usedCompilers . has ( $callee . node . name ) ) return
366389 // Create a `process` function call
367- state . hasTransformedClassName = true
368390 const processCall = t . callExpression (
369- state . reqName ,
391+ getOrCreateRuntime ( state ) ,
370392 [
371393 $this . get ( 'arguments.0' )
372394 ? $this . get ( 'arguments.0' ) . node
@@ -384,26 +406,6 @@ module.exports = function (babel) {
384406 $this . replaceWith ( processCall )
385407 }
386408 } , state )
387-
388- // 3. Finalize
389- if ( ! state . hasTransformedClassName ) {
390- return
391- }
392-
393- const lastImportOrRequire = $this
394- . get ( 'body' )
395- . filter ( p => p . isImportDeclaration ( ) || isRequire ( p . node ) )
396- . pop ( )
397-
398- if ( lastImportOrRequire ) {
399- const useImport = state . opts . useImport == null ? true : state . opts . useImport
400- const runtimePath = getRuntimePath ( $this , state , hasObserver )
401- lastImportOrRequire . insertAfter (
402- useImport
403- ? buildImport ( { name : state . reqName , runtimePath : t . stringLiteral ( runtimePath ) } )
404- : buildRequire ( { name : state . reqName , runtimePath : t . stringLiteral ( runtimePath ) } )
405- )
406- }
407409 }
408410 }
409411 }
@@ -582,3 +584,10 @@ function getRuntimePath ($node, state, hasObserver) {
582584 }
583585 return runtimePath
584586}
587+
588+ function addNamedImport ( $program , name , sourceName ) {
589+ return addNamed ( $program , name , sourceName , {
590+ importedType : 'es6' ,
591+ importPosition : 'after'
592+ } )
593+ }
0 commit comments