@@ -20,17 +20,16 @@ const SAFE_CREATE_STYLE = '__create_style__';
2020const USE_EFFECT = 'useEffect' ;
2121const USE_STATE = 'useState' ;
2222const USE_CONTEXT = 'useContext' ;
23- const USE_HISTORY = 'useHistory' ;
24- const USE_LOCATION = 'useLocation' ;
23+ const USE_REF = 'useRef' ;
2524
2625const EXPORTED_DEF = '__def__' ;
27- const RUNTIME = '/npm/ jsx2mp-runtime' ;
26+ const RUNTIME = 'jsx2mp-runtime' ;
2827
28+ const getRuntimeByPlatform = ( platform ) => `${ RUNTIME } /dist/jsx2mp-runtime.${ platform } .esm` ;
2929const isAppRuntime = ( mod ) => mod === 'rax-app' ;
3030const isFileModule = ( mod ) => / \. ( p n g | j p e ? g | g i f | b m p | w e b p ) $ / . test ( mod ) ;
3131
32- const isHooksAPI = ( node ) => [ USE_EFFECT , USE_STATE , USE_CONTEXT ,
33- USE_HISTORY , USE_LOCATION ] . includes ( node . name ) ;
32+ const isCoreHooksAPI = ( node ) => [ USE_EFFECT , USE_STATE , USE_CONTEXT , USE_REF ] . includes ( node . name ) ;
3433
3534function getConstructor ( type ) {
3635 switch ( type ) {
@@ -50,13 +49,14 @@ function getConstructor(type) {
5049module . exports = {
5150 parse ( parsed , code , options ) {
5251 const { defaultExportedPath, eventHandlers = [ ] } = parsed ;
53- if ( options . type !== 'app' && ( ! defaultExportedPath || ! defaultExportedPath . node ) ) {
52+ const { platform, type, cwd, outputPath, sourcePath, resourcePath, disableCopyNpm } = options ;
53+ if ( type !== 'app' && ( ! defaultExportedPath || ! defaultExportedPath . node ) ) {
5454 // Can not found default export, otherwise app.js is excluded.
5555 return ;
5656 }
5757 let userDefineType ;
5858
59- if ( options . type === 'app' ) {
59+ if ( type === 'app' ) {
6060 userDefineType = 'function' ;
6161 } else if ( isFunctionComponent ( defaultExportedPath ) ) { // replace with class def.
6262 userDefineType = 'function' ;
@@ -91,28 +91,30 @@ module.exports = {
9191 }
9292
9393 const hooks = collectHooks ( parsed . renderFunctionPath ) ;
94-
95- const targetFileDir = dirname ( join ( options . outputPath , relative ( options . sourcePath , options . resourcePath ) ) ) ;
94+ const targetFileDir = dirname ( join ( outputPath , relative ( sourcePath , resourcePath ) ) ) ;
95+ const runtimePath = getRuntimePath ( outputPath , targetFileDir , platform , disableCopyNpm ) ;
9696
9797 removeRaxImports ( parsed . ast ) ;
98- renameCoreModule ( parsed . ast , options . outputPath , targetFileDir ) ;
98+ renameCoreModule ( parsed . ast , runtimePath ) ;
9999 renameFileModule ( parsed . ast ) ;
100- renameAppConfig ( parsed . ast , options . sourcePath , options . resourcePath ) ;
100+ renameAppConfig ( parsed . ast , sourcePath , resourcePath ) ;
101101
102- const currentNodeModulePath = join ( options . sourcePath , 'npm' ) ;
103- const npmRelativePath = relative ( dirname ( options . resourcePath ) , currentNodeModulePath ) ;
104- renameNpmModules ( parsed . ast , npmRelativePath , options . resourcePath , options . cwd ) ;
102+ if ( ! disableCopyNpm ) {
103+ const currentNodeModulePath = join ( sourcePath , 'npm' ) ;
104+ const npmRelativePath = relative ( dirname ( resourcePath ) , currentNodeModulePath ) ;
105+ renameNpmModules ( parsed . ast , npmRelativePath , resourcePath , cwd ) ;
106+ }
105107
106- if ( options . type !== 'app' ) {
107- addDefine ( parsed . ast , options . type , options . outputPath , targetFileDir , userDefineType , eventHandlers , parsed . useCreateStyle , hooks ) ;
108+ if ( type !== 'app' ) {
109+ addDefine ( parsed . ast , type , userDefineType , eventHandlers , parsed . useCreateStyle , hooks , runtimePath ) ;
108110 }
109111
110112 removeDefaultImports ( parsed . ast ) ;
111113
112114 /**
113115 * updateChildProps: collect props dependencies.
114116 */
115- if ( options . type !== 'app' && parsed . renderFunctionPath ) {
117+ if ( type !== 'app' && parsed . renderFunctionPath ) {
116118 const fnBody = parsed . renderFunctionPath . node . body . body ;
117119 let firstReturnStatementIdx = - 1 ;
118120 for ( let i = 0 , l = fnBody . length ; i < l ; i ++ ) {
@@ -159,6 +161,7 @@ module.exports = {
159161 addUpdateData ( parsed . dynamicValue , parsed . renderItemFunctions , parsed . renderFunctionPath ) ;
160162 addUpdateEvent ( parsed . dynamicEvents , parsed . eventHandler , parsed . renderFunctionPath ) ;
161163 addProviderIniter ( parsed . contextList , parsed . renderFunctionPath ) ;
164+ addRegisterRefs ( parsed . refs , parsed . renderFunctionPath ) ;
162165 }
163166 } ,
164167} ;
@@ -176,14 +179,21 @@ function genTagIdExp(expressions) {
176179 return parseExpression ( ret ) ;
177180}
178181
179- function renameCoreModule ( ast , outputPath , targetFileDir ) {
182+ function getRuntimePath ( outputPath , targetFileDir , platform , disableCopyNpm ) {
183+ let runtimePath = getRuntimeByPlatform ( platform . type ) ;
184+ if ( ! disableCopyNpm ) {
185+ runtimePath = relative ( targetFileDir , join ( outputPath , 'npm' , RUNTIME ) ) ;
186+ runtimePath = runtimePath [ 0 ] !== '.' ? './' + runtimePath : runtimePath ;
187+ }
188+ return runtimePath ;
189+ }
190+
191+ function renameCoreModule ( ast , runtimePath ) {
180192 traverse ( ast , {
181193 ImportDeclaration ( path ) {
182194 const source = path . get ( 'source' ) ;
183195 if ( source . isStringLiteral ( ) && isAppRuntime ( source . node . value ) ) {
184- let runtimeRelativePath = relative ( targetFileDir , join ( outputPath , RUNTIME ) ) ;
185- runtimeRelativePath = runtimeRelativePath [ 0 ] !== '.' ? './' + runtimeRelativePath : runtimeRelativePath ;
186- source . replaceWith ( t . stringLiteral ( runtimeRelativePath ) ) ;
196+ source . replaceWith ( t . stringLiteral ( runtimePath ) ) ;
187197 }
188198 }
189199 } ) ;
@@ -282,7 +292,7 @@ function renameNpmModules(ast, npmRelativePath, filename, cwd) {
282292 } ) ;
283293}
284294
285- function addDefine ( ast , type , outputPath , targetFileDir , userDefineType , eventHandlers , useCreateStyle , hooks ) {
295+ function addDefine ( ast , type , userDefineType , eventHandlers , useCreateStyle , hooks , runtimePath ) {
286296 let safeCreateInstanceId ;
287297 let importedIdentifier ;
288298 switch ( type ) {
@@ -323,13 +333,10 @@ function addDefine(ast, type, outputPath, targetFileDir, userDefineType, eventHa
323333 ) ) ;
324334 }
325335
326- let runtimeRelativePath = relative ( targetFileDir , join ( outputPath , RUNTIME ) ) ;
327- runtimeRelativePath = runtimeRelativePath [ 0 ] !== '.' ? './' + runtimeRelativePath : runtimeRelativePath ;
328-
329336 path . node . body . unshift (
330337 t . importDeclaration (
331338 specifiers ,
332- t . stringLiteral ( runtimeRelativePath )
339+ t . stringLiteral ( runtimePath )
333340 )
334341 ) ;
335342
@@ -405,7 +412,7 @@ function collectHooks(root) {
405412 traverse ( root , {
406413 CallExpression ( path ) {
407414 const { node } = path ;
408- if ( t . isIdentifier ( node . callee ) && isHooksAPI ( node . callee ) ) {
415+ if ( t . isIdentifier ( node . callee ) && isCoreHooksAPI ( node . callee ) ) {
409416 ret [ node . callee . name ] = true ;
410417 }
411418 }
@@ -468,6 +475,51 @@ function addProviderIniter(contextList, renderFunctionPath) {
468475 }
469476}
470477
478+ /**
479+ * Insert register ref method
480+ * @param {Array } refs
481+ * @param {Object } renderFunctionPath
482+ * */
483+ function addRegisterRefs ( refs , renderFunctionPath ) {
484+ const registerRefsMethods = t . memberExpression (
485+ t . thisExpression ( ) ,
486+ t . identifier ( '_registerRefs' )
487+ ) ;
488+ const fnBody = renderFunctionPath . node . body . body ;
489+ /**
490+ * this._registerRefs([
491+ * {
492+ * name: 'scrollViewRef',
493+ * method: scrollViewRef
494+ * }
495+ * ])
496+ * */
497+ const scopedRefs = [ ] ;
498+ const stringRefs = [ ] ;
499+ refs . map ( ref => {
500+ if ( renderFunctionPath . scope . hasBinding ( ref . value ) ) {
501+ scopedRefs . push ( ref ) ;
502+ } else {
503+ stringRefs . push ( ref ) ;
504+ }
505+ } ) ;
506+ if ( scopedRefs . length > 0 ) {
507+ fnBody . push ( t . expressionStatement ( t . callExpression ( registerRefsMethods , [
508+ t . arrayExpression ( scopedRefs . map ( ref => {
509+ return t . objectExpression ( [ t . objectProperty ( t . stringLiteral ( 'name' ) , ref ) ,
510+ t . objectProperty ( t . stringLiteral ( 'method' ) , t . identifier ( ref . value ) ) ] ) ;
511+ } ) )
512+ ] ) ) ) ;
513+ }
514+ if ( stringRefs . length > 0 ) {
515+ fnBody . unshift ( t . expressionStatement ( t . callExpression ( registerRefsMethods , [
516+ t . arrayExpression ( stringRefs . map ( ref => {
517+ return t . objectExpression ( [ t . objectProperty ( t . stringLiteral ( 'name' ) , ref ) ] ) ;
518+ } ) )
519+ ] ) ) ) ;
520+ }
521+ }
522+
471523/**
472524 * For that alipay build folder can not contain `@`, escape to `_`.
473525 */
0 commit comments