@@ -37,31 +37,46 @@ define(['uglifyjs/index'], function (uglify) {
37
37
38
38
/**
39
39
* Validates a node as being an object literal (like for i18n bundles)
40
- * or an array literal with just string members.
40
+ * or an array literal with just string members. If an array literal,
41
+ * only return array members that are full strings. So the caller of
42
+ * this function should use the return value as the new value for the
43
+ * node.
44
+ *
41
45
* This function does not need to worry about comments, they are not
42
46
* present in this AST.
47
+ *
48
+ * @param {Node } node an AST node.
49
+ *
50
+ * @returns {Node } an AST node to use for the valid dependencies.
51
+ * If null is returned, then it means the input node was not a valid
52
+ * dependency.
43
53
*/
44
54
function validateDeps ( node ) {
45
- var arrayArgs , i , dep ;
55
+ var newDeps = [ 'array' , [ ] ] ,
56
+ arrayArgs , i , dep ;
57
+
58
+ if ( ! node ) {
59
+ return null ;
60
+ }
46
61
47
62
if ( isObjectLiteral ( node ) || node [ 0 ] === 'function' ) {
48
- return true ;
63
+ return node ;
49
64
}
50
65
51
66
//Dependencies can be an object literal or an array.
52
67
if ( ! isArrayLiteral ( node ) ) {
53
- return false ;
68
+ return null ;
54
69
}
55
70
56
71
arrayArgs = node [ 1 ] ;
57
72
58
73
for ( i = 0 ; i < arrayArgs . length ; i ++ ) {
59
74
dep = arrayArgs [ i ] ;
60
- if ( dep [ 0 ] ! == 'string' ) {
61
- return false ;
75
+ if ( dep [ 0 ] = == 'string' ) {
76
+ newDeps [ 1 ] . push ( dep ) ;
62
77
}
63
78
}
64
- return true ;
79
+ return newDeps [ 1 ] . length ? newDeps : null ;
65
80
}
66
81
67
82
/**
@@ -77,7 +92,12 @@ define(['uglifyjs/index'], function (uglify) {
77
92
var matches = [ ] , result = null ,
78
93
astRoot = parser . parse ( fileContents ) ;
79
94
80
- parse . recurse ( astRoot , matches ) ;
95
+ parse . recurse ( astRoot , function ( ) {
96
+ var parsed = parse . callToString . apply ( parse , arguments ) ;
97
+ if ( parsed ) {
98
+ matches . push ( parsed ) ;
99
+ }
100
+ } ) ;
81
101
82
102
if ( matches . length ) {
83
103
result = matches . join ( "\n" ) ;
@@ -94,19 +114,16 @@ define(['uglifyjs/index'], function (uglify) {
94
114
/**
95
115
* Handles parsing a file recursively for require calls.
96
116
* @param {Array } parentNode the AST node to start with.
97
- * @param {Array } matches where to store the string matches
117
+ * @param {Function } onMatch function to call on a parse match.
98
118
*/
99
- parse . recurse = function ( parentNode , matches ) {
100
- var i , node , parsed ;
119
+ parse . recurse = function ( parentNode , onMatch ) {
120
+ var i , node ;
101
121
if ( isArray ( parentNode ) ) {
102
122
for ( i = 0 ; i < parentNode . length ; i ++ ) {
103
123
node = parentNode [ i ] ;
104
124
if ( isArray ( node ) ) {
105
- parsed = this . parseNode ( node ) ;
106
- if ( parsed ) {
107
- matches . push ( parsed ) ;
108
- }
109
- this . recurse ( node , matches ) ;
125
+ this . parseNode ( node , onMatch ) ;
126
+ this . recurse ( node , onMatch ) ;
110
127
}
111
128
}
112
129
}
@@ -192,6 +209,42 @@ define(['uglifyjs/index'], function (uglify) {
192
209
return null ;
193
210
} ;
194
211
212
+ /**
213
+ * Finds all dependencies specified in dependency arrays and inside
214
+ * simplified commonjs wrappers.
215
+ * @param {String } fileName
216
+ * @param {String } fileContents
217
+ *
218
+ * @returns {Array } an array of dependency strings. The dependencies
219
+ * have not been normalized, they may be relative IDs.
220
+ */
221
+ parse . findDependencies = function ( fileName , fileContents ) {
222
+ //This is a litle bit inefficient, it ends up with two uglifyjs parser
223
+ //calls. Can revisit later, but trying to build out larger functional
224
+ //pieces first.
225
+ var dependencies = parse . getAnonDeps ( fileName , fileContents ) ,
226
+ astRoot = parser . parse ( fileContents ) ,
227
+ i , dep ;
228
+
229
+ parse . recurse ( astRoot , function ( callName , config , name , deps ) {
230
+ //Normalize the input args.
231
+ if ( name && isArrayLiteral ( name ) ) {
232
+ deps = name ;
233
+ name = null ;
234
+ }
235
+
236
+ if ( ! ( deps = validateDeps ( deps ) ) || ! isArrayLiteral ( deps ) ) {
237
+ return ;
238
+ }
239
+
240
+ for ( i = 0 ; ( dep = deps [ 1 ] [ i ] ) ; i ++ ) {
241
+ dependencies . push ( dep [ 1 ] ) ;
242
+ }
243
+ } ) ;
244
+
245
+ return dependencies ;
246
+ } ;
247
+
195
248
parse . findRequireDepNames = function ( node , deps ) {
196
249
var moduleName , i , n , call , args ;
197
250
@@ -291,7 +344,7 @@ define(['uglifyjs/index'], function (uglify) {
291
344
name = null ;
292
345
}
293
346
294
- if ( deps && ! validateDeps ( deps ) ) {
347
+ if ( ! ( deps = validateDeps ( deps ) ) ) {
295
348
return null ;
296
349
}
297
350
@@ -311,11 +364,14 @@ define(['uglifyjs/index'], function (uglify) {
311
364
/**
312
365
* Determines if a specific node is a valid require or define/require.def call.
313
366
* @param {Array } node
367
+ * @param {Function } onMatch a function to call when a match is found.
368
+ * It is passed the match name, and the config, name, deps possible args.
369
+ * The config, name and deps args are not normalized.
314
370
*
315
371
* @returns {String } a JS source string with the valid require/define call.
316
372
* Otherwise null.
317
373
*/
318
- parse . parseNode = function ( node ) {
374
+ parse . parseNode = function ( node , onMatch ) {
319
375
var call , name , config , deps , args ;
320
376
321
377
if ( ! isArray ( node ) ) {
@@ -337,11 +393,11 @@ define(['uglifyjs/index'], function (uglify) {
337
393
config = null ;
338
394
}
339
395
340
- if ( ! deps || ! validateDeps ( deps ) ) {
396
+ if ( ! ( deps = validateDeps ( deps ) ) ) {
341
397
return null ;
342
398
}
343
399
344
- return this . callToString ( "require" , null , null , deps ) ;
400
+ return onMatch ( "require" , null , null , deps ) ;
345
401
346
402
} else if ( ( call [ 0 ] === 'name' && call [ 1 ] === 'define' ) ||
347
403
( call [ 0 ] === 'dot' && call [ 1 ] [ 1 ] === 'require' &&
@@ -364,7 +420,7 @@ define(['uglifyjs/index'], function (uglify) {
364
420
name [ 0 ] === 'function' || isObjectLiteral ( name ) ) ) &&
365
421
( ! deps || isArrayLiteral ( deps ) ||
366
422
deps [ 0 ] === 'function' || isObjectLiteral ( deps ) ) ) {
367
- return this . callToString ( "define" , null , name , deps ) ;
423
+ return onMatch ( "define" , null , name , deps ) ;
368
424
}
369
425
}
370
426
}
0 commit comments