Skip to content

Commit ad1be75

Browse files
committed
parse.usesCommonJs() method, mainly for volo.
1 parent 13b93bd commit ad1be75

File tree

2 files changed

+99
-6
lines changed

2 files changed

+99
-6
lines changed

build/jslib/parse.js

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/*jslint plusplus: false, strict: false */
88
/*global define: false */
99

10-
define(['uglifyjs/index'], function (uglify) {
10+
define(['./uglifyjs/index'], function (uglify) {
1111
var parser = uglify.parser,
1212
processor = uglify.uglify,
1313
ostring = Object.prototype.toString,
@@ -469,6 +469,69 @@ define(['uglifyjs/index'], function (uglify) {
469469
return uses;
470470
};
471471

472+
473+
/**
474+
* Determines if require(''), exports.x =, and/or module.exports =
475+
* are used.
476+
*/
477+
parse.usesCommonJs = function (fileName, fileContents, options) {
478+
var uses = null,
479+
assignsExports = false,
480+
astRoot = parser.parse(fileContents);
481+
482+
parse.recurse(astRoot, function (prop) {
483+
if (prop === 'varExports') {
484+
assignsExports = true;
485+
} else if (prop !== 'exports' || !assignsExports) {
486+
if (!uses) {
487+
uses = {};
488+
}
489+
uses[prop] = true;
490+
}
491+
}, options, function (node, onMatch) {
492+
493+
var call, configNode, args;
494+
495+
if (!isArray(node)) {
496+
return false;
497+
}
498+
499+
if (node[0] === 'var' && node[1] && node[1][0] && node[1][0][0] === 'exports') {
500+
//Hmm, a variable assignment for exports, so does not use cjs exports.
501+
return onMatch('varExports');
502+
} else if (node[0] === 'assign' && node[2][0] === 'dot') {
503+
args = node[2][1];
504+
505+
if (args) {
506+
//An exports or module.exports assignment.
507+
if (args[0] === 'name' && args[1] === 'module' &&
508+
node[2][2] === 'exports') {
509+
return onMatch('moduleExports');
510+
} else if (args[0] === 'name' && args[1] === 'exports') {
511+
return onMatch('exports');
512+
}
513+
}
514+
} else if (node[0] === 'call') {
515+
call = node[1];
516+
args = node[2];
517+
518+
if (call) {
519+
//A require('') use.
520+
if (call[0] === 'name' && call[1] === 'require' &&
521+
args[0][0] === 'string') {
522+
return onMatch('require');
523+
}
524+
}
525+
}
526+
527+
return false;
528+
529+
});
530+
531+
return uses;
532+
};
533+
534+
472535
parse.findRequireDepNames = function (node, deps) {
473536
var moduleName, i, n, call, args;
474537

build/tests/parse.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ define(['parse', 'env!env/file'], function (parse, file) {
122122
);
123123
doh.run();
124124

125-
126125
doh.register('parseUsesAmdOrRequireJs',
127126
[
128127
function parseUsesAmdOrRequireJs(t) {
@@ -140,15 +139,46 @@ define(['parse', 'env!env/file'], function (parse, file) {
140139
t.is(true, parse.usesAmdOrRequireJs("good1", good1));
141140
t.is(true, parse.usesAmdOrRequireJs("good2", good2));
142141
t.is(true, parse.usesAmdOrRequireJs("good3", good3));
143-
t.is(true, parse.usesAmdOrRequireJs("good4", good3));
144-
t.is(true, parse.usesAmdOrRequireJs("good5", good3));
145-
t.is(true, parse.usesAmdOrRequireJs("good6", good3));
146-
t.is(true, parse.usesAmdOrRequireJs("good7", good3));
142+
t.is(true, parse.usesAmdOrRequireJs("good4", good4));
143+
t.is(true, parse.usesAmdOrRequireJs("good5", good5));
144+
t.is(true, parse.usesAmdOrRequireJs("good6", good6));
145+
t.is(true, parse.usesAmdOrRequireJs("good7", good7));
147146
t.is(false, parse.usesAmdOrRequireJs("bad1", bad1));
148147
t.is(false, parse.usesAmdOrRequireJs("bad2", bad2));
149148
}
150149
]
151150
);
152151
doh.run();
153152

153+
doh.register('parseUsesCommonJs',
154+
[
155+
function parseUsesCommonJs(t) {
156+
var good1 = "var dep = require('dep');",
157+
good2 = "something(); exports.foo = another();",
158+
good3 = "(function () { module.exports = function () {}; }());",
159+
good4 = "var a = require('a'); something(); exports.b = a;",
160+
161+
bad1 = "(function(){ if (typeof define === 'function' && define.amd) { define(['some'], function (some) {}) } }());",
162+
bad2 = "require(['something']);",
163+
bad3 = "var exports; exports.foo = 'bar';",
164+
bad4 = "var exports = function () {};",
165+
result;
166+
167+
t.is(true, parse.usesCommonJs("good1", good1).require);
168+
t.is(true, parse.usesCommonJs("good2", good2).exports);
169+
t.is(true, parse.usesCommonJs("good3", good3).moduleExports);
170+
171+
result = parse.usesCommonJs("good4", good4);
172+
t.is(true, result.require);
173+
t.is(true, result.exports);
174+
t.is(false, !!result.moduleExports);
175+
176+
t.is(null, parse.usesCommonJs("bad1", bad1));
177+
t.is(null, parse.usesCommonJs("bad2", bad2));
178+
t.is(null, parse.usesCommonJs("bad3", bad3));
179+
t.is(null, parse.usesCommonJs("bad4", bad4));
180+
}
181+
]
182+
);
183+
doh.run();
154184
});

0 commit comments

Comments
 (0)