1 |
|
2 |
|
3 |
|
4 |
|
5 | var estraverse = require('estraverse');
|
6 | var optionsNormalize = require('./options_normalize');
|
7 | var getAst = require("./get_ast");
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | module.exports = function (load, options) {
|
26 |
|
27 | var ast = getAst(load);
|
28 | var tast;
|
29 | var isAMD = false;
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | estraverse.replace(ast, {
|
38 | enter: function(node) {
|
39 | if (isDefine(node)) {
|
40 | var parents = this.parents();
|
41 |
|
42 |
|
43 |
|
44 |
|
45 | if (parents.length == 2 && parents[0].type == 'Program' && parents[1].type == 'ExpressionStatement') {
|
46 | isAMD = true;
|
47 | }
|
48 | }
|
49 | },
|
50 |
|
51 | leave: function(node) {
|
52 | if (isDefine(node)) {
|
53 | var ids;
|
54 | var vars;
|
55 | var reqs;
|
56 | var factory;
|
57 | var dependencies;
|
58 |
|
59 | if (node.arguments.length == 1 && node.arguments[0].type == 'FunctionExpression') {
|
60 | factory = node.arguments[0];
|
61 |
|
62 | if (factory.params.length == 0) {
|
63 | tast = createProgram(factory.body.body);
|
64 | this.break();
|
65 | } else if (factory.params.length > 0) {
|
66 |
|
67 | tast = createProgram(factory.body.body);
|
68 | this.break();
|
69 | }
|
70 | } else if (node.arguments.length == 1 && node.arguments[0].type == 'ObjectExpression') {
|
71 |
|
72 | var obj = node.arguments[0];
|
73 |
|
74 | tast = createModuleExport(obj);
|
75 | this.break();
|
76 | } else if (node.arguments.length == 2 && node.arguments[0].type == 'ArrayExpression' && node.arguments[1].type == 'FunctionExpression') {
|
77 | dependencies = node.arguments[0];
|
78 | factory = node.arguments[1];
|
79 |
|
80 | ids = dependencies.elements.map(function(el) { return el.value });
|
81 | vars = factory.params.map(function(el) { return el.name });
|
82 | reqs = createRequires(ids, vars, load, options);
|
83 | if (reqs) {
|
84 | tast = createProgram(reqs.concat(factory.body.body));
|
85 | } else {
|
86 | tast = createProgram(factory.body.body);
|
87 | }
|
88 | this.break();
|
89 | } else if (node.arguments.length == 3 && node.arguments[0].type == 'Literal' && node.arguments[1].type == 'ArrayExpression' && node.arguments[2].type == 'FunctionExpression') {
|
90 | dependencies = node.arguments[1]
|
91 | factory = node.arguments[2];
|
92 |
|
93 | ids = dependencies.elements.map(function(el) { return el.value });
|
94 | vars = factory.params.map(function(el) { return el.name });
|
95 | reqs = createRequires(ids, vars, load, options);
|
96 | if (reqs) {
|
97 | tast = createProgram(reqs.concat(factory.body.body));
|
98 | } else {
|
99 | tast = createProgram(factory.body.body);
|
100 | }
|
101 | this.break();
|
102 | }
|
103 | } else if (isReturn(node)) {
|
104 | var parents = this.parents();
|
105 |
|
106 | if (parents.length == 5 && isDefine(parents[2]) && isAMD) {
|
107 | return createModuleExport(node.argument);
|
108 | }
|
109 | }
|
110 | }
|
111 | });
|
112 |
|
113 | tast = tast || ast;
|
114 |
|
115 | return tast;
|
116 | };
|
117 |
|
118 | function isDefine(node) {
|
119 | var callee = node.callee;
|
120 | return callee &&
|
121 | node.type == 'CallExpression' &&
|
122 | callee.type == 'Identifier' &&
|
123 | callee.name == 'define';
|
124 | }
|
125 |
|
126 | function isReturn(node) {
|
127 | return node.type == 'ReturnStatement';
|
128 | }
|
129 |
|
130 | function createProgram(body) {
|
131 | return {
|
132 | type: 'Program',
|
133 | body: body
|
134 | };
|
135 | }
|
136 |
|
137 | function createRequires(ids, vars, load, options) {
|
138 | var decls = [];
|
139 |
|
140 | for (var i = 0, len = ids.length; i < len; ++i) {
|
141 | if (['require', 'module', 'exports'].indexOf(ids[i]) != -1) { continue; }
|
142 |
|
143 | if(vars[i]) {
|
144 | decls.push({
|
145 | type: 'VariableDeclaration',
|
146 | declarations: [{
|
147 | type: 'VariableDeclarator',
|
148 | id: { type: 'Identifier', name: vars[i] },
|
149 | init: {
|
150 | type: 'CallExpression',
|
151 | callee: { type: 'Identifier', name: 'require' },
|
152 | arguments: [ { type: 'Literal', value: optionsNormalize(options, ids[i], load.name, load.address) } ]
|
153 | }
|
154 | }],
|
155 | kind: 'var'
|
156 | });
|
157 | } else {
|
158 | decls.push({
|
159 | "type": "ExpressionStatement",
|
160 | "expression": {
|
161 | "type": "CallExpression",
|
162 | "callee": {
|
163 | "type": "Identifier",
|
164 | "name": "require"
|
165 | },
|
166 | "arguments": [
|
167 | {
|
168 | "type": "Literal",
|
169 | "value": optionsNormalize(options, ids[i], load.name, load.address)
|
170 | }
|
171 | ]
|
172 | }
|
173 | });
|
174 | }
|
175 | }
|
176 |
|
177 | if (decls.length == 0) { return null; }
|
178 |
|
179 | return decls;
|
180 | }
|
181 |
|
182 | function createModuleExport(obj) {
|
183 | return {
|
184 | type: 'ExpressionStatement',
|
185 | expression: {
|
186 | type: 'AssignmentExpression',
|
187 | operator: '=',
|
188 | left: {
|
189 | type: 'MemberExpression',
|
190 | computed: false,
|
191 | object: { type: 'Identifier', name: 'module' },
|
192 | property: { type: 'Identifier', name: 'exports' }
|
193 | },
|
194 | right: obj
|
195 | }
|
196 | };
|
197 | }
|