1+ const { babel } = require ( "@rollup/plugin-babel" )
2+
3+
14function addImportDeclarationToProgram ( types , program , specifier , imported , source ) {
25 program . node . body . unshift (
36 types . importDeclaration (
@@ -18,15 +21,43 @@ function addStatementToFunction(types, path, statement) {
1821 }
1922}
2023
24+ function getMergePropsUniqueName ( types , path , program ) {
25+ let mergePropsUniqueName
26+ // Look for `mergeProps` import
27+ program . traverse ( {
28+ ImportDeclaration ( path ) {
29+ if ( path . node . source . value !== "solid-js" ) return
30+ for ( const specifier of path . node . specifiers )
31+ if (
32+ specifier . imported
33+ && specifier . imported . name === "mergeProps"
34+ && specifier . local . unique
35+ ) {
36+ mergePropsUniqueName = specifier . local
37+ return
38+ }
39+ }
40+ } )
41+
42+ // If not found, create one
43+ if ( ! mergePropsUniqueName ) {
44+ mergePropsUniqueName = program . scope . generateUidIdentifier ( "mergeProps" )
45+ mergePropsUniqueName . unique = true
46+ addImportDeclarationToProgram ( types , program , mergePropsUniqueName , "mergeProps" , "solid-js" )
47+ }
48+
49+ return mergePropsUniqueName
50+ }
51+
2152const functionVisitor = types => ( path , { opts } ) => {
2253 {
2354 const { mode = 'vanilla-js' } = opts
24-
55+
2556 if ( mode !== 'ts' && mode !== 'vanilla-js' )
2657 throw new Error ( "babel-plugin-solid-undestructure error: Invalid configuration - mode must be either 'ts' or 'vanilla-js'." )
2758
2859 const type = path . type
29-
60+
3061 if ( mode === 'ts' ) {
3162 if ( type !== "ArrowFunctionExpression" ) return
3263 if ( path . parent . type !== "VariableDeclarator" ) return
@@ -74,84 +105,70 @@ const functionVisitor = types => (path, { opts }) => {
74105 }
75106 }
76107
108+ let mergePropsUniqueName
109+ let defaultPropsObject = types . objectExpression ( [ ] )
110+
77111 let firstParam = path . node . params [ 0 ]
78112 if (
79- ! firstParam
80- || (
81- firstParam . type !== "ObjectPattern"
82- && firstParam . type !== "AssignmentPattern"
113+ ! firstParam
114+ || (
115+ firstParam . type !== "ObjectPattern"
116+ && (
117+ firstParam . type !== "AssignmentPattern"
118+ || firstParam . left . type !== "ObjectPattern"
119+ )
83120 )
84121 ) return
85-
122+
123+ const program = path . findParent ( path => path . isProgram ( ) )
124+ const newPropsIdentifier = program . scope . generateUidIdentifier ( "props" )
125+
86126 let defaultPropsWhole = types . objectExpression ( [ ] )
87127 if ( firstParam . type == "AssignmentPattern" ) {
88128 defaultPropsWhole = firstParam . right
89129 firstParam = firstParam . left
130+
131+ mergePropsUniqueName = getMergePropsUniqueName ( types , path , program )
132+
133+ const callExpression = types . callExpression ( mergePropsUniqueName , [ defaultPropsWhole , defaultPropsObject , newPropsIdentifier ] )
134+ const assignmentStatement = types . expressionStatement ( types . assignmentExpression ( "=" , newPropsIdentifier , callExpression ) )
135+ addStatementToFunction ( types , path , assignmentStatement )
90136 }
91137
92- const program = path . findParent ( path => path . isProgram ( ) )
93- const newPropsIdentifier = program . scope . generateUidIdentifier ( "props" )
94-
95138 const propsDestructredProperties = firstParam . properties
96139 const componentScopeBindings = path . scope . bindings
97-
98- let defaultPropsObject
99-
140+
100141 for ( const DestructredProperty of propsDestructredProperties ) {
101142 if ( DestructredProperty . type === "RestElement" ) throw new Error ( "babel-plugin-solid-undestructure error: Rest elements are not supported." )
102143 if (
103- (
144+ (
104145 // Nested destructuring
105- DestructredProperty . value . type !== "Identifier"
106- && DestructredProperty . value . type !== "AssignmentPattern"
146+ DestructredProperty . value . type !== "Identifier"
147+ && DestructredProperty . value . type !== "AssignmentPattern"
107148 )
108- || (
149+ || (
109150 // Nested destructuring + default value
110151 DestructredProperty . value . type !== "Identifier"
111152 && DestructredProperty . value . left . type !== "Identifier"
112153 )
113154 )
114- throw new Error ( "babel-plugin-solid-undestructure error: Nested destructuring is not supported." )
115-
155+ throw new Error ( "babel-plugin-solid-undestructure error: Nested destructuring is not supported." )
156+
116157 // Handle default props
117158 if ( DestructredProperty . value . type === "AssignmentPattern" ) {
118- if ( ! defaultPropsObject ) {
119- // Look for `mergeProps` import
120- let mergePropsUniqueName
121- program . traverse ( {
122- ImportDeclaration ( path ) {
123- if ( mergePropsUniqueName || path . node . source . value !== "solid-js" ) return
124- for ( const specifier of path . node . specifiers )
125- if (
126- specifier . imported
127- && specifier . imported . name === "mergeProps"
128- && specifier . local . unique
129- ) {
130- mergePropsUniqueName = specifier . local
131- return
132- }
133- }
134- } )
135-
136- // If not found, create one
137- if ( ! mergePropsUniqueName ) {
138- mergePropsUniqueName = program . scope . generateUidIdentifier ( "mergeProps" )
139- mergePropsUniqueName . unique = true
140- addImportDeclarationToProgram ( types , program , mergePropsUniqueName , "mergeProps" , "solid-js" )
141- }
159+ if ( ! mergePropsUniqueName ) {
160+ mergePropsUniqueName = getMergePropsUniqueName ( types , path , program )
142161
143- defaultPropsObject = types . objectExpression ( [ types . objectProperty ( DestructredProperty . value . left , DestructredProperty . value . right ) ] )
144162 const callExpression = types . callExpression ( mergePropsUniqueName , [ defaultPropsWhole , defaultPropsObject , newPropsIdentifier ] )
145163 const assignmentStatement = types . expressionStatement ( types . assignmentExpression ( "=" , newPropsIdentifier , callExpression ) )
146164 addStatementToFunction ( types , path , assignmentStatement )
147165 }
148-
149- else defaultPropsObject . properties . push ( types . objectProperty ( DestructredProperty . value . left , DestructredProperty . value . right ) )
166+
167+ defaultPropsObject . properties . push ( types . objectProperty ( DestructredProperty . value . left , DestructredProperty . value . right ) )
150168 }
151-
169+
152170 const DestructredKeyIdentifier = DestructredProperty . key
153- const undestructuredPropExpression =
154- types . memberExpression ( newPropsIdentifier , DestructredKeyIdentifier )
171+ const undestructuredPropExpression = types . memberExpression ( newPropsIdentifier , DestructredKeyIdentifier )
155172
156173 const DestructredName = DestructredProperty . value . name || DestructredProperty . value . left . name
157174
@@ -165,12 +182,12 @@ const functionVisitor = types => (path, { opts }) => {
165182 for ( const constantViolation of constantViolations )
166183 constantViolation . node && ( constantViolation . node . left = undestructuredPropExpression )
167184 }
168-
185+
169186 path . node . params [ 0 ] = newPropsIdentifier
170187}
171-
172-
173- module . exports = function babelPluginUndestructure ( { types } ) {
188+
189+
190+ module . exports = function babelPluginUndestructure ( { types } ) {
174191 const visitor = {
175192 FunctionDeclaration : functionVisitor ( types ) ,
176193 FunctionExpression : functionVisitor ( types ) ,
@@ -212,4 +229,4 @@ module.exports.undestructurePlugin = mode => {
212229 return [ "babel-plugin-solid-undestructure" , { mode : "vanilla-js" } ]
213230
214231 else throw new Error ( "babel-plugin-solid-undestructure error: Invalid mode. Mode must be either 'ts' or 'vanilla-js'" )
215- }
232+ }
0 commit comments