Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80743 views
1
/***********************************************************************
2
3
A JavaScript tokenizer / parser / beautifier / compressor.
4
https://github.com/mishoo/UglifyJS2
5
6
-------------------------------- (C) ---------------------------------
7
8
Author: Mihai Bazon
9
<[email protected]>
10
http://mihai.bazon.net/blog
11
12
Distributed under the BSD license:
13
14
Copyright 2012 (c) Mihai Bazon <[email protected]>
15
16
Redistribution and use in source and binary forms, with or without
17
modification, are permitted provided that the following conditions
18
are met:
19
20
* Redistributions of source code must retain the above
21
copyright notice, this list of conditions and the following
22
disclaimer.
23
24
* Redistributions in binary form must reproduce the above
25
copyright notice, this list of conditions and the following
26
disclaimer in the documentation and/or other materials
27
provided with the distribution.
28
29
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
30
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
33
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
34
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
35
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
36
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
38
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
39
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40
SUCH DAMAGE.
41
42
***********************************************************************/
43
44
"use strict";
45
46
(function(){
47
48
var MOZ_TO_ME = {
49
ExpressionStatement: function(M) {
50
var expr = M.expression;
51
if (expr.type === "Literal" && typeof expr.value === "string") {
52
return new AST_Directive({
53
start: my_start_token(M),
54
end: my_end_token(M),
55
value: expr.value
56
});
57
}
58
return new AST_SimpleStatement({
59
start: my_start_token(M),
60
end: my_end_token(M),
61
body: from_moz(expr)
62
});
63
},
64
TryStatement: function(M) {
65
var handlers = M.handlers || [M.handler];
66
if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
67
throw new Error("Multiple catch clauses are not supported.");
68
}
69
return new AST_Try({
70
start : my_start_token(M),
71
end : my_end_token(M),
72
body : from_moz(M.block).body,
73
bcatch : from_moz(handlers[0]),
74
bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
75
});
76
},
77
Property: function(M) {
78
var key = M.key;
79
var name = key.type == "Identifier" ? key.name : key.value;
80
var args = {
81
start : my_start_token(key),
82
end : my_end_token(M.value),
83
key : name,
84
value : from_moz(M.value)
85
};
86
switch (M.kind) {
87
case "init":
88
return new AST_ObjectKeyVal(args);
89
case "set":
90
args.value.name = from_moz(key);
91
return new AST_ObjectSetter(args);
92
case "get":
93
args.value.name = from_moz(key);
94
return new AST_ObjectGetter(args);
95
}
96
},
97
ObjectExpression: function(M) {
98
return new AST_Object({
99
start : my_start_token(M),
100
end : my_end_token(M),
101
properties : M.properties.map(function(prop){
102
prop.type = "Property";
103
return from_moz(prop)
104
})
105
});
106
},
107
SequenceExpression: function(M) {
108
return AST_Seq.from_array(M.expressions.map(from_moz));
109
},
110
MemberExpression: function(M) {
111
return new (M.computed ? AST_Sub : AST_Dot)({
112
start : my_start_token(M),
113
end : my_end_token(M),
114
property : M.computed ? from_moz(M.property) : M.property.name,
115
expression : from_moz(M.object)
116
});
117
},
118
SwitchCase: function(M) {
119
return new (M.test ? AST_Case : AST_Default)({
120
start : my_start_token(M),
121
end : my_end_token(M),
122
expression : from_moz(M.test),
123
body : M.consequent.map(from_moz)
124
});
125
},
126
VariableDeclaration: function(M) {
127
return new (M.kind === "const" ? AST_Const : AST_Var)({
128
start : my_start_token(M),
129
end : my_end_token(M),
130
definitions : M.declarations.map(from_moz)
131
});
132
},
133
Literal: function(M) {
134
var val = M.value, args = {
135
start : my_start_token(M),
136
end : my_end_token(M)
137
};
138
if (val === null) return new AST_Null(args);
139
switch (typeof val) {
140
case "string":
141
args.value = val;
142
return new AST_String(args);
143
case "number":
144
args.value = val;
145
return new AST_Number(args);
146
case "boolean":
147
return new (val ? AST_True : AST_False)(args);
148
default:
149
args.value = val;
150
return new AST_RegExp(args);
151
}
152
},
153
Identifier: function(M) {
154
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
155
return new ( p.type == "LabeledStatement" ? AST_Label
156
: p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
157
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
158
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
159
: p.type == "CatchClause" ? AST_SymbolCatch
160
: p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef
161
: AST_SymbolRef)({
162
start : my_start_token(M),
163
end : my_end_token(M),
164
name : M.name
165
});
166
}
167
};
168
169
MOZ_TO_ME.UpdateExpression =
170
MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
171
var prefix = "prefix" in M ? M.prefix
172
: M.type == "UnaryExpression" ? true : false;
173
return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
174
start : my_start_token(M),
175
end : my_end_token(M),
176
operator : M.operator,
177
expression : from_moz(M.argument)
178
});
179
};
180
181
map("Program", AST_Toplevel, "body@body");
182
map("EmptyStatement", AST_EmptyStatement);
183
map("BlockStatement", AST_BlockStatement, "body@body");
184
map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
185
map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
186
map("BreakStatement", AST_Break, "label>label");
187
map("ContinueStatement", AST_Continue, "label>label");
188
map("WithStatement", AST_With, "object>expression, body>body");
189
map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
190
map("ReturnStatement", AST_Return, "argument>value");
191
map("ThrowStatement", AST_Throw, "argument>value");
192
map("WhileStatement", AST_While, "test>condition, body>body");
193
map("DoWhileStatement", AST_Do, "test>condition, body>body");
194
map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
195
map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
196
map("DebuggerStatement", AST_Debugger);
197
map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
198
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
199
map("CatchClause", AST_Catch, "param>argname, body%body");
200
201
map("ThisExpression", AST_This);
202
map("ArrayExpression", AST_Array, "elements@elements");
203
map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
204
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
205
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
206
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
207
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
208
map("NewExpression", AST_New, "callee>expression, arguments@args");
209
map("CallExpression", AST_Call, "callee>expression, arguments@args");
210
211
def_to_moz(AST_Directive, function To_Moz_Directive(M) {
212
return {
213
type: "ExpressionStatement",
214
expression: {
215
type: "Literal",
216
value: M.value
217
}
218
};
219
});
220
221
def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
222
return {
223
type: "ExpressionStatement",
224
expression: to_moz(M.body)
225
};
226
});
227
228
def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
229
return {
230
type: "SwitchCase",
231
test: to_moz(M.expression),
232
consequent: M.body.map(to_moz)
233
};
234
});
235
236
def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
237
return {
238
type: "TryStatement",
239
block: to_moz_block(M),
240
handler: to_moz(M.bcatch),
241
guardedHandlers: [],
242
finalizer: to_moz(M.bfinally)
243
};
244
});
245
246
def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
247
return {
248
type: "CatchClause",
249
param: to_moz(M.argname),
250
guard: null,
251
body: to_moz_block(M)
252
};
253
});
254
255
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
256
return {
257
type: "VariableDeclaration",
258
kind: M instanceof AST_Const ? "const" : "var",
259
declarations: M.definitions.map(to_moz)
260
};
261
});
262
263
def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
264
return {
265
type: "SequenceExpression",
266
expressions: M.to_array().map(to_moz)
267
};
268
});
269
270
def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
271
var isComputed = M instanceof AST_Sub;
272
return {
273
type: "MemberExpression",
274
object: to_moz(M.expression),
275
computed: isComputed,
276
property: isComputed ? to_moz(M.property) : {type: "Identifier", name: M.property}
277
};
278
});
279
280
def_to_moz(AST_Unary, function To_Moz_Unary(M) {
281
return {
282
type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
283
operator: M.operator,
284
prefix: M instanceof AST_UnaryPrefix,
285
argument: to_moz(M.expression)
286
};
287
});
288
289
def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
290
return {
291
type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
292
left: to_moz(M.left),
293
operator: M.operator,
294
right: to_moz(M.right)
295
};
296
});
297
298
def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
299
return {
300
type: "ObjectExpression",
301
properties: M.properties.map(to_moz)
302
};
303
});
304
305
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
306
var key = (
307
is_identifier(M.key)
308
? {type: "Identifier", name: M.key}
309
: {type: "Literal", value: M.key}
310
);
311
var kind;
312
if (M instanceof AST_ObjectKeyVal) {
313
kind = "init";
314
} else
315
if (M instanceof AST_ObjectGetter) {
316
kind = "get";
317
} else
318
if (M instanceof AST_ObjectSetter) {
319
kind = "set";
320
}
321
return {
322
type: "Property",
323
kind: kind,
324
key: key,
325
value: to_moz(M.value)
326
};
327
});
328
329
def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
330
var def = M.definition();
331
return {
332
type: "Identifier",
333
name: def ? def.mangled_name || def.name : M.name
334
};
335
});
336
337
def_to_moz(AST_Constant, function To_Moz_Literal(M) {
338
var value = M.value;
339
if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
340
return {
341
type: "UnaryExpression",
342
operator: "-",
343
prefix: true,
344
argument: {
345
type: "Literal",
346
value: -value
347
}
348
};
349
}
350
return {
351
type: "Literal",
352
value: value
353
};
354
});
355
356
def_to_moz(AST_Atom, function To_Moz_Atom(M) {
357
return {
358
type: "Identifier",
359
name: String(M.value)
360
};
361
});
362
363
AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
364
AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
365
AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
366
367
AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
368
AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
369
370
/* -----[ tools ]----- */
371
372
function my_start_token(moznode) {
373
var loc = moznode.loc, start = loc && loc.start;
374
var range = moznode.range;
375
return new AST_Token({
376
file : loc && loc.source,
377
line : start && start.line,
378
col : start && start.column,
379
pos : range ? range[0] : moznode.start,
380
endline : start && start.line,
381
endcol : start && start.column,
382
endpos : range ? range[0] : moznode.start
383
});
384
};
385
386
function my_end_token(moznode) {
387
var loc = moznode.loc, end = loc && loc.end;
388
var range = moznode.range;
389
return new AST_Token({
390
file : loc && loc.source,
391
line : end && end.line,
392
col : end && end.column,
393
pos : range ? range[1] : moznode.end,
394
endline : end && end.line,
395
endcol : end && end.column,
396
endpos : range ? range[1] : moznode.end
397
});
398
};
399
400
function map(moztype, mytype, propmap) {
401
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
402
moz_to_me += "return new " + mytype.name + "({\n" +
403
"start: my_start_token(M),\n" +
404
"end: my_end_token(M)";
405
406
var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
407
me_to_moz += "return {\n" +
408
"type: " + JSON.stringify(moztype);
409
410
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
411
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
412
if (!m) throw new Error("Can't understand property map: " + prop);
413
var moz = m[1], how = m[2], my = m[3];
414
moz_to_me += ",\n" + my + ": ";
415
me_to_moz += ",\n" + moz + ": ";
416
switch (how) {
417
case "@":
418
moz_to_me += "M." + moz + ".map(from_moz)";
419
me_to_moz += "M." + my + ".map(to_moz)";
420
break;
421
case ">":
422
moz_to_me += "from_moz(M." + moz + ")";
423
me_to_moz += "to_moz(M." + my + ")";
424
break;
425
case "=":
426
moz_to_me += "M." + moz;
427
me_to_moz += "M." + my;
428
break;
429
case "%":
430
moz_to_me += "from_moz(M." + moz + ").body";
431
me_to_moz += "to_moz_block(M)";
432
break;
433
default:
434
throw new Error("Can't understand operator in propmap: " + prop);
435
}
436
});
437
438
moz_to_me += "\n})\n}";
439
me_to_moz += "\n}\n}";
440
441
//moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
442
//me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
443
//console.log(moz_to_me);
444
445
moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
446
my_start_token, my_end_token, from_moz
447
);
448
me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(
449
to_moz, to_moz_block
450
);
451
MOZ_TO_ME[moztype] = moz_to_me;
452
def_to_moz(mytype, me_to_moz);
453
};
454
455
var FROM_MOZ_STACK = null;
456
457
function from_moz(node) {
458
FROM_MOZ_STACK.push(node);
459
var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
460
FROM_MOZ_STACK.pop();
461
return ret;
462
};
463
464
AST_Node.from_mozilla_ast = function(node){
465
var save_stack = FROM_MOZ_STACK;
466
FROM_MOZ_STACK = [];
467
var ast = from_moz(node);
468
FROM_MOZ_STACK = save_stack;
469
return ast;
470
};
471
472
function set_moz_loc(mynode, moznode, myparent) {
473
var start = mynode.start;
474
var end = mynode.end;
475
if (start.pos != null && end.endpos != null) {
476
moznode.range = [start.pos, end.endpos];
477
}
478
if (start.line) {
479
moznode.loc = {
480
start: {line: start.line, column: start.col},
481
end: end.endline ? {line: end.endline, column: end.endcol} : null
482
};
483
if (start.file) {
484
moznode.loc.source = start.file;
485
}
486
}
487
return moznode;
488
};
489
490
function def_to_moz(mytype, handler) {
491
mytype.DEFMETHOD("to_mozilla_ast", function() {
492
return set_moz_loc(this, handler(this));
493
});
494
};
495
496
function to_moz(node) {
497
return node != null ? node.to_mozilla_ast() : null;
498
};
499
500
function to_moz_block(node) {
501
return {
502
type: "BlockStatement",
503
body: node.body.map(to_moz)
504
};
505
};
506
507
})();
508
509