Use AST.Node instead of AST_Node

This commit is contained in:
Flamefire 2018-06-13 12:50:22 +02:00
parent 1ce651ee14
commit 13196026eb
14 changed files with 1611 additions and 1841 deletions

View File

@ -10,6 +10,7 @@ var info = require("../package.json");
var path = require("path"); var path = require("path");
var program = require("commander"); var program = require("commander");
var UglifyJS = require("../tools/node"); var UglifyJS = require("../tools/node");
var AST = UglifyJS.AST;
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ]; var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
var files = {}; var files = {};
@ -182,11 +183,11 @@ if (program.self) {
} }
function convert_ast(fn) { function convert_ast(fn) {
return UglifyJS.ast.AST_Node.from_mozilla_ast(Object.keys(files).reduce(fn, null)); return AST.Node.from_mozilla_ast(Object.keys(files).reduce(fn, null));
} }
function run() { function run() {
UglifyJS.ast.AST_Node.warn_function = function(msg) { AST.Node.warn_function = function(msg) {
print_error("WARN: " + msg); print_error("WARN: " + msg);
}; };
var content = program.sourceMap && program.sourceMap.content; var content = program.sourceMap && program.sourceMap.content;
@ -260,11 +261,11 @@ function run() {
return value.size() ? value.map(symdef) : undefined; return value.size() ? value.map(symdef) : undefined;
} }
if (skip_key(key)) return; if (skip_key(key)) return;
if (value instanceof UglifyJS.ast.AST_Token) return; if (value instanceof AST.Token) return;
if (value instanceof UglifyJS.Dictionary) return; if (value instanceof UglifyJS.Dictionary) return;
if (value instanceof UglifyJS.ast.AST_Node) { if (value instanceof AST.Node) {
var result = { var result = {
_class: "AST_" + value.TYPE _class: "AST." + value.TYPE
}; };
value.CTOR.PROPS.forEach(function(prop) { value.CTOR.PROPS.forEach(function(prop) {
result[prop] = value[prop]; result[prop] = value[prop];
@ -359,27 +360,27 @@ function parse_js(flag) {
code: false code: false
} }
}).ast.walk(new UglifyJS.TreeWalker(function(node) { }).ast.walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.ast.AST_Assign) { if (node instanceof AST.Assign) {
var name = node.left.print_to_string(); var name = node.left.print_to_string();
var value = node.right; var value = node.right;
if (flag) { if (flag) {
options[name] = value; options[name] = value;
} else if (value instanceof UglifyJS.ast.AST_Array) { } else if (value instanceof AST.Array) {
options[name] = value.elements.map(to_string); options[name] = value.elements.map(to_string);
} else { } else {
options[name] = to_string(value); options[name] = to_string(value);
} }
return true; return true;
} }
if (node instanceof UglifyJS.ast.AST_Symbol || node instanceof UglifyJS.ast.AST_PropAccess) { if (node instanceof AST.Symbol || node instanceof AST.PropAccess) {
var name = node.print_to_string(); var name = node.print_to_string();
options[name] = true; options[name] = true;
return true; return true;
} }
if (!(node instanceof UglifyJS.ast.AST_Sequence)) throw node; if (!(node instanceof AST.Sequence)) throw node;
function to_string(value) { function to_string(value) {
return value instanceof UglifyJS.ast.AST_Constant ? value.getValue() : value.print_to_string({ return value instanceof AST.Constant ? value.getValue() : value.print_to_string({
quote_keys: true quote_keys: true
}); });
} }

View File

@ -1193,4 +1193,89 @@ merge(exports, {
TreeWalker : TreeWalker, TreeWalker : TreeWalker,
TreeTransformer : TreeTransformer, TreeTransformer : TreeTransformer,
first_in_statement : first_in_statement, first_in_statement : first_in_statement,
Token : AST_Token,
Node : AST_Node,
Statement : AST_Statement,
Debugger : AST_Debugger,
Directive : AST_Directive,
SimpleStatement : AST_SimpleStatement,
Block : AST_Block,
BlockStatement : AST_BlockStatement,
EmptyStatement : AST_EmptyStatement,
StatementWithBody : AST_StatementWithBody,
LabeledStatement : AST_LabeledStatement,
IterationStatement : AST_IterationStatement,
DWLoop : AST_DWLoop,
Do : AST_Do,
While : AST_While,
For : AST_For,
ForIn : AST_ForIn,
With : AST_With,
Scope : AST_Scope,
Toplevel : AST_Toplevel,
Lambda : AST_Lambda,
Accessor : AST_Accessor,
Function : AST_Function,
Defun : AST_Defun,
Jump : AST_Jump,
Exit : AST_Exit,
Return : AST_Return,
Throw : AST_Throw,
LoopControl : AST_LoopControl,
Break : AST_Break,
Continue : AST_Continue,
If : AST_If,
Switch : AST_Switch,
SwitchBranch : AST_SwitchBranch,
Default : AST_Default,
Case : AST_Case,
Try : AST_Try,
Catch : AST_Catch,
Finally : AST_Finally,
Definitions : AST_Definitions,
Var : AST_Var,
VarDef : AST_VarDef,
Call : AST_Call,
New : AST_New,
Sequence : AST_Sequence,
PropAccess : AST_PropAccess,
Dot : AST_Dot,
Sub : AST_Sub,
Unary : AST_Unary,
UnaryPrefix : AST_UnaryPrefix,
UnaryPostfix : AST_UnaryPostfix,
Binary : AST_Binary,
Conditional : AST_Conditional,
Assign : AST_Assign,
Array : AST_Array,
Object : AST_Object,
ObjectProperty : AST_ObjectProperty,
ObjectKeyVal : AST_ObjectKeyVal,
ObjectSetter : AST_ObjectSetter,
ObjectGetter : AST_ObjectGetter,
Symbol : AST_Symbol,
SymbolAccessor : AST_SymbolAccessor,
SymbolDeclaration : AST_SymbolDeclaration,
SymbolVar : AST_SymbolVar,
SymbolFunarg : AST_SymbolFunarg,
SymbolDefun : AST_SymbolDefun,
SymbolLambda : AST_SymbolLambda,
SymbolCatch : AST_SymbolCatch,
Label : AST_Label,
SymbolRef : AST_SymbolRef,
LabelRef : AST_LabelRef,
This : AST_This,
Constant : AST_Constant,
String : AST_String,
Number : AST_Number,
RegExp : AST_RegExp,
Atom : AST_Atom,
Null : AST_Null,
NaN : AST_NaN,
Undefined : AST_Undefined,
Hole : AST_Hole,
Infinity : AST_Infinity,
Boolean : AST_Boolean,
False : AST_False,
True : AST_True,
}); });

File diff suppressed because it is too large Load Diff

View File

@ -7,11 +7,8 @@ var HOP = utils.HOP;
var MAP = utils.MAP; var MAP = utils.MAP;
var merge = utils.merge; var merge = utils.merge;
var ast = require("./ast"); var AST = require("./ast");
var AST_Node = ast.AST_Node; var TreeTransformer = AST.TreeTransformer;
var AST_Toplevel = ast.AST_Toplevel;
var AST_Directive = ast.AST_Directive;
var TreeTransformer = ast.TreeTransformer;
var parse = require("./parse"); var parse = require("./parse");
var parse = parse.parse; var parse = parse.parse;
@ -35,7 +32,7 @@ var to_base64 = typeof btoa == "undefined" ? function(str) {
function read_source_map(name, code) { function read_source_map(name, code) {
var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code); var match = /\n\/\/# sourceMappingURL=data:application\/json(;.*?)?;base64,(.*)/.exec(code);
if (!match) { if (!match) {
AST_Node.warn("inline source map not found: " + name); AST.Node.warn("inline source map not found: " + name);
return null; return null;
} }
return to_ascii(match[2]); return to_ascii(match[2]);
@ -81,7 +78,7 @@ function minify(files, options) {
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
wrapped_tl = parse(wrapped_tl); wrapped_tl = parse(wrapped_tl);
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) { wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
if (node instanceof AST_Directive && node.value == "$ORIG") { if (node instanceof AST.Directive && node.value == "$ORIG") {
return MAP.splice(body); return MAP.splice(body);
} }
})); }));
@ -99,13 +96,13 @@ function minify(files, options) {
args_values.slice(index + 1), args_values.slice(index + 1),
")" ")"
].join("")).transform(new TreeTransformer(function(node) { ].join("")).transform(new TreeTransformer(function(node) {
if (node instanceof AST_Directive && node.value == "$ORIG") { if (node instanceof AST.Directive && node.value == "$ORIG") {
return MAP.splice(body); return MAP.splice(body);
} }
})); }));
} }
var warn_function = AST_Node.warn_function; var warn_function = AST.Node.warn_function;
try { try {
options = defaults(options, { options = defaults(options, {
compress: {}, compress: {},
@ -170,14 +167,14 @@ function minify(files, options) {
}, true); }, true);
} }
var warnings = []; var warnings = [];
if (options.warnings && !AST_Node.warn_function) { if (options.warnings && !AST.Node.warn_function) {
AST_Node.warn_function = function(warning) { AST.Node.warn_function = function(warning) {
warnings.push(warning); warnings.push(warning);
}; };
} }
if (timings) timings.parse = Date.now(); if (timings) timings.parse = Date.now();
var source_maps, toplevel; var source_maps, toplevel;
if (files instanceof AST_Toplevel) { if (files instanceof AST.Toplevel) {
toplevel = files; toplevel = files;
} else { } else {
if (typeof files == "string") { if (typeof files == "string") {
@ -246,7 +243,7 @@ function minify(files, options) {
root: options.sourceMap.root root: options.sourceMap.root
}); });
if (options.sourceMap.includeSources) { if (options.sourceMap.includeSources) {
if (files instanceof AST_Toplevel) { if (files instanceof AST.Toplevel) {
throw new Error("original source content unavailable"); throw new Error("original source content unavailable");
} else for (var name in files) if (HOP(files, name)) { } else for (var name in files) if (HOP(files, name)) {
options.output.source_map.get().setSourceContent(name, files[name]); options.output.source_map.get().setSourceContent(name, files[name]);
@ -295,7 +292,7 @@ function minify(files, options) {
} catch (ex) { } catch (ex) {
return { error: ex }; return { error: ex };
} finally { } finally {
AST_Node.warn_function = warn_function; AST.Node.warn_function = warn_function;
} }
} }

View File

@ -43,95 +43,20 @@
"use strict"; "use strict";
var ast = require("./ast"); var AST = require("./ast");
var TreeWalker = ast.TreeWalker; var TreeWalker = AST.TreeWalker;
var AST_Token = ast.AST_Token;
var AST_Node = ast.AST_Node;
var AST_Statement = ast.AST_Statement;
var AST_Debugger = ast.AST_Debugger;
var AST_Directive = ast.AST_Directive;
var AST_SimpleStatement = ast.AST_SimpleStatement;
var AST_Block = ast.AST_Block;
var AST_BlockStatement = ast.AST_BlockStatement;
var AST_EmptyStatement = ast.AST_EmptyStatement;
var AST_LabeledStatement = ast.AST_LabeledStatement;
var AST_Do = ast.AST_Do;
var AST_While = ast.AST_While;
var AST_For = ast.AST_For;
var AST_ForIn = ast.AST_ForIn;
var AST_With = ast.AST_With;
var AST_Scope = ast.AST_Scope;
var AST_Toplevel = ast.AST_Toplevel;
var AST_Lambda = ast.AST_Lambda;
var AST_Accessor = ast.AST_Accessor;
var AST_Function = ast.AST_Function;
var AST_Defun = ast.AST_Defun;
var AST_Return = ast.AST_Return;
var AST_Throw = ast.AST_Throw;
var AST_Break = ast.AST_Break;
var AST_Continue = ast.AST_Continue;
var AST_If = ast.AST_If;
var AST_Switch = ast.AST_Switch;
var AST_SwitchBranch = ast.AST_SwitchBranch;
var AST_Default = ast.AST_Default;
var AST_Case = ast.AST_Case;
var AST_Try = ast.AST_Try;
var AST_Catch = ast.AST_Catch;
var AST_Finally = ast.AST_Finally;
var AST_Definitions = ast.AST_Definitions;
var AST_Var = ast.AST_Var;
var AST_VarDef = ast.AST_VarDef;
var AST_Call = ast.AST_Call;
var AST_New = ast.AST_New;
var AST_Sequence = ast.AST_Sequence;
var AST_PropAccess = ast.AST_PropAccess;
var AST_Dot = ast.AST_Dot;
var AST_Sub = ast.AST_Sub;
var AST_Unary = ast.AST_Unary;
var AST_UnaryPrefix = ast.AST_UnaryPrefix;
var AST_UnaryPostfix = ast.AST_UnaryPostfix;
var AST_Binary = ast.AST_Binary;
var AST_Conditional = ast.AST_Conditional;
var AST_Assign = ast.AST_Assign;
var AST_Array = ast.AST_Array;
var AST_Object = ast.AST_Object;
var AST_ObjectProperty = ast.AST_ObjectProperty;
var AST_ObjectKeyVal = ast.AST_ObjectKeyVal;
var AST_ObjectSetter = ast.AST_ObjectSetter;
var AST_ObjectGetter = ast.AST_ObjectGetter;
var AST_Symbol = ast.AST_Symbol;
var AST_SymbolAccessor = ast.AST_SymbolAccessor;
var AST_SymbolVar = ast.AST_SymbolVar;
var AST_SymbolFunarg = ast.AST_SymbolFunarg;
var AST_SymbolDefun = ast.AST_SymbolDefun;
var AST_SymbolLambda = ast.AST_SymbolLambda;
var AST_SymbolCatch = ast.AST_SymbolCatch;
var AST_Label = ast.AST_Label;
var AST_SymbolRef = ast.AST_SymbolRef;
var AST_LabelRef = ast.AST_LabelRef;
var AST_This = ast.AST_This;
var AST_Constant = ast.AST_Constant;
var AST_String = ast.AST_String;
var AST_Number = ast.AST_Number;
var AST_RegExp = ast.AST_RegExp;
var AST_Atom = ast.AST_Atom;
var AST_Null = ast.AST_Null;
var AST_Hole = ast.AST_Hole;
var AST_Boolean = ast.AST_Boolean;
var AST_False = ast.AST_False;
var AST_True = ast.AST_True;
(function() { (function() {
function normalize_directives(body) { function normalize_directives(body) {
var in_directive = true; var in_directive = true;
for (var i = 0; i < body.length; i++) { for (var i = 0; i < body.length; i++) {
if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) { if (in_directive && body[i] instanceof AST.Statement && body[i].body instanceof AST.String) {
body[i] = new AST_Directive({ body[i] = new AST.Directive({
start: body[i].start, start: body[i].start,
end: body[i].end, end: body[i].end,
value: body[i].body.value value: body[i].body.value
}); });
} else if (in_directive && !(body[i] instanceof AST_Statement && body[i].body instanceof AST_String)) { } else if (in_directive && !(body[i] instanceof AST.Statement && body[i].body instanceof AST.String)) {
in_directive = false; in_directive = false;
} }
} }
@ -140,14 +65,14 @@ var AST_True = ast.AST_True;
var MOZ_TO_ME = { var MOZ_TO_ME = {
Program: function(M) { Program: function(M) {
return new AST_Toplevel({ return new AST.Toplevel({
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
body: normalize_directives(M.body.map(from_moz)) body: normalize_directives(M.body.map(from_moz))
}); });
}, },
FunctionDeclaration: function(M) { FunctionDeclaration: function(M) {
return new AST_Defun({ return new AST.Defun({
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
name: from_moz(M.id), name: from_moz(M.id),
@ -156,7 +81,7 @@ var AST_True = ast.AST_True;
}); });
}, },
FunctionExpression: function(M) { FunctionExpression: function(M) {
return new AST_Function({ return new AST.Function({
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
name: from_moz(M.id), name: from_moz(M.id),
@ -165,7 +90,7 @@ var AST_True = ast.AST_True;
}); });
}, },
ExpressionStatement: function(M) { ExpressionStatement: function(M) {
return new AST_SimpleStatement({ return new AST.SimpleStatement({
start: my_start_token(M), start: my_start_token(M),
end: my_end_token(M), end: my_end_token(M),
body: from_moz(M.expression) body: from_moz(M.expression)
@ -176,12 +101,12 @@ var AST_True = ast.AST_True;
if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) { if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
throw new Error("Multiple catch clauses are not supported."); throw new Error("Multiple catch clauses are not supported.");
} }
return new AST_Try({ return new AST.Try({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
body : from_moz(M.block).body, body : from_moz(M.block).body,
bcatch : from_moz(handlers[0]), bcatch : from_moz(handlers[0]),
bfinally : M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null bfinally : M.finalizer ? new AST.Finally(from_moz(M.finalizer)) : null
}); });
}, },
Property: function(M) { Property: function(M) {
@ -192,25 +117,25 @@ var AST_True = ast.AST_True;
key : key.type == "Identifier" ? key.name : key.value, key : key.type == "Identifier" ? key.name : key.value,
value : from_moz(M.value) value : from_moz(M.value)
}; };
if (M.kind == "init") return new AST_ObjectKeyVal(args); if (M.kind == "init") return new AST.ObjectKeyVal(args);
args.key = new AST_SymbolAccessor({ args.key = new AST.SymbolAccessor({
name: args.key name: args.key
}); });
args.value = new AST_Accessor(args.value); args.value = new AST.Accessor(args.value);
if (M.kind == "get") return new AST_ObjectGetter(args); if (M.kind == "get") return new AST.ObjectGetter(args);
if (M.kind == "set") return new AST_ObjectSetter(args); if (M.kind == "set") return new AST.ObjectSetter(args);
}, },
ArrayExpression: function(M) { ArrayExpression: function(M) {
return new AST_Array({ return new AST.Array({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
elements : M.elements.map(function(elem) { elements : M.elements.map(function(elem) {
return elem === null ? new AST_Hole() : from_moz(elem); return elem === null ? new AST.Hole() : from_moz(elem);
}) })
}); });
}, },
ObjectExpression: function(M) { ObjectExpression: function(M) {
return new AST_Object({ return new AST.Object({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
properties : M.properties.map(function(prop) { properties : M.properties.map(function(prop) {
@ -220,14 +145,14 @@ var AST_True = ast.AST_True;
}); });
}, },
SequenceExpression: function(M) { SequenceExpression: function(M) {
return new AST_Sequence({ return new AST.Sequence({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
expressions: M.expressions.map(from_moz) expressions: M.expressions.map(from_moz)
}); });
}, },
MemberExpression: function(M) { MemberExpression: function(M) {
return new (M.computed ? AST_Sub : AST_Dot)({ return new (M.computed ? AST.Sub : AST.Dot)({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
property : M.computed ? from_moz(M.property) : M.property.name, property : M.computed ? from_moz(M.property) : M.property.name,
@ -235,7 +160,7 @@ var AST_True = ast.AST_True;
}); });
}, },
SwitchCase: function(M) { SwitchCase: function(M) {
return new (M.test ? AST_Case : AST_Default)({ return new (M.test ? AST.Case : AST.Default)({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
expression : from_moz(M.test), expression : from_moz(M.test),
@ -243,7 +168,7 @@ var AST_True = ast.AST_True;
}); });
}, },
VariableDeclaration: function(M) { VariableDeclaration: function(M) {
return new AST_Var({ return new AST.Var({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
definitions : M.declarations.map(from_moz) definitions : M.declarations.map(from_moz)
@ -254,38 +179,38 @@ var AST_True = ast.AST_True;
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M) end : my_end_token(M)
}; };
if (val === null) return new AST_Null(args); if (val === null) return new AST.Null(args);
var rx = M.regex; var rx = M.regex;
if (rx && rx.pattern) { if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec // RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags); args.value = new RegExp(rx.pattern, rx.flags);
args.value.raw_source = rx.pattern; args.value.raw_source = rx.pattern;
return new AST_RegExp(args); return new AST.RegExp(args);
} else if (rx) { } else if (rx) {
// support legacy RegExp // support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val; args.value = M.regex && M.raw ? M.raw : val;
return new AST_RegExp(args); return new AST.RegExp(args);
} }
switch (typeof val) { switch (typeof val) {
case "string": case "string":
args.value = val; args.value = val;
return new AST_String(args); return new AST.String(args);
case "number": case "number":
args.value = val; args.value = val;
return new AST_Number(args); return new AST.Number(args);
case "boolean": case "boolean":
return new (val ? AST_True : AST_False)(args); return new (val ? AST.True : AST.False)(args);
} }
}, },
Identifier: function(M) { Identifier: function(M) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
return new ( p.type == "LabeledStatement" ? AST_Label return new ( p.type == "LabeledStatement" ? AST.Label
: p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar : p.type == "VariableDeclarator" && p.id === M ? AST.SymbolVar
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) : p.type == "FunctionExpression" ? (p.id === M ? AST.SymbolLambda : AST.SymbolFunarg)
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) : p.type == "FunctionDeclaration" ? (p.id === M ? AST.SymbolDefun : AST.SymbolFunarg)
: p.type == "CatchClause" ? AST_SymbolCatch : p.type == "CatchClause" ? AST.SymbolCatch
: p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST.LabelRef
: AST_SymbolRef)({ : AST.SymbolRef)({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
name : M.name name : M.name
@ -297,7 +222,7 @@ var AST_True = ast.AST_True;
MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) { MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
var prefix = "prefix" in M ? M.prefix var prefix = "prefix" in M ? M.prefix
: M.type == "UnaryExpression" ? true : false; : M.type == "UnaryExpression" ? true : false;
return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({ return new (prefix ? AST.UnaryPrefix : AST.UnaryPostfix)({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
operator : M.operator, operator : M.operator,
@ -305,37 +230,37 @@ var AST_True = ast.AST_True;
}); });
}; };
map("EmptyStatement", AST_EmptyStatement); map("EmptyStatement", AST.EmptyStatement);
map("BlockStatement", AST_BlockStatement, "body@body"); map("BlockStatement", AST.BlockStatement, "body@body");
map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative"); map("IfStatement", AST.If, "test>condition, consequent>body, alternate>alternative");
map("LabeledStatement", AST_LabeledStatement, "label>label, body>body"); map("LabeledStatement", AST.LabeledStatement, "label>label, body>body");
map("BreakStatement", AST_Break, "label>label"); map("BreakStatement", AST.Break, "label>label");
map("ContinueStatement", AST_Continue, "label>label"); map("ContinueStatement", AST.Continue, "label>label");
map("WithStatement", AST_With, "object>expression, body>body"); map("WithStatement", AST.With, "object>expression, body>body");
map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body"); map("SwitchStatement", AST.Switch, "discriminant>expression, cases@body");
map("ReturnStatement", AST_Return, "argument>value"); map("ReturnStatement", AST.Return, "argument>value");
map("ThrowStatement", AST_Throw, "argument>value"); map("ThrowStatement", AST.Throw, "argument>value");
map("WhileStatement", AST_While, "test>condition, body>body"); map("WhileStatement", AST.While, "test>condition, body>body");
map("DoWhileStatement", AST_Do, "test>condition, body>body"); map("DoWhileStatement", AST.Do, "test>condition, body>body");
map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body"); map("ForStatement", AST.For, "init>init, test>condition, update>step, body>body");
map("ForInStatement", AST_ForIn, "left>init, right>object, body>body"); map("ForInStatement", AST.ForIn, "left>init, right>object, body>body");
map("DebuggerStatement", AST_Debugger); map("DebuggerStatement", AST.Debugger);
map("VariableDeclarator", AST_VarDef, "id>name, init>value"); map("VariableDeclarator", AST.VarDef, "id>name, init>value");
map("CatchClause", AST_Catch, "param>argname, body%body"); map("CatchClause", AST.Catch, "param>argname, body%body");
map("ThisExpression", AST_This); map("ThisExpression", AST.This);
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); map("BinaryExpression", AST.Binary, "operator=operator, left>left, right>right");
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); map("LogicalExpression", AST.Binary, "operator=operator, left>left, right>right");
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); map("AssignmentExpression", AST.Assign, "operator=operator, left>left, right>right");
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative"); map("ConditionalExpression", AST.Conditional, "test>condition, consequent>consequent, alternate>alternative");
map("NewExpression", AST_New, "callee>expression, arguments@args"); map("NewExpression", AST.New, "callee>expression, arguments@args");
map("CallExpression", AST_Call, "callee>expression, arguments@args"); map("CallExpression", AST.Call, "callee>expression, arguments@args");
def_to_moz(AST_Toplevel, function To_Moz_Program(M) { def_to_moz(AST.Toplevel, function To_Moz_Program(M) {
return to_moz_scope("Program", M); return to_moz_scope("Program", M);
}); });
def_to_moz(AST_Defun, function To_Moz_FunctionDeclaration(M) { def_to_moz(AST.Defun, function To_Moz_FunctionDeclaration(M) {
return { return {
type: "FunctionDeclaration", type: "FunctionDeclaration",
id: to_moz(M.name), id: to_moz(M.name),
@ -344,7 +269,7 @@ var AST_True = ast.AST_True;
} }
}); });
def_to_moz(AST_Function, function To_Moz_FunctionExpression(M) { def_to_moz(AST.Function, function To_Moz_FunctionExpression(M) {
return { return {
type: "FunctionExpression", type: "FunctionExpression",
id: to_moz(M.name), id: to_moz(M.name),
@ -353,7 +278,7 @@ var AST_True = ast.AST_True;
} }
}); });
def_to_moz(AST_Directive, function To_Moz_Directive(M) { def_to_moz(AST.Directive, function To_Moz_Directive(M) {
return { return {
type: "ExpressionStatement", type: "ExpressionStatement",
expression: { expression: {
@ -363,14 +288,14 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) { def_to_moz(AST.SimpleStatement, function To_Moz_ExpressionStatement(M) {
return { return {
type: "ExpressionStatement", type: "ExpressionStatement",
expression: to_moz(M.body) expression: to_moz(M.body)
}; };
}); });
def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) { def_to_moz(AST.SwitchBranch, function To_Moz_SwitchCase(M) {
return { return {
type: "SwitchCase", type: "SwitchCase",
test: to_moz(M.expression), test: to_moz(M.expression),
@ -378,7 +303,7 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Try, function To_Moz_TryStatement(M) { def_to_moz(AST.Try, function To_Moz_TryStatement(M) {
return { return {
type: "TryStatement", type: "TryStatement",
block: to_moz_block(M), block: to_moz_block(M),
@ -388,7 +313,7 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Catch, function To_Moz_CatchClause(M) { def_to_moz(AST.Catch, function To_Moz_CatchClause(M) {
return { return {
type: "CatchClause", type: "CatchClause",
param: to_moz(M.argname), param: to_moz(M.argname),
@ -397,7 +322,7 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) { def_to_moz(AST.Definitions, function To_Moz_VariableDeclaration(M) {
return { return {
type: "VariableDeclaration", type: "VariableDeclaration",
kind: "var", kind: "var",
@ -405,15 +330,15 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) { def_to_moz(AST.Sequence, function To_Moz_SequenceExpression(M) {
return { return {
type: "SequenceExpression", type: "SequenceExpression",
expressions: M.expressions.map(to_moz) expressions: M.expressions.map(to_moz)
}; };
}); });
def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) { def_to_moz(AST.PropAccess, function To_Moz_MemberExpression(M) {
var isComputed = M instanceof AST_Sub; var isComputed = M instanceof AST.Sub;
return { return {
type: "MemberExpression", type: "MemberExpression",
object: to_moz(M.expression), object: to_moz(M.expression),
@ -422,16 +347,16 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Unary, function To_Moz_Unary(M) { def_to_moz(AST.Unary, function To_Moz_Unary(M) {
return { return {
type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression", type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
operator: M.operator, operator: M.operator,
prefix: M instanceof AST_UnaryPrefix, prefix: M instanceof AST.UnaryPrefix,
argument: to_moz(M.expression) argument: to_moz(M.expression)
}; };
}); });
def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) { def_to_moz(AST.Binary, function To_Moz_BinaryExpression(M) {
return { return {
type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression", type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
left: to_moz(M.left), left: to_moz(M.left),
@ -440,33 +365,33 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Array, function To_Moz_ArrayExpression(M) { def_to_moz(AST.Array, function To_Moz_ArrayExpression(M) {
return { return {
type: "ArrayExpression", type: "ArrayExpression",
elements: M.elements.map(to_moz) elements: M.elements.map(to_moz)
}; };
}); });
def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) { def_to_moz(AST.Object, function To_Moz_ObjectExpression(M) {
return { return {
type: "ObjectExpression", type: "ObjectExpression",
properties: M.properties.map(to_moz) properties: M.properties.map(to_moz)
}; };
}); });
def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) { def_to_moz(AST.ObjectProperty, function To_Moz_Property(M) {
var key = { var key = {
type: "Literal", type: "Literal",
value: M.key instanceof AST_SymbolAccessor ? M.key.name : M.key value: M.key instanceof AST.SymbolAccessor ? M.key.name : M.key
}; };
var kind; var kind;
if (M instanceof AST_ObjectKeyVal) { if (M instanceof AST.ObjectKeyVal) {
kind = "init"; kind = "init";
} else } else
if (M instanceof AST_ObjectGetter) { if (M instanceof AST.ObjectGetter) {
kind = "get"; kind = "get";
} else } else
if (M instanceof AST_ObjectSetter) { if (M instanceof AST.ObjectSetter) {
kind = "set"; kind = "set";
} }
return { return {
@ -477,7 +402,7 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Symbol, function To_Moz_Identifier(M) { def_to_moz(AST.Symbol, function To_Moz_Identifier(M) {
var def = M.definition(); var def = M.definition();
return { return {
type: "Identifier", type: "Identifier",
@ -485,7 +410,7 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) { def_to_moz(AST.RegExp, function To_Moz_RegExpLiteral(M) {
var flags = M.value.toString().match(/[gimuy]*$/)[0]; var flags = M.value.toString().match(/[gimuy]*$/)[0];
var value = "/" + M.value.raw_source + "/" + flags; var value = "/" + M.value.raw_source + "/" + flags;
return { return {
@ -499,7 +424,7 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Constant, function To_Moz_Literal(M) { def_to_moz(AST.Constant, function To_Moz_Literal(M) {
var value = M.value; var value = M.value;
if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) { if (typeof value === 'number' && (value < 0 || (value === 0 && 1 / value < 0))) {
return { return {
@ -520,19 +445,19 @@ var AST_True = ast.AST_True;
}; };
}); });
def_to_moz(AST_Atom, function To_Moz_Atom(M) { def_to_moz(AST.Atom, function To_Moz_Atom(M) {
return { return {
type: "Identifier", type: "Identifier",
name: String(M.value) name: String(M.value)
}; };
}); });
AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast); AST.Boolean.DEFMETHOD("to_mozilla_ast", AST.Constant.prototype.to_mozilla_ast);
AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast); AST.Null.DEFMETHOD("to_mozilla_ast", AST.Constant.prototype.to_mozilla_ast);
AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null }); AST.Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() { return null });
AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast); AST.Block.DEFMETHOD("to_mozilla_ast", AST.BlockStatement.prototype.to_mozilla_ast);
AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast); AST.Lambda.DEFMETHOD("to_mozilla_ast", AST.Function.prototype.to_mozilla_ast);
/* -----[ tools ]----- */ /* -----[ tools ]----- */
@ -545,7 +470,7 @@ var AST_True = ast.AST_True;
function my_start_token(moznode) { function my_start_token(moznode) {
var loc = moznode.loc, start = loc && loc.start; var loc = moznode.loc, start = loc && loc.start;
var range = moznode.range; var range = moznode.range;
return new AST_Token({ return new AST.Token({
file : loc && loc.source, file : loc && loc.source,
line : start && start.line, line : start && start.line,
col : start && start.column, col : start && start.column,
@ -560,7 +485,7 @@ var AST_True = ast.AST_True;
function my_end_token(moznode) { function my_end_token(moznode) {
var loc = moznode.loc, end = loc && loc.end; var loc = moznode.loc, end = loc && loc.end;
var range = moznode.range; var range = moznode.range;
return new AST_Token({ return new AST.Token({
file : loc && loc.source, file : loc && loc.source,
line : end && end.line, line : end && end.line,
col : end && end.column, col : end && end.column,
@ -618,7 +543,7 @@ var AST_True = ast.AST_True;
//console.log(moz_to_me); //console.log(moz_to_me);
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")( moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
ast, my_start_token, my_end_token, from_moz AST, my_start_token, my_end_token, from_moz
); );
me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")( me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
to_moz, to_moz_block, to_moz_scope to_moz, to_moz_block, to_moz_scope
@ -636,16 +561,16 @@ var AST_True = ast.AST_True;
return ret; return ret;
} }
AST_Node.from_mozilla_ast = function(node) { AST.Node.from_mozilla_ast = function(node) {
var save_stack = FROM_MOZ_STACK; var save_stack = FROM_MOZ_STACK;
FROM_MOZ_STACK = []; FROM_MOZ_STACK = [];
var ast = from_moz(node); var ast = from_moz(node);
FROM_MOZ_STACK = save_stack; FROM_MOZ_STACK = save_stack;
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_LabelRef) { if (node instanceof AST.LabelRef) {
for (var level = 0, parent; parent = this.parent(level); level++) { for (var level = 0, parent; parent = this.parent(level); level++) {
if (parent instanceof AST_Scope) break; if (parent instanceof AST.Scope) break;
if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) { if (parent instanceof AST.LabeledStatement && parent.label.name == node.name) {
node.thedef = parent.label; node.thedef = parent.label;
break; break;
} }
@ -696,8 +621,8 @@ var AST_True = ast.AST_True;
function to_moz_scope(type, node) { function to_moz_scope(type, node) {
var body = node.body.map(to_moz); var body = node.body.map(to_moz);
if (node.body[0] instanceof AST_SimpleStatement && node.body[0].body instanceof AST_String) { if (node.body[0] instanceof AST.SimpleStatement && node.body[0].body instanceof AST.String) {
body.unshift(to_moz(new AST_EmptyStatement(node.body[0]))); body.unshift(to_moz(new AST.EmptyStatement(node.body[0])));
} }
return { return {
type: type, type: type,

View File

@ -53,69 +53,9 @@ var makePredicate = utils.makePredicate;
var all = utils.all; var all = utils.all;
var merge = utils.merge; var merge = utils.merge;
var ast = require("./ast"); var AST = require("./ast");
var first_in_statement = ast.first_in_statement; var first_in_statement = AST.first_in_statement;
var TreeWalker = ast.TreeWalker; var TreeWalker = AST.TreeWalker;
var AST_Node = ast.AST_Node;
var AST_Statement = ast.AST_Statement;
var AST_Debugger = ast.AST_Debugger;
var AST_Directive = ast.AST_Directive;
var AST_SimpleStatement = ast.AST_SimpleStatement;
var AST_BlockStatement = ast.AST_BlockStatement;
var AST_EmptyStatement = ast.AST_EmptyStatement;
var AST_StatementWithBody = ast.AST_StatementWithBody;
var AST_LabeledStatement = ast.AST_LabeledStatement;
var AST_Do = ast.AST_Do;
var AST_While = ast.AST_While;
var AST_For = ast.AST_For;
var AST_ForIn = ast.AST_ForIn;
var AST_With = ast.AST_With;
var AST_Scope = ast.AST_Scope;
var AST_Toplevel = ast.AST_Toplevel;
var AST_Lambda = ast.AST_Lambda;
var AST_Function = ast.AST_Function;
var AST_Jump = ast.AST_Jump;
var AST_Exit = ast.AST_Exit;
var AST_Return = ast.AST_Return;
var AST_Throw = ast.AST_Throw;
var AST_Break = ast.AST_Break;
var AST_Continue = ast.AST_Continue;
var AST_If = ast.AST_If;
var AST_Switch = ast.AST_Switch;
var AST_SwitchBranch = ast.AST_SwitchBranch;
var AST_Default = ast.AST_Default;
var AST_Case = ast.AST_Case;
var AST_Try = ast.AST_Try;
var AST_Catch = ast.AST_Catch;
var AST_Finally = ast.AST_Finally;
var AST_Definitions = ast.AST_Definitions;
var AST_Var = ast.AST_Var;
var AST_VarDef = ast.AST_VarDef;
var AST_Call = ast.AST_Call;
var AST_New = ast.AST_New;
var AST_Sequence = ast.AST_Sequence;
var AST_PropAccess = ast.AST_PropAccess;
var AST_Dot = ast.AST_Dot;
var AST_Sub = ast.AST_Sub;
var AST_Unary = ast.AST_Unary;
var AST_UnaryPrefix = ast.AST_UnaryPrefix;
var AST_UnaryPostfix = ast.AST_UnaryPostfix;
var AST_Binary = ast.AST_Binary;
var AST_Conditional = ast.AST_Conditional;
var AST_Assign = ast.AST_Assign;
var AST_Array = ast.AST_Array;
var AST_Object = ast.AST_Object;
var AST_ObjectProperty = ast.AST_ObjectProperty;
var AST_ObjectKeyVal = ast.AST_ObjectKeyVal;
var AST_ObjectSetter = ast.AST_ObjectSetter;
var AST_ObjectGetter = ast.AST_ObjectGetter;
var AST_Symbol = ast.AST_Symbol;
var AST_This = ast.AST_This;
var AST_Constant = ast.AST_Constant;
var AST_String = ast.AST_String;
var AST_Number = ast.AST_Number;
var AST_RegExp = ast.AST_RegExp;
var AST_Hole = ast.AST_Hole;
var parse = require("./parse"); var parse = require("./parse");
var is_surrogate_pair_head = parse.is_surrogate_pair_head; var is_surrogate_pair_head = parse.is_surrogate_pair_head;
@ -299,7 +239,7 @@ function OutputStream(options) {
!mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name !mapping.name && mapping.token.type == "name" ? mapping.token.value : mapping.name
); );
} catch(ex) { } catch(ex) {
AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", { AST.Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
file: mapping.token.file, file: mapping.token.file,
line: mapping.token.line, line: mapping.token.line,
col: mapping.token.col, col: mapping.token.col,
@ -330,7 +270,7 @@ function OutputStream(options) {
current_col = right.length; current_col = right.length;
} }
if (current_col > options.max_line_len) { if (current_col > options.max_line_len) {
AST_Node.warn("Output exceeds {max_line_len} characters", options); AST.Node.warn("Output exceeds {max_line_len} characters", options);
} }
} }
if (might_add_newline) { if (might_add_newline) {
@ -559,17 +499,17 @@ function OutputStream(options) {
} }
comments._dumped = self; comments._dumped = self;
if (node instanceof AST_Exit && node.value) { if (node instanceof AST.Exit && node.value) {
var tw = new TreeWalker(function(node) { var tw = new TreeWalker(function(node) {
var parent = tw.parent(); var parent = tw.parent();
if (parent instanceof AST_Exit if (parent instanceof AST.Exit
|| parent instanceof AST_Binary && parent.left === node || parent instanceof AST.Binary && parent.left === node
|| parent.TYPE == "Call" && parent.expression === node || parent.TYPE == "Call" && parent.expression === node
|| parent instanceof AST_Conditional && parent.condition === node || parent instanceof AST.Conditional && parent.condition === node
|| parent instanceof AST_Dot && parent.expression === node || parent instanceof AST.Dot && parent.expression === node
|| parent instanceof AST_Sequence && parent.expressions[0] === node || parent instanceof AST.Sequence && parent.expressions[0] === node
|| parent instanceof AST_Sub && parent.expression === node || parent instanceof AST.Sub && parent.expression === node
|| parent instanceof AST_UnaryPostfix) { || parent instanceof AST.UnaryPostfix) {
var text = node.start.comments_before; var text = node.start.comments_before;
if (text && text._dumped !== self) { if (text && text._dumped !== self) {
text._dumped = self; text._dumped = self;
@ -632,7 +572,7 @@ function OutputStream(options) {
if (!token) return; if (!token) return;
var comments = token[tail ? "comments_before" : "comments_after"]; var comments = token[tail ? "comments_before" : "comments_after"];
if (!comments || comments._dumped === self) return; if (!comments || comments._dumped === self) return;
if (!(node instanceof AST_Statement || all(comments, function(c) { if (!(node instanceof AST.Statement || all(comments, function(c) {
return !/comment[134]/.test(c.type); return !/comment[134]/.test(c.type);
}))) return; }))) return;
comments._dumped = self; comments._dumped = self;
@ -725,12 +665,12 @@ function OutputStream(options) {
var active_scope = null; var active_scope = null;
var use_asm = null; var use_asm = null;
AST_Node.DEFMETHOD("print", function(stream, force_parens) { AST.Node.DEFMETHOD("print", function(stream, force_parens) {
var self = this, generator = self._codegen; var self = this, generator = self._codegen;
if (self instanceof AST_Scope) { if (self instanceof AST.Scope) {
active_scope = self; active_scope = self;
} }
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") { else if (!use_asm && self instanceof AST.Directive && self.value == "use asm") {
use_asm = active_scope; use_asm = active_scope;
} }
function doit() { function doit() {
@ -750,9 +690,9 @@ function OutputStream(options) {
use_asm = null; use_asm = null;
} }
}); });
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print); AST.Node.DEFMETHOD("_print", AST.Node.prototype.print);
AST_Node.DEFMETHOD("print_to_string", function(options) { AST.Node.DEFMETHOD("print_to_string", function(options) {
var s = OutputStream(options); var s = OutputStream(options);
this.print(s); this.print(s);
return s.get(); return s.get();
@ -770,25 +710,25 @@ function OutputStream(options) {
} }
} }
PARENS(AST_Node, return_false); PARENS(AST.Node, return_false);
// a function expression needs parens around it when it's provably // a function expression needs parens around it when it's provably
// the first token to appear in a statement. // the first token to appear in a statement.
PARENS(AST_Function, function(output) { PARENS(AST.Function, function(output) {
if (!output.has_parens() && first_in_statement(output)) { if (!output.has_parens() && first_in_statement(output)) {
return true; return true;
} }
if (output.option('webkit')) { if (output.option('webkit')) {
var p = output.parent(); var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this) { if (p instanceof AST.PropAccess && p.expression === this) {
return true; return true;
} }
} }
if (output.option('wrap_iife')) { if (output.option('wrap_iife')) {
var p = output.parent(); var p = output.parent();
return p instanceof AST_Call && p.expression === this; return p instanceof AST.Call && p.expression === this;
} }
return false; return false;
@ -796,43 +736,43 @@ function OutputStream(options) {
// same goes for an object literal, because otherwise it would be // same goes for an object literal, because otherwise it would be
// interpreted as a block of code. // interpreted as a block of code.
PARENS(AST_Object, function(output) { PARENS(AST.Object, function(output) {
return !output.has_parens() && first_in_statement(output); return !output.has_parens() && first_in_statement(output);
}); });
PARENS(AST_Unary, function(output) { PARENS(AST.Unary, function(output) {
var p = output.parent(); var p = output.parent();
return p instanceof AST_PropAccess && p.expression === this return p instanceof AST.PropAccess && p.expression === this
|| p instanceof AST_Call && p.expression === this; || p instanceof AST.Call && p.expression === this;
}); });
PARENS(AST_Sequence, function(output) { PARENS(AST.Sequence, function(output) {
var p = output.parent(); var p = output.parent();
return p instanceof AST_Call // (foo, bar)() or foo(1, (2, 3), 4) return p instanceof AST.Call // (foo, bar)() or foo(1, (2, 3), 4)
|| p instanceof AST_Unary // !(foo, bar, baz) || p instanceof AST.Unary // !(foo, bar, baz)
|| p instanceof AST_Binary // 1 + (2, 3) + 4 ==> 8 || p instanceof AST.Binary // 1 + (2, 3) + 4 ==> 8
|| p instanceof AST_VarDef // var a = (1, 2), b = a + a; ==> b == 4 || p instanceof AST.VarDef // var a = (1, 2), b = a + a; ==> b == 4
|| p instanceof AST_PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2 || p instanceof AST.PropAccess // (1, {foo:2}).foo or (1, {foo:2})["foo"] ==> 2
|| p instanceof AST_Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ] || p instanceof AST.Array // [ 1, (2, 3), 4 ] ==> [ 1, 3, 4 ]
|| p instanceof AST_ObjectProperty // { foo: (1, 2) }.foo ==> 2 || p instanceof AST.ObjectProperty // { foo: (1, 2) }.foo ==> 2
|| p instanceof AST_Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30) || p instanceof AST.Conditional /* (false, true) ? (a = 10, b = 20) : (c = 30)
* ==> 20 (side effect, set a := 10 and b := 20) */ * ==> 20 (side effect, set a := 10 and b := 20) */
; ;
}); });
PARENS(AST_Binary, function(output) { PARENS(AST.Binary, function(output) {
var p = output.parent(); var p = output.parent();
// (foo && bar)() // (foo && bar)()
if (p instanceof AST_Call && p.expression === this) if (p instanceof AST.Call && p.expression === this)
return true; return true;
// typeof (foo && bar) // typeof (foo && bar)
if (p instanceof AST_Unary) if (p instanceof AST.Unary)
return true; return true;
// (foo && bar)["prop"], (foo && bar).prop // (foo && bar)["prop"], (foo && bar).prop
if (p instanceof AST_PropAccess && p.expression === this) if (p instanceof AST.PropAccess && p.expression === this)
return true; return true;
// this deals with precedence: 3 * (2 + 1) // this deals with precedence: 3 * (2 + 1)
if (p instanceof AST_Binary) { if (p instanceof AST.Binary) {
var po = p.operator, pp = PRECEDENCE[po]; var po = p.operator, pp = PRECEDENCE[po];
var so = this.operator, sp = PRECEDENCE[so]; var so = this.operator, sp = PRECEDENCE[so];
if (pp > sp if (pp > sp
@ -843,9 +783,9 @@ function OutputStream(options) {
} }
}); });
PARENS(AST_PropAccess, function(output) { PARENS(AST.PropAccess, function(output) {
var p = output.parent(); var p = output.parent();
if (p instanceof AST_New && p.expression === this) { if (p instanceof AST.New && p.expression === this) {
// i.e. new (foo.bar().baz) // i.e. new (foo.bar().baz)
// //
// if there's one call into this subtree, then we need // if there's one call into this subtree, then we need
@ -854,8 +794,8 @@ function OutputStream(options) {
// expression. // expression.
var parens = false; var parens = false;
this.walk(new TreeWalker(function(node) { this.walk(new TreeWalker(function(node) {
if (parens || node instanceof AST_Scope) return true; if (parens || node instanceof AST.Scope) return true;
if (node instanceof AST_Call) { if (node instanceof AST.Call) {
parens = true; parens = true;
return true; return true;
} }
@ -864,31 +804,31 @@ function OutputStream(options) {
} }
}); });
PARENS(AST_Call, function(output) { PARENS(AST.Call, function(output) {
var p = output.parent(), p1; var p = output.parent(), p1;
if (p instanceof AST_New && p.expression === this) if (p instanceof AST.New && p.expression === this)
return true; return true;
// workaround for Safari bug. // workaround for Safari bug.
// https://bugs.webkit.org/show_bug.cgi?id=123506 // https://bugs.webkit.org/show_bug.cgi?id=123506
return this.expression instanceof AST_Function return this.expression instanceof AST.Function
&& p instanceof AST_PropAccess && p instanceof AST.PropAccess
&& p.expression === this && p.expression === this
&& (p1 = output.parent(1)) instanceof AST_Assign && (p1 = output.parent(1)) instanceof AST.Assign
&& p1.left === p; && p1.left === p;
}); });
PARENS(AST_New, function(output) { PARENS(AST.New, function(output) {
var p = output.parent(); var p = output.parent();
if (!need_constructor_parens(this, output) if (!need_constructor_parens(this, output)
&& (p instanceof AST_PropAccess // (new Date).getTime(), (new Date)["getTime"]() && (p instanceof AST.PropAccess // (new Date).getTime(), (new Date)["getTime"]()
|| p instanceof AST_Call && p.expression === this)) // (new foo)(bar) || p instanceof AST.Call && p.expression === this)) // (new foo)(bar)
return true; return true;
}); });
PARENS(AST_Number, function(output) { PARENS(AST.Number, function(output) {
var p = output.parent(); var p = output.parent();
if (p instanceof AST_PropAccess && p.expression === this) { if (p instanceof AST.PropAccess && p.expression === this) {
var value = this.getValue(); var value = this.getValue();
if (value < 0 || /^0/.test(make_num(value))) { if (value < 0 || /^0/.test(make_num(value))) {
return true; return true;
@ -896,32 +836,32 @@ function OutputStream(options) {
} }
}); });
PARENS([ AST_Assign, AST_Conditional ], function(output) { PARENS([ AST.Assign, AST.Conditional ], function(output) {
var p = output.parent(); var p = output.parent();
// !(a = false) → true // !(a = false) → true
if (p instanceof AST_Unary) if (p instanceof AST.Unary)
return true; return true;
// 1 + (a = 2) + 3 → 6, side effect setting a = 2 // 1 + (a = 2) + 3 → 6, side effect setting a = 2
if (p instanceof AST_Binary && !(p instanceof AST_Assign)) if (p instanceof AST.Binary && !(p instanceof AST.Assign))
return true; return true;
// (a = func)() —or— new (a = Object)() // (a = func)() —or— new (a = Object)()
if (p instanceof AST_Call && p.expression === this) if (p instanceof AST.Call && p.expression === this)
return true; return true;
// (a = foo) ? bar : baz // (a = foo) ? bar : baz
if (p instanceof AST_Conditional && p.condition === this) if (p instanceof AST.Conditional && p.condition === this)
return true; return true;
// (a = foo)["prop"] —or— (a = foo).prop // (a = foo)["prop"] —or— (a = foo).prop
if (p instanceof AST_PropAccess && p.expression === this) if (p instanceof AST.PropAccess && p.expression === this)
return true; return true;
}); });
/* -----[ PRINTERS ]----- */ /* -----[ PRINTERS ]----- */
DEFPRINT(AST_Directive, function(self, output) { DEFPRINT(AST.Directive, function(self, output) {
output.print_string(self.value, self.quote); output.print_string(self.value, self.quote);
output.semicolon(); output.semicolon();
}); });
DEFPRINT(AST_Debugger, function(self, output) { DEFPRINT(AST.Debugger, function(self, output) {
output.print("debugger"); output.print("debugger");
output.semicolon(); output.semicolon();
}); });
@ -932,13 +872,13 @@ function OutputStream(options) {
var last = body.length - 1; var last = body.length - 1;
in_directive = allow_directives; in_directive = allow_directives;
body.forEach(function(stmt, i) { body.forEach(function(stmt, i) {
if (in_directive === true && !(stmt instanceof AST_Directive || if (in_directive === true && !(stmt instanceof AST.Directive ||
stmt instanceof AST_EmptyStatement || stmt instanceof AST.EmptyStatement ||
(stmt instanceof AST_SimpleStatement && stmt.body instanceof AST_String) (stmt instanceof AST.SimpleStatement && stmt.body instanceof AST.String)
)) { )) {
in_directive = false; in_directive = false;
} }
if (!(stmt instanceof AST_EmptyStatement)) { if (!(stmt instanceof AST.EmptyStatement)) {
output.indent(); output.indent();
stmt.print(output); stmt.print(output);
if (!(i == last && is_toplevel)) { if (!(i == last && is_toplevel)) {
@ -947,8 +887,8 @@ function OutputStream(options) {
} }
} }
if (in_directive === true && if (in_directive === true &&
stmt instanceof AST_SimpleStatement && stmt instanceof AST.SimpleStatement &&
stmt.body instanceof AST_String stmt.body instanceof AST.String
) { ) {
in_directive = false; in_directive = false;
} }
@ -956,24 +896,24 @@ function OutputStream(options) {
in_directive = false; in_directive = false;
} }
AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) { AST.StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
force_statement(this.body, output); force_statement(this.body, output);
}); });
DEFPRINT(AST_Statement, function(self, output) { DEFPRINT(AST.Statement, function(self, output) {
self.body.print(output); self.body.print(output);
output.semicolon(); output.semicolon();
}); });
DEFPRINT(AST_Toplevel, function(self, output) { DEFPRINT(AST.Toplevel, function(self, output) {
display_body(self.body, true, output, true); display_body(self.body, true, output, true);
output.print(""); output.print("");
}); });
DEFPRINT(AST_LabeledStatement, function(self, output) { DEFPRINT(AST.LabeledStatement, function(self, output) {
self.label.print(output); self.label.print(output);
output.colon(); output.colon();
self.body.print(output); self.body.print(output);
}); });
DEFPRINT(AST_SimpleStatement, function(self, output) { DEFPRINT(AST.SimpleStatement, function(self, output) {
self.body.print(output); self.body.print(output);
output.semicolon(); output.semicolon();
}); });
@ -991,13 +931,13 @@ function OutputStream(options) {
}); });
} else print_braced_empty(self, output); } else print_braced_empty(self, output);
} }
DEFPRINT(AST_BlockStatement, function(self, output) { DEFPRINT(AST.BlockStatement, function(self, output) {
print_braced(self, output); print_braced(self, output);
}); });
DEFPRINT(AST_EmptyStatement, function(self, output) { DEFPRINT(AST.EmptyStatement, function(self, output) {
output.semicolon(); output.semicolon();
}); });
DEFPRINT(AST_Do, function(self, output) { DEFPRINT(AST.Do, function(self, output) {
output.print("do"); output.print("do");
output.space(); output.space();
make_block(self.body, output); make_block(self.body, output);
@ -1009,7 +949,7 @@ function OutputStream(options) {
}); });
output.semicolon(); output.semicolon();
}); });
DEFPRINT(AST_While, function(self, output) { DEFPRINT(AST.While, function(self, output) {
output.print("while"); output.print("while");
output.space(); output.space();
output.with_parens(function() { output.with_parens(function() {
@ -1018,12 +958,12 @@ function OutputStream(options) {
output.space(); output.space();
self._do_print_body(output); self._do_print_body(output);
}); });
DEFPRINT(AST_For, function(self, output) { DEFPRINT(AST.For, function(self, output) {
output.print("for"); output.print("for");
output.space(); output.space();
output.with_parens(function() { output.with_parens(function() {
if (self.init) { if (self.init) {
if (self.init instanceof AST_Definitions) { if (self.init instanceof AST.Definitions) {
self.init.print(output); self.init.print(output);
} else { } else {
parenthesize_for_noin(self.init, output, true); parenthesize_for_noin(self.init, output, true);
@ -1047,7 +987,7 @@ function OutputStream(options) {
output.space(); output.space();
self._do_print_body(output); self._do_print_body(output);
}); });
DEFPRINT(AST_ForIn, function(self, output) { DEFPRINT(AST.ForIn, function(self, output) {
output.print("for"); output.print("for");
output.space(); output.space();
output.with_parens(function() { output.with_parens(function() {
@ -1060,7 +1000,7 @@ function OutputStream(options) {
output.space(); output.space();
self._do_print_body(output); self._do_print_body(output);
}); });
DEFPRINT(AST_With, function(self, output) { DEFPRINT(AST.With, function(self, output) {
output.print("with"); output.print("with");
output.space(); output.space();
output.with_parens(function() { output.with_parens(function() {
@ -1071,7 +1011,7 @@ function OutputStream(options) {
}); });
/* -----[ functions ]----- */ /* -----[ functions ]----- */
AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) { AST.Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
var self = this; var self = this;
if (!nokeyword) { if (!nokeyword) {
output.print("function"); output.print("function");
@ -1089,7 +1029,7 @@ function OutputStream(options) {
output.space(); output.space();
print_braced(self, output, true); print_braced(self, output, true);
}); });
DEFPRINT(AST_Lambda, function(self, output) { DEFPRINT(AST.Lambda, function(self, output) {
self._do_print(output); self._do_print(output);
}); });
@ -1103,16 +1043,16 @@ function OutputStream(options) {
output.semicolon(); output.semicolon();
} }
DEFPRINT(AST_Return, function(self, output) { DEFPRINT(AST.Return, function(self, output) {
print_jump(output, "return", self.value); print_jump(output, "return", self.value);
}); });
DEFPRINT(AST_Throw, function(self, output) { DEFPRINT(AST.Throw, function(self, output) {
print_jump(output, "throw", self.value); print_jump(output, "throw", self.value);
}); });
DEFPRINT(AST_Break, function(self, output) { DEFPRINT(AST.Break, function(self, output) {
print_jump(output, "break", self.label); print_jump(output, "break", self.label);
}); });
DEFPRINT(AST_Continue, function(self, output) { DEFPRINT(AST.Continue, function(self, output) {
print_jump(output, "continue", self.label); print_jump(output, "continue", self.label);
}); });
@ -1120,7 +1060,7 @@ function OutputStream(options) {
function make_then(self, output) { function make_then(self, output) {
var b = self.body; var b = self.body;
if (output.option("braces") if (output.option("braces")
|| output.option("ie8") && b instanceof AST_Do) || output.option("ie8") && b instanceof AST.Do)
return make_block(b, output); return make_block(b, output);
// The squeezer replaces "block"-s that contain only a single // The squeezer replaces "block"-s that contain only a single
// statement with the statement itself; technically, the AST // statement with the statement itself; technically, the AST
@ -1131,21 +1071,21 @@ function OutputStream(options) {
// adds the block braces if needed. // adds the block braces if needed.
if (!b) return output.force_semicolon(); if (!b) return output.force_semicolon();
while (true) { while (true) {
if (b instanceof AST_If) { if (b instanceof AST.If) {
if (!b.alternative) { if (!b.alternative) {
make_block(self.body, output); make_block(self.body, output);
return; return;
} }
b = b.alternative; b = b.alternative;
} }
else if (b instanceof AST_StatementWithBody) { else if (b instanceof AST.StatementWithBody) {
b = b.body; b = b.body;
} }
else break; else break;
} }
force_statement(self.body, output); force_statement(self.body, output);
} }
DEFPRINT(AST_If, function(self, output) { DEFPRINT(AST.If, function(self, output) {
output.print("if"); output.print("if");
output.space(); output.space();
output.with_parens(function() { output.with_parens(function() {
@ -1157,7 +1097,7 @@ function OutputStream(options) {
output.space(); output.space();
output.print("else"); output.print("else");
output.space(); output.space();
if (self.alternative instanceof AST_If) if (self.alternative instanceof AST.If)
self.alternative.print(output); self.alternative.print(output);
else else
force_statement(self.alternative, output); force_statement(self.alternative, output);
@ -1167,7 +1107,7 @@ function OutputStream(options) {
}); });
/* -----[ switch ]----- */ /* -----[ switch ]----- */
DEFPRINT(AST_Switch, function(self, output) { DEFPRINT(AST.Switch, function(self, output) {
output.print("switch"); output.print("switch");
output.space(); output.space();
output.with_parens(function() { output.with_parens(function() {
@ -1185,7 +1125,7 @@ function OutputStream(options) {
}); });
}); });
}); });
AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) { AST.SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
output.newline(); output.newline();
this.body.forEach(function(stmt) { this.body.forEach(function(stmt) {
output.indent(); output.indent();
@ -1193,11 +1133,11 @@ function OutputStream(options) {
output.newline(); output.newline();
}); });
}); });
DEFPRINT(AST_Default, function(self, output) { DEFPRINT(AST.Default, function(self, output) {
output.print("default:"); output.print("default:");
self._do_print_body(output); self._do_print_body(output);
}); });
DEFPRINT(AST_Case, function(self, output) { DEFPRINT(AST.Case, function(self, output) {
output.print("case"); output.print("case");
output.space(); output.space();
self.expression.print(output); self.expression.print(output);
@ -1206,7 +1146,7 @@ function OutputStream(options) {
}); });
/* -----[ exceptions ]----- */ /* -----[ exceptions ]----- */
DEFPRINT(AST_Try, function(self, output) { DEFPRINT(AST.Try, function(self, output) {
output.print("try"); output.print("try");
output.space(); output.space();
print_braced(self, output); print_braced(self, output);
@ -1219,7 +1159,7 @@ function OutputStream(options) {
self.bfinally.print(output); self.bfinally.print(output);
} }
}); });
DEFPRINT(AST_Catch, function(self, output) { DEFPRINT(AST.Catch, function(self, output) {
output.print("catch"); output.print("catch");
output.space(); output.space();
output.with_parens(function() { output.with_parens(function() {
@ -1228,13 +1168,13 @@ function OutputStream(options) {
output.space(); output.space();
print_braced(self, output); print_braced(self, output);
}); });
DEFPRINT(AST_Finally, function(self, output) { DEFPRINT(AST.Finally, function(self, output) {
output.print("finally"); output.print("finally");
output.space(); output.space();
print_braced(self, output); print_braced(self, output);
}); });
DEFPRINT(AST_Var, function(self, output) { DEFPRINT(AST.Var, function(self, output) {
output.print("var"); output.print("var");
output.space(); output.space();
self.definitions.forEach(function(def, i) { self.definitions.forEach(function(def, i) {
@ -1242,7 +1182,7 @@ function OutputStream(options) {
def.print(output); def.print(output);
}); });
var p = output.parent(); var p = output.parent();
if (p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon(); if (p.init !== self || !(p instanceof AST.For || p instanceof AST.ForIn)) output.semicolon();
}); });
function parenthesize_for_noin(node, output, noin) { function parenthesize_for_noin(node, output, noin) {
@ -1250,8 +1190,8 @@ function OutputStream(options) {
// need to take some precautions here: // need to take some precautions here:
// https://github.com/mishoo/UglifyJS2/issues/60 // https://github.com/mishoo/UglifyJS2/issues/60
if (noin) node.walk(new TreeWalker(function(node) { if (noin) node.walk(new TreeWalker(function(node) {
if (parens || node instanceof AST_Scope) return true; if (parens || node instanceof AST.Scope) return true;
if (node instanceof AST_Binary && node.operator == "in") { if (node instanceof AST.Binary && node.operator == "in") {
parens = true; parens = true;
return true; return true;
} }
@ -1259,24 +1199,24 @@ function OutputStream(options) {
node.print(output, parens); node.print(output, parens);
} }
DEFPRINT(AST_VarDef, function(self, output) { DEFPRINT(AST.VarDef, function(self, output) {
self.name.print(output); self.name.print(output);
if (self.value) { if (self.value) {
output.space(); output.space();
output.print("="); output.print("=");
output.space(); output.space();
var p = output.parent(1); var p = output.parent(1);
var noin = p instanceof AST_For || p instanceof AST_ForIn; var noin = p instanceof AST.For || p instanceof AST.ForIn;
parenthesize_for_noin(self.value, output, noin); parenthesize_for_noin(self.value, output, noin);
} }
}); });
/* -----[ other expressions ]----- */ /* -----[ other expressions ]----- */
DEFPRINT(AST_Call, function(self, output) { DEFPRINT(AST.Call, function(self, output) {
self.expression.print(output); self.expression.print(output);
if (self instanceof AST_New && !need_constructor_parens(self, output)) if (self instanceof AST.New && !need_constructor_parens(self, output))
return; return;
if (self.expression instanceof AST_Call || self.expression instanceof AST_Lambda) { if (self.expression instanceof AST.Call || self.expression instanceof AST.Lambda) {
output.add_mapping(self.start); output.add_mapping(self.start);
} }
output.with_parens(function() { output.with_parens(function() {
@ -1286,12 +1226,12 @@ function OutputStream(options) {
}); });
}); });
}); });
DEFPRINT(AST_New, function(self, output) { DEFPRINT(AST.New, function(self, output) {
output.print("new"); output.print("new");
output.space(); output.space();
AST_Call.prototype._codegen(self, output); AST.Call.prototype._codegen(self, output);
}); });
DEFPRINT(AST_Sequence, function(self, output) { DEFPRINT(AST.Sequence, function(self, output) {
self.expressions.forEach(function(node, index) { self.expressions.forEach(function(node, index) {
if (index > 0) { if (index > 0) {
output.comma(); output.comma();
@ -1303,7 +1243,7 @@ function OutputStream(options) {
node.print(output); node.print(output);
}); });
}); });
DEFPRINT(AST_Dot, function(self, output) { DEFPRINT(AST.Dot, function(self, output) {
var expr = self.expression; var expr = self.expression;
expr.print(output); expr.print(output);
var prop = self.property; var prop = self.property;
@ -1313,7 +1253,7 @@ function OutputStream(options) {
output.print_string(prop); output.print_string(prop);
output.print("]"); output.print("]");
} else { } else {
if (expr instanceof AST_Number && expr.getValue() >= 0) { if (expr instanceof AST.Number && expr.getValue() >= 0) {
if (!/[xa-f.)]/i.test(output.last())) { if (!/[xa-f.)]/i.test(output.last())) {
output.print("."); output.print(".");
} }
@ -1324,32 +1264,32 @@ function OutputStream(options) {
output.print_name(prop); output.print_name(prop);
} }
}); });
DEFPRINT(AST_Sub, function(self, output) { DEFPRINT(AST.Sub, function(self, output) {
self.expression.print(output); self.expression.print(output);
output.print("["); output.print("[");
self.property.print(output); self.property.print(output);
output.print("]"); output.print("]");
}); });
DEFPRINT(AST_UnaryPrefix, function(self, output) { DEFPRINT(AST.UnaryPrefix, function(self, output) {
var op = self.operator; var op = self.operator;
output.print(op); output.print(op);
if (/^[a-z]/i.test(op) if (/^[a-z]/i.test(op)
|| (/[+-]$/.test(op) || (/[+-]$/.test(op)
&& self.expression instanceof AST_UnaryPrefix && self.expression instanceof AST.UnaryPrefix
&& /^[+-]/.test(self.expression.operator))) { && /^[+-]/.test(self.expression.operator))) {
output.space(); output.space();
} }
self.expression.print(output); self.expression.print(output);
}); });
DEFPRINT(AST_UnaryPostfix, function(self, output) { DEFPRINT(AST.UnaryPostfix, function(self, output) {
self.expression.print(output); self.expression.print(output);
output.print(self.operator); output.print(self.operator);
}); });
DEFPRINT(AST_Binary, function(self, output) { DEFPRINT(AST.Binary, function(self, output) {
var op = self.operator; var op = self.operator;
self.left.print(output); self.left.print(output);
if (op[0] == ">" /* ">>" ">>>" ">" ">=" */ if (op[0] == ">" /* ">>" ">>>" ">" ">=" */
&& self.left instanceof AST_UnaryPostfix && self.left instanceof AST.UnaryPostfix
&& self.left.operator == "--") { && self.left.operator == "--") {
// space is mandatory to avoid outputting --> // space is mandatory to avoid outputting -->
output.print(" "); output.print(" ");
@ -1359,9 +1299,9 @@ function OutputStream(options) {
} }
output.print(op); output.print(op);
if ((op == "<" || op == "<<") if ((op == "<" || op == "<<")
&& self.right instanceof AST_UnaryPrefix && self.right instanceof AST.UnaryPrefix
&& self.right.operator == "!" && self.right.operator == "!"
&& self.right.expression instanceof AST_UnaryPrefix && self.right.expression instanceof AST.UnaryPrefix
&& self.right.expression.operator == "--") { && self.right.expression.operator == "--") {
// space is mandatory to avoid outputting <!-- // space is mandatory to avoid outputting <!--
output.print(" "); output.print(" ");
@ -1371,7 +1311,7 @@ function OutputStream(options) {
} }
self.right.print(output); self.right.print(output);
}); });
DEFPRINT(AST_Conditional, function(self, output) { DEFPRINT(AST.Conditional, function(self, output) {
self.condition.print(output); self.condition.print(output);
output.space(); output.space();
output.print("?"); output.print("?");
@ -1383,7 +1323,7 @@ function OutputStream(options) {
}); });
/* -----[ literals ]----- */ /* -----[ literals ]----- */
DEFPRINT(AST_Array, function(self, output) { DEFPRINT(AST.Array, function(self, output) {
output.with_square(function() { output.with_square(function() {
var a = self.elements, len = a.length; var a = self.elements, len = a.length;
if (len > 0) output.space(); if (len > 0) output.space();
@ -1393,13 +1333,13 @@ function OutputStream(options) {
// If the final element is a hole, we need to make sure it // If the final element is a hole, we need to make sure it
// doesn't look like a trailing comma, by inserting an actual // doesn't look like a trailing comma, by inserting an actual
// trailing comma. // trailing comma.
if (i === len - 1 && exp instanceof AST_Hole) if (i === len - 1 && exp instanceof AST.Hole)
output.comma(); output.comma();
}); });
if (len > 0) output.space(); if (len > 0) output.space();
}); });
}); });
DEFPRINT(AST_Object, function(self, output) { DEFPRINT(AST.Object, function(self, output) {
if (self.properties.length > 0) output.with_block(function() { if (self.properties.length > 0) output.with_block(function() {
self.properties.forEach(function(prop, i) { self.properties.forEach(function(prop, i) {
if (i) { if (i) {
@ -1430,38 +1370,38 @@ function OutputStream(options) {
} }
} }
DEFPRINT(AST_ObjectKeyVal, function(self, output) { DEFPRINT(AST.ObjectKeyVal, function(self, output) {
print_property_name(self.key, self.quote, output); print_property_name(self.key, self.quote, output);
output.colon(); output.colon();
self.value.print(output); self.value.print(output);
}); });
AST_ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) { AST.ObjectProperty.DEFMETHOD("_print_getter_setter", function(type, output) {
output.print(type); output.print(type);
output.space(); output.space();
print_property_name(this.key.name, this.quote, output); print_property_name(this.key.name, this.quote, output);
this.value._do_print(output, true); this.value._do_print(output, true);
}); });
DEFPRINT(AST_ObjectSetter, function(self, output) { DEFPRINT(AST.ObjectSetter, function(self, output) {
self._print_getter_setter("set", output); self._print_getter_setter("set", output);
}); });
DEFPRINT(AST_ObjectGetter, function(self, output) { DEFPRINT(AST.ObjectGetter, function(self, output) {
self._print_getter_setter("get", output); self._print_getter_setter("get", output);
}); });
DEFPRINT(AST_Symbol, function(self, output) { DEFPRINT(AST.Symbol, function(self, output) {
var def = self.definition(); var def = self.definition();
output.print_name(def ? def.mangled_name || def.name : self.name); output.print_name(def ? def.mangled_name || def.name : self.name);
}); });
DEFPRINT(AST_Hole, noop); DEFPRINT(AST.Hole, noop);
DEFPRINT(AST_This, function(self, output) { DEFPRINT(AST.This, function(self, output) {
output.print("this"); output.print("this");
}); });
DEFPRINT(AST_Constant, function(self, output) { DEFPRINT(AST.Constant, function(self, output) {
output.print(self.getValue()); output.print(self.getValue());
}); });
DEFPRINT(AST_String, function(self, output) { DEFPRINT(AST.String, function(self, output) {
output.print_string(self.getValue(), self.quote, in_directive); output.print_string(self.getValue(), self.quote, in_directive);
}); });
DEFPRINT(AST_Number, function(self, output) { DEFPRINT(AST.Number, function(self, output) {
if (use_asm && self.start && self.start.raw != null) { if (use_asm && self.start && self.start.raw != null) {
output.print(self.start.raw); output.print(self.start.raw);
} else { } else {
@ -1469,7 +1409,7 @@ function OutputStream(options) {
} }
}); });
DEFPRINT(AST_RegExp, function(self, output) { DEFPRINT(AST.RegExp, function(self, output) {
var regexp = self.getValue(); var regexp = self.getValue();
var str = regexp.toString(); var str = regexp.toString();
if (regexp.raw_source) { if (regexp.raw_source) {
@ -1478,7 +1418,7 @@ function OutputStream(options) {
str = output.to_utf8(str); str = output.to_utf8(str);
output.print(str); output.print(str);
var p = output.parent(); var p = output.parent();
if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) if (p instanceof AST.Binary && /^in/.test(p.operator) && p.left === self)
output.print(" "); output.print(" ");
}); });
@ -1486,14 +1426,14 @@ function OutputStream(options) {
if (output.option("braces")) { if (output.option("braces")) {
make_block(stat, output); make_block(stat, output);
} else { } else {
if (!stat || stat instanceof AST_EmptyStatement) if (!stat || stat instanceof AST.EmptyStatement)
output.force_semicolon(); output.force_semicolon();
else else
stat.print(output); stat.print(output);
} }
} }
// self should be AST_New. decide if we want to show parens or not. // self should be AST.New. decide if we want to show parens or not.
function need_constructor_parens(self, output) { function need_constructor_parens(self, output) {
// Always print parentheses with arguments // Always print parentheses with arguments
if (self.args.length > 0) return true; if (self.args.length > 0) return true;
@ -1537,9 +1477,9 @@ function OutputStream(options) {
} }
function make_block(stmt, output) { function make_block(stmt, output) {
if (!stmt || stmt instanceof AST_EmptyStatement) if (!stmt || stmt instanceof AST.EmptyStatement)
output.print("{}"); output.print("{}");
else if (stmt instanceof AST_BlockStatement) else if (stmt instanceof AST.BlockStatement)
stmt.print(output); stmt.print(output);
else output.with_block(function() { else output.with_block(function() {
output.indent(); output.indent();
@ -1559,44 +1499,44 @@ function OutputStream(options) {
DEFMAP([ DEFMAP([
// We could easily add info for ALL nodes, but it seems to me that // We could easily add info for ALL nodes, but it seems to me that
// would be quite wasteful, hence this noop in the base class. // would be quite wasteful, hence this noop in the base class.
AST_Node, AST.Node,
// since the label symbol will mark it // since the label symbol will mark it
AST_LabeledStatement, AST.LabeledStatement,
AST_Toplevel, AST.Toplevel,
], noop); ], noop);
// XXX: I'm not exactly sure if we need it for all of these nodes, // XXX: I'm not exactly sure if we need it for all of these nodes,
// or if we should add even more. // or if we should add even more.
DEFMAP([ DEFMAP([
AST_Array, AST.Array,
AST_BlockStatement, AST.BlockStatement,
AST_Catch, AST.Catch,
AST_Constant, AST.Constant,
AST_Debugger, AST.Debugger,
AST_Definitions, AST.Definitions,
AST_Directive, AST.Directive,
AST_Finally, AST.Finally,
AST_Jump, AST.Jump,
AST_Lambda, AST.Lambda,
AST_New, AST.New,
AST_Object, AST.Object,
AST_StatementWithBody, AST.StatementWithBody,
AST_Symbol, AST.Symbol,
AST_Switch, AST.Switch,
AST_SwitchBranch, AST.SwitchBranch,
AST_Try, AST.Try,
], function(output) { ], function(output) {
output.add_mapping(this.start); output.add_mapping(this.start);
}); });
DEFMAP([ DEFMAP([
AST_ObjectGetter, AST.ObjectGetter,
AST_ObjectSetter, AST.ObjectSetter,
], function(output) { ], function(output) {
output.add_mapping(this.start, this.key.name); output.add_mapping(this.start, this.key.name);
}); });
DEFMAP([ AST_ObjectProperty ], function(output) { DEFMAP([ AST.ObjectProperty ], function(output) {
output.add_mapping(this.start, this.key); output.add_mapping(this.start, this.key);
}); });
})(); })();

View File

@ -54,72 +54,7 @@ var all = utils.all;
var HOP = utils.HOP; var HOP = utils.HOP;
var merge = utils.merge; var merge = utils.merge;
var ast = require("./ast"); var AST = require("./ast");
var AST_Token = ast.AST_Token;
var AST_Debugger = ast.AST_Debugger;
var AST_Directive = ast.AST_Directive;
var AST_SimpleStatement = ast.AST_SimpleStatement;
var AST_BlockStatement = ast.AST_BlockStatement;
var AST_EmptyStatement = ast.AST_EmptyStatement;
var AST_LabeledStatement = ast.AST_LabeledStatement;
var AST_IterationStatement = ast.AST_IterationStatement;
var AST_Do = ast.AST_Do;
var AST_While = ast.AST_While;
var AST_For = ast.AST_For;
var AST_ForIn = ast.AST_ForIn;
var AST_With = ast.AST_With;
var AST_Toplevel = ast.AST_Toplevel;
var AST_Lambda = ast.AST_Lambda;
var AST_Accessor = ast.AST_Accessor;
var AST_Function = ast.AST_Function;
var AST_Defun = ast.AST_Defun;
var AST_Return = ast.AST_Return;
var AST_Throw = ast.AST_Throw;
var AST_Break = ast.AST_Break;
var AST_Continue = ast.AST_Continue;
var AST_If = ast.AST_If;
var AST_Switch = ast.AST_Switch;
var AST_Default = ast.AST_Default;
var AST_Case = ast.AST_Case;
var AST_Try = ast.AST_Try;
var AST_Catch = ast.AST_Catch;
var AST_Finally = ast.AST_Finally;
var AST_Var = ast.AST_Var;
var AST_VarDef = ast.AST_VarDef;
var AST_Call = ast.AST_Call;
var AST_New = ast.AST_New;
var AST_Sequence = ast.AST_Sequence;
var AST_PropAccess = ast.AST_PropAccess;
var AST_Dot = ast.AST_Dot;
var AST_Sub = ast.AST_Sub;
var AST_UnaryPrefix = ast.AST_UnaryPrefix;
var AST_UnaryPostfix = ast.AST_UnaryPostfix;
var AST_Binary = ast.AST_Binary;
var AST_Conditional = ast.AST_Conditional;
var AST_Assign = ast.AST_Assign;
var AST_Array = ast.AST_Array;
var AST_Object = ast.AST_Object;
var AST_ObjectKeyVal = ast.AST_ObjectKeyVal;
var AST_ObjectSetter = ast.AST_ObjectSetter;
var AST_ObjectGetter = ast.AST_ObjectGetter;
var AST_SymbolAccessor = ast.AST_SymbolAccessor;
var AST_SymbolDeclaration = ast.AST_SymbolDeclaration;
var AST_SymbolVar = ast.AST_SymbolVar;
var AST_SymbolFunarg = ast.AST_SymbolFunarg;
var AST_SymbolDefun = ast.AST_SymbolDefun;
var AST_SymbolLambda = ast.AST_SymbolLambda;
var AST_SymbolCatch = ast.AST_SymbolCatch;
var AST_Label = ast.AST_Label;
var AST_SymbolRef = ast.AST_SymbolRef;
var AST_LabelRef = ast.AST_LabelRef;
var AST_This = ast.AST_This;
var AST_String = ast.AST_String;
var AST_Number = ast.AST_Number;
var AST_RegExp = ast.AST_RegExp;
var AST_Null = ast.AST_Null;
var AST_Hole = ast.AST_Hole;
var AST_False = ast.AST_False;
var AST_True = ast.AST_True;
var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with'; var KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
var KEYWORDS_ATOM = 'false null true'; var KEYWORDS_ATOM = 'false null true';
@ -399,7 +334,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
ret.comments_after = S.comments_before = []; ret.comments_after = S.comments_before = [];
} }
S.newline_before = false; S.newline_before = false;
return new AST_Token(ret); return new AST.Token(ret);
} }
function skip_whitespace() { function skip_whitespace() {
@ -910,7 +845,7 @@ function parse($TEXT, options) {
} }
} }
var dir = S.in_directives, stat = simple_statement(); var dir = S.in_directives, stat = simple_statement();
return dir ? new AST_Directive(stat.body) : stat; return dir ? new AST.Directive(stat.body) : stat;
case "num": case "num":
case "regexp": case "regexp":
case "operator": case "operator":
@ -925,7 +860,7 @@ function parse($TEXT, options) {
case "punc": case "punc":
switch (S.token.value) { switch (S.token.value) {
case "{": case "{":
return new AST_BlockStatement({ return new AST.BlockStatement({
start : S.token, start : S.token,
body : block_(), body : block_(),
end : prev() end : prev()
@ -936,7 +871,7 @@ function parse($TEXT, options) {
case ";": case ";":
S.in_directives = false; S.in_directives = false;
next(); next();
return new AST_EmptyStatement(); return new AST.EmptyStatement();
default: default:
unexpected(); unexpected();
} }
@ -945,16 +880,16 @@ function parse($TEXT, options) {
switch (S.token.value) { switch (S.token.value) {
case "break": case "break":
next(); next();
return break_cont(AST_Break); return break_cont(AST.Break);
case "continue": case "continue":
next(); next();
return break_cont(AST_Continue); return break_cont(AST.Continue);
case "debugger": case "debugger":
next(); next();
semicolon(); semicolon();
return new AST_Debugger(); return new AST.Debugger();
case "do": case "do":
next(); next();
@ -962,14 +897,14 @@ function parse($TEXT, options) {
expect_token("keyword", "while"); expect_token("keyword", "while");
var condition = parenthesised(); var condition = parenthesised();
semicolon(true); semicolon(true);
return new AST_Do({ return new AST.Do({
body : body, body : body,
condition : condition condition : condition
}); });
case "while": case "while":
next(); next();
return new AST_While({ return new AST.While({
condition : parenthesised(), condition : parenthesised(),
body : in_loop(statement) body : in_loop(statement)
}); });
@ -983,7 +918,7 @@ function parse($TEXT, options) {
croak("In strict mode code, functions can only be declared at top level or immediately within another function."); croak("In strict mode code, functions can only be declared at top level or immediately within another function.");
} }
next(); next();
return function_(AST_Defun); return function_(AST.Defun);
case "if": case "if":
next(); next();
@ -1000,13 +935,13 @@ function parse($TEXT, options) {
value = expression(true); value = expression(true);
semicolon(); semicolon();
} }
return new AST_Return({ return new AST.Return({
value: value value: value
}); });
case "switch": case "switch":
next(); next();
return new AST_Switch({ return new AST.Switch({
expression : parenthesised(), expression : parenthesised(),
body : in_loop(switch_body_) body : in_loop(switch_body_)
}); });
@ -1017,7 +952,7 @@ function parse($TEXT, options) {
croak("Illegal newline after 'throw'"); croak("Illegal newline after 'throw'");
var value = expression(true); var value = expression(true);
semicolon(); semicolon();
return new AST_Throw({ return new AST.Throw({
value: value value: value
}); });
@ -1036,7 +971,7 @@ function parse($TEXT, options) {
croak("Strict mode may not include a with statement"); croak("Strict mode may not include a with statement");
} }
next(); next();
return new AST_With({ return new AST.With({
expression : parenthesised(), expression : parenthesised(),
body : statement() body : statement()
}); });
@ -1046,7 +981,7 @@ function parse($TEXT, options) {
}); });
function labeled_statement() { function labeled_statement() {
var label = as_symbol(AST_Label); var label = as_symbol(AST.Label);
if (!all(S.labels, function(l) { if (!all(S.labels, function(l) {
return l.name != label.name; return l.name != label.name;
})) { })) {
@ -1060,29 +995,29 @@ function parse($TEXT, options) {
S.labels.push(label); S.labels.push(label);
var stat = statement(); var stat = statement();
S.labels.pop(); S.labels.pop();
if (!(stat instanceof AST_IterationStatement)) { if (!(stat instanceof AST.IterationStatement)) {
// check for `continue` that refers to this label. // check for `continue` that refers to this label.
// those should be reported as syntax errors. // those should be reported as syntax errors.
// https://github.com/mishoo/UglifyJS2/issues/287 // https://github.com/mishoo/UglifyJS2/issues/287
label.references.forEach(function(ref) { label.references.forEach(function(ref) {
if (ref instanceof AST_Continue) { if (ref instanceof AST.Continue) {
ref = ref.label.start; ref = ref.label.start;
croak("Continue label `" + label.name + "` refers to non-IterationStatement.", croak("Continue label `" + label.name + "` refers to non-IterationStatement.",
ref.line, ref.col, ref.pos); ref.line, ref.col, ref.pos);
} }
}); });
} }
return new AST_LabeledStatement({ body: stat, label: label }); return new AST.LabeledStatement({ body: stat, label: label });
} }
function simple_statement(tmp) { function simple_statement(tmp) {
return new AST_SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) }); return new AST.SimpleStatement({ body: (tmp = expression(true), semicolon(), tmp) });
} }
function break_cont(type) { function break_cont(type) {
var label = null, ldef; var label = null, ldef;
if (!can_insert_semicolon()) { if (!can_insert_semicolon()) {
label = as_symbol(AST_LabelRef, true); label = as_symbol(AST.LabelRef, true);
} }
if (label != null) { if (label != null) {
ldef = find_if(function(l) { ldef = find_if(function(l) {
@ -1105,7 +1040,7 @@ function parse($TEXT, options) {
? (next(), var_(true)) ? (next(), var_(true))
: expression(true, true); : expression(true, true);
if (is("operator", "in")) { if (is("operator", "in")) {
if (init instanceof AST_Var) { if (init instanceof AST.Var) {
if (init.definitions.length > 1) if (init.definitions.length > 1)
croak("Only one variable declaration allowed in for..in loop", init.start.line, init.start.col, init.start.pos); croak("Only one variable declaration allowed in for..in loop", init.start.line, init.start.col, init.start.pos);
} else if (!is_assignable(init)) { } else if (!is_assignable(init)) {
@ -1124,7 +1059,7 @@ function parse($TEXT, options) {
expect(";"); expect(";");
var step = is("punc", ")") ? null : expression(true); var step = is("punc", ")") ? null : expression(true);
expect(")"); expect(")");
return new AST_For({ return new AST.For({
init : init, init : init,
condition : test, condition : test,
step : step, step : step,
@ -1135,7 +1070,7 @@ function parse($TEXT, options) {
function for_in(init) { function for_in(init) {
var obj = expression(true); var obj = expression(true);
expect(")"); expect(")");
return new AST_ForIn({ return new AST.ForIn({
init : init, init : init,
object : obj, object : obj,
body : in_loop(statement) body : in_loop(statement)
@ -1143,17 +1078,17 @@ function parse($TEXT, options) {
} }
var function_ = function(ctor) { var function_ = function(ctor) {
var in_statement = ctor === AST_Defun; var in_statement = ctor === AST.Defun;
var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null; var name = is("name") ? as_symbol(in_statement ? AST.SymbolDefun : AST.SymbolLambda) : null;
if (in_statement && !name) if (in_statement && !name)
unexpected(); unexpected();
if (name && ctor !== AST_Accessor && !(name instanceof AST_SymbolDeclaration)) if (name && ctor !== AST.Accessor && !(name instanceof AST.SymbolDeclaration))
unexpected(prev()); unexpected(prev());
expect("("); expect("(");
var argnames = []; var argnames = [];
for (var first = true; !is("punc", ")");) { for (var first = true; !is("punc", ")");) {
if (first) first = false; else expect(","); if (first) first = false; else expect(",");
argnames.push(as_symbol(AST_SymbolFunarg)); argnames.push(as_symbol(AST.SymbolFunarg));
} }
next(); next();
var loop = S.in_loop; var loop = S.in_loop;
@ -1185,7 +1120,7 @@ function parse($TEXT, options) {
next(); next();
belse = statement(); belse = statement();
} }
return new AST_If({ return new AST.If({
condition : cond, condition : cond,
body : body, body : body,
alternative : belse alternative : belse
@ -1211,7 +1146,7 @@ function parse($TEXT, options) {
if (is("keyword", "case")) { if (is("keyword", "case")) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
cur = []; cur = [];
branch = new AST_Case({ branch = new AST.Case({
start : (tmp = S.token, next(), tmp), start : (tmp = S.token, next(), tmp),
expression : expression(true), expression : expression(true),
body : cur body : cur
@ -1222,7 +1157,7 @@ function parse($TEXT, options) {
else if (is("keyword", "default")) { else if (is("keyword", "default")) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
cur = []; cur = [];
branch = new AST_Default({ branch = new AST.Default({
start : (tmp = S.token, next(), expect(":"), tmp), start : (tmp = S.token, next(), expect(":"), tmp),
body : cur body : cur
}); });
@ -1244,9 +1179,9 @@ function parse($TEXT, options) {
var start = S.token; var start = S.token;
next(); next();
expect("("); expect("(");
var name = as_symbol(AST_SymbolCatch); var name = as_symbol(AST.SymbolCatch);
expect(")"); expect(")");
bcatch = new AST_Catch({ bcatch = new AST.Catch({
start : start, start : start,
argname : name, argname : name,
body : block_(), body : block_(),
@ -1256,7 +1191,7 @@ function parse($TEXT, options) {
if (is("keyword", "finally")) { if (is("keyword", "finally")) {
var start = S.token; var start = S.token;
next(); next();
bfinally = new AST_Finally({ bfinally = new AST.Finally({
start : start, start : start,
body : block_(), body : block_(),
end : prev() end : prev()
@ -1264,7 +1199,7 @@ function parse($TEXT, options) {
} }
if (!bcatch && !bfinally) if (!bcatch && !bfinally)
croak("Missing catch/finally blocks"); croak("Missing catch/finally blocks");
return new AST_Try({ return new AST.Try({
body : body, body : body,
bcatch : bcatch, bcatch : bcatch,
bfinally : bfinally bfinally : bfinally
@ -1274,9 +1209,9 @@ function parse($TEXT, options) {
function vardefs(no_in) { function vardefs(no_in) {
var a = []; var a = [];
for (;;) { for (;;) {
a.push(new AST_VarDef({ a.push(new AST.VarDef({
start : S.token, start : S.token,
name : as_symbol(AST_SymbolVar), name : as_symbol(AST.SymbolVar),
value : is("operator", "=") ? (next(), expression(false, no_in)) : null, value : is("operator", "=") ? (next(), expression(false, no_in)) : null,
end : prev() end : prev()
})); }));
@ -1288,7 +1223,7 @@ function parse($TEXT, options) {
} }
var var_ = function(no_in) { var var_ = function(no_in) {
return new AST_Var({ return new AST.Var({
start : prev(), start : prev(),
definitions : vardefs(no_in), definitions : vardefs(no_in),
end : prev() end : prev()
@ -1305,7 +1240,7 @@ function parse($TEXT, options) {
} else { } else {
args = []; args = [];
} }
var call = new AST_New({ var call = new AST.New({
start : start, start : start,
expression : newexp, expression : newexp,
args : args, args : args,
@ -1319,13 +1254,13 @@ function parse($TEXT, options) {
var tok = S.token, ret; var tok = S.token, ret;
switch (tok.type) { switch (tok.type) {
case "name": case "name":
ret = _make_symbol(AST_SymbolRef); ret = _make_symbol(AST.SymbolRef);
break; break;
case "num": case "num":
ret = new AST_Number({ start: tok, end: tok, value: tok.value }); ret = new AST.Number({ start: tok, end: tok, value: tok.value });
break; break;
case "string": case "string":
ret = new AST_String({ ret = new AST.String({
start : tok, start : tok,
end : tok, end : tok,
value : tok.value, value : tok.value,
@ -1333,18 +1268,18 @@ function parse($TEXT, options) {
}); });
break; break;
case "regexp": case "regexp":
ret = new AST_RegExp({ start: tok, end: tok, value: tok.value }); ret = new AST.RegExp({ start: tok, end: tok, value: tok.value });
break; break;
case "atom": case "atom":
switch (tok.value) { switch (tok.value) {
case "false": case "false":
ret = new AST_False({ start: tok, end: tok }); ret = new AST.False({ start: tok, end: tok });
break; break;
case "true": case "true":
ret = new AST_True({ start: tok, end: tok }); ret = new AST.True({ start: tok, end: tok });
break; break;
case "null": case "null":
ret = new AST_Null({ start: tok, end: tok }); ret = new AST.Null({ start: tok, end: tok });
break; break;
} }
break; break;
@ -1382,7 +1317,7 @@ function parse($TEXT, options) {
[].push.apply(ex.end.comments_after, end.comments_after); [].push.apply(ex.end.comments_after, end.comments_after);
end.comments_after = ex.end.comments_after; end.comments_after = ex.end.comments_after;
ex.end = end; ex.end = end;
if (ex instanceof AST_Call) mark_pure(ex); if (ex instanceof AST.Call) mark_pure(ex);
return subscripts(ex, allow_calls); return subscripts(ex, allow_calls);
case "[": case "[":
return subscripts(array_(), allow_calls); return subscripts(array_(), allow_calls);
@ -1393,7 +1328,7 @@ function parse($TEXT, options) {
} }
if (is("keyword", "function")) { if (is("keyword", "function")) {
next(); next();
var func = function_(AST_Function); var func = function_(AST.Function);
func.start = start; func.start = start;
func.end = prev(); func.end = prev();
return subscripts(func, allow_calls); return subscripts(func, allow_calls);
@ -1410,7 +1345,7 @@ function parse($TEXT, options) {
if (first) first = false; else expect(","); if (first) first = false; else expect(",");
if (allow_trailing_comma && is("punc", closing)) break; if (allow_trailing_comma && is("punc", closing)) break;
if (is("punc", ",") && allow_empty) { if (is("punc", ",") && allow_empty) {
a.push(new AST_Hole({ start: S.token, end: S.token })); a.push(new AST.Hole({ start: S.token, end: S.token }));
} else { } else {
a.push(expression(false)); a.push(expression(false));
} }
@ -1421,13 +1356,13 @@ function parse($TEXT, options) {
var array_ = embed_tokens(function() { var array_ = embed_tokens(function() {
expect("["); expect("[");
return new AST_Array({ return new AST.Array({
elements: expr_list("]", !options.strict, true) elements: expr_list("]", !options.strict, true)
}); });
}); });
var create_accessor = embed_tokens(function() { var create_accessor = embed_tokens(function() {
return function_(AST_Accessor); return function_(AST.Accessor);
}); });
var object_ = embed_tokens(function() { var object_ = embed_tokens(function() {
@ -1442,13 +1377,13 @@ function parse($TEXT, options) {
var type = start.type; var type = start.type;
var name = as_property_name(); var name = as_property_name();
if (type == "name" && !is("punc", ":")) { if (type == "name" && !is("punc", ":")) {
var key = new AST_SymbolAccessor({ var key = new AST.SymbolAccessor({
start: S.token, start: S.token,
name: "" + as_property_name(), name: "" + as_property_name(),
end: prev() end: prev()
}); });
if (name == "get") { if (name == "get") {
a.push(new AST_ObjectGetter({ a.push(new AST.ObjectGetter({
start : start, start : start,
key : key, key : key,
value : create_accessor(), value : create_accessor(),
@ -1457,7 +1392,7 @@ function parse($TEXT, options) {
continue; continue;
} }
if (name == "set") { if (name == "set") {
a.push(new AST_ObjectSetter({ a.push(new AST.ObjectSetter({
start : start, start : start,
key : key, key : key,
value : create_accessor(), value : create_accessor(),
@ -1467,7 +1402,7 @@ function parse($TEXT, options) {
} }
} }
expect(":"); expect(":");
a.push(new AST_ObjectKeyVal({ a.push(new AST.ObjectKeyVal({
start : start, start : start,
quote : start.quote, quote : start.quote,
key : "" + name, key : "" + name,
@ -1476,7 +1411,7 @@ function parse($TEXT, options) {
})); }));
} }
next(); next();
return new AST_Object({ properties: a }); return new AST.Object({ properties: a });
}); });
function as_property_name() { function as_property_name() {
@ -1505,7 +1440,7 @@ function parse($TEXT, options) {
function _make_symbol(type) { function _make_symbol(type) {
var name = S.token.value; var name = S.token.value;
return new (name == "this" ? AST_This : type)({ return new (name == "this" ? AST.This : type)({
name : String(name), name : String(name),
start : S.token, start : S.token,
end : S.token end : S.token
@ -1523,7 +1458,7 @@ function parse($TEXT, options) {
return null; return null;
} }
var sym = _make_symbol(type); var sym = _make_symbol(type);
if (S.input.has_directive("use strict") && sym instanceof AST_SymbolDeclaration) { if (S.input.has_directive("use strict") && sym instanceof AST.SymbolDeclaration) {
strict_verify_symbol(sym); strict_verify_symbol(sym);
} }
next(); next();
@ -1547,7 +1482,7 @@ function parse($TEXT, options) {
var start = expr.start; var start = expr.start;
if (is("punc", ".")) { if (is("punc", ".")) {
next(); next();
return subscripts(new AST_Dot({ return subscripts(new AST.Dot({
start : start, start : start,
expression : expr, expression : expr,
property : as_name(), property : as_name(),
@ -1558,7 +1493,7 @@ function parse($TEXT, options) {
next(); next();
var prop = expression(true); var prop = expression(true);
expect("]"); expect("]");
return subscripts(new AST_Sub({ return subscripts(new AST.Sub({
start : start, start : start,
expression : expr, expression : expr,
property : prop, property : prop,
@ -1567,7 +1502,7 @@ function parse($TEXT, options) {
} }
if (allow_calls && is("punc", "(")) { if (allow_calls && is("punc", "(")) {
next(); next();
var call = new AST_Call({ var call = new AST.Call({
start : start, start : start,
expression : expr, expression : expr,
args : expr_list(")"), args : expr_list(")"),
@ -1584,14 +1519,14 @@ function parse($TEXT, options) {
if (is("operator") && UNARY_PREFIX[start.value]) { if (is("operator") && UNARY_PREFIX[start.value]) {
next(); next();
handle_regexp(); handle_regexp();
var ex = make_unary(AST_UnaryPrefix, start, maybe_unary(allow_calls)); var ex = make_unary(AST.UnaryPrefix, start, maybe_unary(allow_calls));
ex.start = start; ex.start = start;
ex.end = prev(); ex.end = prev();
return ex; return ex;
} }
var val = expr_atom(allow_calls); var val = expr_atom(allow_calls);
while (is("operator") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) { while (is("operator") && UNARY_POSTFIX[S.token.value] && !has_newline_before(S.token)) {
val = make_unary(AST_UnaryPostfix, S.token, val); val = make_unary(AST.UnaryPostfix, S.token, val);
val.start = start; val.start = start;
val.end = S.token; val.end = S.token;
next(); next();
@ -1608,7 +1543,7 @@ function parse($TEXT, options) {
croak("Invalid use of " + op + " operator", token.line, token.col, token.pos); croak("Invalid use of " + op + " operator", token.line, token.col, token.pos);
break; break;
case "delete": case "delete":
if (expr instanceof AST_SymbolRef && S.input.has_directive("use strict")) if (expr instanceof AST.SymbolRef && S.input.has_directive("use strict"))
croak("Calling delete on expression not allowed in strict mode", expr.start.line, expr.start.col, expr.start.pos); croak("Calling delete on expression not allowed in strict mode", expr.start.line, expr.start.col, expr.start.pos);
break; break;
} }
@ -1622,7 +1557,7 @@ function parse($TEXT, options) {
if (prec != null && prec > min_prec) { if (prec != null && prec > min_prec) {
next(); next();
var right = expr_op(maybe_unary(true), prec, no_in); var right = expr_op(maybe_unary(true), prec, no_in);
return expr_op(new AST_Binary({ return expr_op(new AST.Binary({
start : left.start, start : left.start,
left : left, left : left,
operator : op, operator : op,
@ -1644,7 +1579,7 @@ function parse($TEXT, options) {
next(); next();
var yes = expression(false); var yes = expression(false);
expect(":"); expect(":");
return new AST_Conditional({ return new AST.Conditional({
start : start, start : start,
condition : expr, condition : expr,
consequent : yes, consequent : yes,
@ -1656,7 +1591,7 @@ function parse($TEXT, options) {
}; };
function is_assignable(expr) { function is_assignable(expr) {
return expr instanceof AST_PropAccess || expr instanceof AST_SymbolRef; return expr instanceof AST.PropAccess || expr instanceof AST.SymbolRef;
} }
var maybe_assign = function(no_in) { var maybe_assign = function(no_in) {
@ -1665,7 +1600,7 @@ function parse($TEXT, options) {
if (is("operator") && ASSIGNMENT[val]) { if (is("operator") && ASSIGNMENT[val]) {
if (is_assignable(left)) { if (is_assignable(left)) {
next(); next();
return new AST_Assign({ return new AST.Assign({
start : start, start : start,
left : left, left : left,
operator : val, operator : val,
@ -1687,7 +1622,7 @@ function parse($TEXT, options) {
next(); next();
commas = true; commas = true;
} }
return exprs.length == 1 ? exprs[0] : new AST_Sequence({ return exprs.length == 1 ? exprs[0] : new AST.Sequence({
start : start, start : start,
expressions : exprs, expressions : exprs,
end : peek() end : peek()
@ -1718,7 +1653,7 @@ function parse($TEXT, options) {
toplevel.body = toplevel.body.concat(body); toplevel.body = toplevel.body.concat(body);
toplevel.end = end; toplevel.end = end;
} else { } else {
toplevel = new AST_Toplevel({ start: start, body: body, end: end }); toplevel = new AST.Toplevel({ start: start, body: body, end: end });
} }
return toplevel; return toplevel;
}(); }();

View File

@ -52,17 +52,9 @@ var merge = utils.merge;
var scope = require("./scope"); var scope = require("./scope");
var base54 = scope.base54; var base54 = scope.base54;
var ast = require("./ast"); var AST = require("./ast");
var TreeWalker = ast.TreeWalker; var TreeWalker = AST.TreeWalker;
var TreeTransformer = ast.TreeTransformer; var TreeTransformer = AST.TreeTransformer;
var AST_Call = ast.AST_Call;
var AST_Sequence = ast.AST_Sequence;
var AST_Dot = ast.AST_Dot;
var AST_Sub = ast.AST_Sub;
var AST_Conditional = ast.AST_Conditional;
var AST_ObjectProperty = ast.AST_ObjectProperty;
var AST_ObjectKeyVal = ast.AST_ObjectKeyVal;
var AST_String = ast.AST_String;
function find_builtins(reserved) { function find_builtins(reserved) {
// NaN will be included due to Number.NaN // NaN will be included due to Number.NaN
@ -94,9 +86,9 @@ function reserve_quoted_keys(ast, reserved) {
} }
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal && node.quote) { if (node instanceof AST.ObjectKeyVal && node.quote) {
add(node.key); add(node.key);
} else if (node instanceof AST_Sub) { } else if (node instanceof AST.Sub) {
addStrings(node.property, add); addStrings(node.property, add);
} }
})); }));
@ -104,11 +96,11 @@ function reserve_quoted_keys(ast, reserved) {
function addStrings(node, add) { function addStrings(node, add) {
node.walk(new TreeWalker(function(node) { node.walk(new TreeWalker(function(node) {
if (node instanceof AST_Sequence) { if (node instanceof AST.Sequence) {
addStrings(node.tail_node(), add); addStrings(node.tail_node(), add);
} else if (node instanceof AST_String) { } else if (node instanceof AST.String) {
add(node.value); add(node.value);
} else if (node instanceof AST_Conditional) { } else if (node instanceof AST.Conditional) {
addStrings(node.consequent, add); addStrings(node.consequent, add);
addStrings(node.alternative, add); addStrings(node.alternative, add);
} }
@ -158,20 +150,20 @@ function mangle_properties(ast, options) {
// step 1: find candidates to mangle // step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST.ObjectKeyVal) {
add(node.key); add(node.key);
} }
else if (node instanceof AST_ObjectProperty) { else if (node instanceof AST.ObjectProperty) {
// setter or getter, since KeyVal is handled above // setter or getter, since KeyVal is handled above
add(node.key.name); add(node.key.name);
} }
else if (node instanceof AST_Dot) { else if (node instanceof AST.Dot) {
add(node.property); add(node.property);
} }
else if (node instanceof AST_Sub) { else if (node instanceof AST.Sub) {
addStrings(node.property, add); addStrings(node.property, add);
} }
else if (node instanceof AST_Call else if (node instanceof AST.Call
&& node.expression.print_to_string() == "Object.defineProperty") { && node.expression.print_to_string() == "Object.defineProperty") {
addStrings(node.args[1], add); addStrings(node.args[1], add);
} }
@ -179,20 +171,20 @@ function mangle_properties(ast, options) {
// step 2: transform the tree, renaming properties // step 2: transform the tree, renaming properties
return ast.transform(new TreeTransformer(function(node) { return ast.transform(new TreeTransformer(function(node) {
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST.ObjectKeyVal) {
node.key = mangle(node.key); node.key = mangle(node.key);
} }
else if (node instanceof AST_ObjectProperty) { else if (node instanceof AST.ObjectProperty) {
// setter or getter // setter or getter
node.key.name = mangle(node.key.name); node.key.name = mangle(node.key.name);
} }
else if (node instanceof AST_Dot) { else if (node instanceof AST.Dot) {
node.property = mangle(node.property); node.property = mangle(node.property);
} }
else if (!options.keep_quoted && node instanceof AST_Sub) { else if (!options.keep_quoted && node instanceof AST.Sub) {
node.property = mangleStrings(node.property); node.property = mangleStrings(node.property);
} }
else if (node instanceof AST_Call else if (node instanceof AST.Call
&& node.expression.print_to_string() == "Object.defineProperty") { && node.expression.print_to_string() == "Object.defineProperty") {
node.args[1] = mangleStrings(node.args[1]); node.args[1] = mangleStrings(node.args[1]);
} }
@ -256,14 +248,14 @@ function mangle_properties(ast, options) {
function mangleStrings(node) { function mangleStrings(node) {
return node.transform(new TreeTransformer(function(node) { return node.transform(new TreeTransformer(function(node) {
if (node instanceof AST_Sequence) { if (node instanceof AST.Sequence) {
var last = node.expressions.length - 1; var last = node.expressions.length - 1;
node.expressions[last] = mangleStrings(node.expressions[last]); node.expressions[last] = mangleStrings(node.expressions[last]);
} }
else if (node instanceof AST_String) { else if (node instanceof AST.String) {
node.value = mangle(node.value); node.value = mangle(node.value);
} }
else if (node instanceof AST_Conditional) { else if (node instanceof AST.Conditional) {
node.consequent = mangleStrings(node.consequent); node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative); node.alternative = mangleStrings(node.alternative);
} }

View File

@ -52,32 +52,8 @@ var makePredicate = utils.makePredicate;
var Dictionary = utils.Dictionary; var Dictionary = utils.Dictionary;
var merge = utils.merge; var merge = utils.merge;
var ast = require("./ast"); var AST = require("./ast");
var TreeWalker = ast.TreeWalker; var TreeWalker = AST.TreeWalker;
var AST_Node = ast.AST_Node;
var AST_LabeledStatement = ast.AST_LabeledStatement;
var AST_With = ast.AST_With;
var AST_Scope = ast.AST_Scope;
var AST_Toplevel = ast.AST_Toplevel;
var AST_Lambda = ast.AST_Lambda;
var AST_Function = ast.AST_Function;
var AST_Defun = ast.AST_Defun;
var AST_LoopControl = ast.AST_LoopControl;
var AST_Catch = ast.AST_Catch;
var AST_Call = ast.AST_Call;
var AST_Sequence = ast.AST_Sequence;
var AST_Dot = ast.AST_Dot;
var AST_Sub = ast.AST_Sub;
var AST_Conditional = ast.AST_Conditional;
var AST_Symbol = ast.AST_Symbol;
var AST_SymbolVar = ast.AST_SymbolVar;
var AST_SymbolFunarg = ast.AST_SymbolFunarg;
var AST_SymbolDefun = ast.AST_SymbolDefun;
var AST_SymbolLambda = ast.AST_SymbolLambda;
var AST_SymbolCatch = ast.AST_SymbolCatch;
var AST_Label = ast.AST_Label;
var AST_SymbolRef = ast.AST_SymbolRef;
var AST_String = ast.AST_String;
var parse = require("./parse"); var parse = require("./parse");
var is_identifier = parse.is_identifier; var is_identifier = parse.is_identifier;
@ -107,8 +83,8 @@ SymbolDef.prototype = {
|| this.undeclared || this.undeclared
|| !options.eval && this.scope.pinned() || !options.eval && this.scope.pinned()
|| options.keep_fnames || options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda && (this.orig[0] instanceof AST.SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun); || this.orig[0] instanceof AST.SymbolDefun);
}, },
mangle: function(options) { mangle: function(options) {
var cache = options.cache && options.cache.props; var cache = options.cache && options.cache.props;
@ -131,7 +107,7 @@ SymbolDef.prototype = {
} }
}; };
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { AST.Toplevel.DEFMETHOD("figure_out_scope", function(options) {
options = defaults(options, { options = defaults(options, {
cache: null, cache: null,
ie8: false, ie8: false,
@ -142,15 +118,15 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
var scope = self.parent_scope = null; var scope = self.parent_scope = null;
var defun = null; var defun = null;
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_Catch) { if (node instanceof AST.Catch) {
var save_scope = scope; var save_scope = scope;
scope = new AST_Scope(node); scope = new AST.Scope(node);
scope.init_scope_vars(save_scope); scope.init_scope_vars(save_scope);
descend(); descend();
scope = save_scope; scope = save_scope;
return true; return true;
} }
if (node instanceof AST_Scope) { if (node instanceof AST.Scope) {
node.init_scope_vars(scope); node.init_scope_vars(scope);
var save_scope = scope; var save_scope = scope;
var save_defun = defun; var save_defun = defun;
@ -160,30 +136,30 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
defun = save_defun; defun = save_defun;
return true; // don't descend again in TreeWalker return true; // don't descend again in TreeWalker
} }
if (node instanceof AST_With) { if (node instanceof AST.With) {
for (var s = scope; s; s = s.parent_scope) for (var s = scope; s; s = s.parent_scope)
s.uses_with = true; s.uses_with = true;
return; return;
} }
if (node instanceof AST_Symbol) { if (node instanceof AST.Symbol) {
node.scope = scope; node.scope = scope;
} }
if (node instanceof AST_Label) { if (node instanceof AST.Label) {
node.thedef = node; node.thedef = node;
node.references = []; node.references = [];
} }
if (node instanceof AST_SymbolLambda) { if (node instanceof AST.SymbolLambda) {
defun.def_function(node, node.name == "arguments" ? undefined : defun); defun.def_function(node, node.name == "arguments" ? undefined : defun);
} }
else if (node instanceof AST_SymbolDefun) { else if (node instanceof AST.SymbolDefun) {
// Careful here, the scope where this should be defined is // Careful here, the scope where this should be defined is
// the parent scope. The reason is that we enter a new // the parent scope. The reason is that we enter a new
// scope when we encounter the AST_Defun node (which is // scope when we encounter the AST.Defun node (which is
// instanceof AST_Scope) but we get to the symbol a bit // instanceof AST.Scope) but we get to the symbol a bit
// later. // later.
(node.scope = defun.parent_scope).def_function(node, defun); (node.scope = defun.parent_scope).def_function(node, defun);
} }
else if (node instanceof AST_SymbolVar) { else if (node instanceof AST.SymbolVar) {
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined); defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
if (defun !== scope) { if (defun !== scope) {
node.mark_enclosed(options); node.mark_enclosed(options);
@ -194,7 +170,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.reference(options); node.reference(options);
} }
} }
else if (node instanceof AST_SymbolCatch) { else if (node instanceof AST.SymbolCatch) {
scope.def_variable(node).defun = defun; scope.def_variable(node).defun = defun;
} }
}); });
@ -203,13 +179,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 2: find back references and eval // pass 2: find back references and eval
self.globals = new Dictionary(); self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_LoopControl && node.label) { if (node instanceof AST.LoopControl && node.label) {
node.label.thedef.references.push(node); node.label.thedef.references.push(node);
return true; return true;
} }
if (node instanceof AST_SymbolRef) { if (node instanceof AST.SymbolRef) {
var name = node.name; var name = node.name;
if (name == "eval" && tw.parent() instanceof AST_Call) { if (name == "eval" && tw.parent() instanceof AST.Call) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) { for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true; s.uses_eval = true;
} }
@ -217,7 +193,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
var sym = node.scope.find_variable(name); var sym = node.scope.find_variable(name);
if (!sym) { if (!sym) {
sym = self.def_global(node); sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") { } else if (sym.scope instanceof AST.Lambda && name == "arguments") {
sym.scope.uses_arguments = true; sym.scope.uses_arguments = true;
} }
node.thedef = sym; node.thedef = sym;
@ -226,7 +202,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} }
// ensure mangling works if catch reuses a scope variable // ensure mangling works if catch reuses a scope variable
var def; var def;
if (node instanceof AST_SymbolCatch && (def = node.definition().redefined())) { if (node instanceof AST.SymbolCatch && (def = node.definition().redefined())) {
var s = node.scope; var s = node.scope;
while (s) { while (s) {
push_uniq(s.enclosed, def); push_uniq(s.enclosed, def);
@ -240,7 +216,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
// pass 3: fix up any scoping issue with IE8 // pass 3: fix up any scoping issue with IE8
if (options.ie8) { if (options.ie8) {
self.walk(new TreeWalker(function(node, descend) { self.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_SymbolCatch) { if (node instanceof AST.SymbolCatch) {
var name = node.name; var name = node.name;
var refs = node.thedef.references; var refs = node.thedef.references;
var scope = node.thedef.defun; var scope = node.thedef.defun;
@ -257,7 +233,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
} }
}); });
AST_Toplevel.DEFMETHOD("def_global", function(node) { AST.Toplevel.DEFMETHOD("def_global", function(node) {
var globals = this.globals, name = node.name; var globals = this.globals, name = node.name;
if (globals.has(name)) { if (globals.has(name)) {
return globals.get(name); return globals.get(name);
@ -270,9 +246,9 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
} }
}); });
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) { AST.Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) this.variables = new Dictionary(); // map name to AST.SymbolVar (variables defined in this scope; includes functions)
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) this.functions = new Dictionary(); // map name to AST.SymbolDefun (functions defined in this scope)
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` this.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
this.parent_scope = parent_scope; // the parent scope this.parent_scope = parent_scope; // the parent scope
@ -280,17 +256,17 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
this.cname = -1; // the current index for mangling functions/variables this.cname = -1; // the current index for mangling functions/variables
}); });
AST_Lambda.DEFMETHOD("init_scope_vars", function() { AST.Lambda.DEFMETHOD("init_scope_vars", function() {
AST_Scope.prototype.init_scope_vars.apply(this, arguments); AST.Scope.prototype.init_scope_vars.apply(this, arguments);
this.uses_arguments = false; this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({ this.def_variable(new AST.SymbolFunarg({
name: "arguments", name: "arguments",
start: this.start, start: this.start,
end: this.end end: this.end
})); }));
}); });
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { AST.Symbol.DEFMETHOD("mark_enclosed", function(options) {
var def = this.definition(); var def = this.definition();
var s = this.scope; var s = this.scope;
while (s) { while (s) {
@ -305,29 +281,29 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
} }
}); });
AST_Symbol.DEFMETHOD("reference", function(options) { AST.Symbol.DEFMETHOD("reference", function(options) {
this.definition().references.push(this); this.definition().references.push(this);
this.mark_enclosed(options); this.mark_enclosed(options);
}); });
AST_Scope.DEFMETHOD("find_variable", function(name) { AST.Scope.DEFMETHOD("find_variable", function(name) {
if (name instanceof AST_Symbol) name = name.name; if (name instanceof AST.Symbol) name = name.name;
return this.variables.get(name) return this.variables.get(name)
|| (this.parent_scope && this.parent_scope.find_variable(name)); || (this.parent_scope && this.parent_scope.find_variable(name));
}); });
AST_Scope.DEFMETHOD("def_function", function(symbol, init) { AST.Scope.DEFMETHOD("def_function", function(symbol, init) {
var def = this.def_variable(symbol, init); var def = this.def_variable(symbol, init);
if (!def.init || def.init instanceof AST_Defun) def.init = init; if (!def.init || def.init instanceof AST.Defun) def.init = init;
this.functions.set(symbol.name, def); this.functions.set(symbol.name, def);
return def; return def;
}); });
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) { AST.Scope.DEFMETHOD("def_variable", function(symbol, init) {
var def = this.variables.get(symbol.name); var def = this.variables.get(symbol.name);
if (def) { if (def) {
def.orig.push(symbol); def.orig.push(symbol);
if (def.init && (def.scope !== symbol.scope || def.init instanceof AST_Function)) { if (def.init && (def.scope !== symbol.scope || def.init instanceof AST.Function)) {
def.init = init; def.init = init;
} }
} else { } else {
@ -357,7 +333,7 @@ function next_mangled_name(scope, options, def) {
// #179, #326 // #179, #326
// in Safari strict mode, something like (function x(x){...}) is a syntax error; // in Safari strict mode, something like (function x(x){...}) is a syntax error;
// a function expression's argument cannot shadow the function expression's name // a function expression's argument cannot shadow the function expression's name
if (scope instanceof AST_Function && scope.name && def.orig[0] instanceof AST_SymbolFunarg) { if (scope instanceof AST.Function && scope.name && def.orig[0] instanceof AST.SymbolFunarg) {
var tricky_def = scope.name.definition(); var tricky_def = scope.name.definition();
// the function's mangled_name is null when keep_fnames is true // the function's mangled_name is null when keep_fnames is true
names[tricky_def.mangled_name || tricky_def.name] = true; names[tricky_def.mangled_name || tricky_def.name] = true;
@ -389,29 +365,29 @@ function next_mangled_name(scope, options, def) {
holes.push(scope.cname); holes.push(scope.cname);
} }
scope.names_in_use[name] = true; scope.names_in_use[name] = true;
if (options.ie8 && def.orig[0] instanceof AST_SymbolLambda) { if (options.ie8 && def.orig[0] instanceof AST.SymbolLambda) {
names_in_use(scope.parent_scope, options)[name] = true; names_in_use(scope.parent_scope, options)[name] = true;
} }
return name; return name;
} }
AST_Symbol.DEFMETHOD("unmangleable", function(options) { AST.Symbol.DEFMETHOD("unmangleable", function(options) {
var def = this.definition(); var def = this.definition();
return !def || def.unmangleable(options); return !def || def.unmangleable(options);
}); });
// labels are always mangleable // labels are always mangleable
AST_Label.DEFMETHOD("unmangleable", return_false); AST.Label.DEFMETHOD("unmangleable", return_false);
AST_Symbol.DEFMETHOD("unreferenced", function() { AST.Symbol.DEFMETHOD("unreferenced", function() {
return !this.definition().references.length && !this.scope.pinned(); return !this.definition().references.length && !this.scope.pinned();
}); });
AST_Symbol.DEFMETHOD("definition", function() { AST.Symbol.DEFMETHOD("definition", function() {
return this.thedef; return this.thedef;
}); });
AST_Symbol.DEFMETHOD("global", function() { AST.Symbol.DEFMETHOD("global", function() {
return this.definition().global; return this.definition().global;
}); });
@ -430,13 +406,13 @@ function _default_mangler_options(options) {
return options; return options;
} }
AST_Toplevel.DEFMETHOD("mangle_names", function(options) { AST.Toplevel.DEFMETHOD("mangle_names", function(options) {
options = _default_mangler_options(options); options = _default_mangler_options(options);
// We only need to mangle declaration nodes. Special logic wired // We only need to mangle declaration nodes. Special logic wired
// into the code generator will display the mangled name if it's // into the code generator will display the mangled name if it's
// present (and for AST_SymbolRef-s it'll use the mangled name of // present (and for AST.SymbolRef-s it'll use the mangled name of
// the AST_SymbolDeclaration that it points to). // the AST.SymbolDeclaration that it points to).
var lname = -1; var lname = -1;
if (options.cache && options.cache.props) { if (options.cache && options.cache.props) {
@ -448,28 +424,28 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
var redefined = []; var redefined = [];
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_LabeledStatement) { if (node instanceof AST.LabeledStatement) {
// lname is incremented when we get to the AST_Label // lname is incremented when we get to the AST.Label
var save_nesting = lname; var save_nesting = lname;
descend(); descend();
lname = save_nesting; lname = save_nesting;
return true; // don't descend again in TreeWalker return true; // don't descend again in TreeWalker
} }
if (node instanceof AST_Scope) { if (node instanceof AST.Scope) {
descend(); descend();
if (options.cache && node instanceof AST_Toplevel) { if (options.cache && node instanceof AST.Toplevel) {
node.globals.each(mangle); node.globals.each(mangle);
} }
node.variables.each(mangle); node.variables.each(mangle);
return true; return true;
} }
if (node instanceof AST_Label) { if (node instanceof AST.Label) {
var name; var name;
do name = base54(++lname); while (!is_identifier(name)); do name = base54(++lname); while (!is_identifier(name));
node.mangled_name = name; node.mangled_name = name;
return true; return true;
} }
if (!options.ie8 && node instanceof AST_Catch) { if (!options.ie8 && node instanceof AST.Catch) {
var def = node.argname.definition(); var def = node.argname.definition();
var redef = def.redefined(); var redef = def.redefined();
if (redef) { if (redef) {
@ -497,14 +473,14 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
} }
}); });
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) { AST.Toplevel.DEFMETHOD("find_colliding_names", function(options) {
var cache = options.cache && options.cache.props; var cache = options.cache && options.cache.props;
var avoid = Object.create(null); var avoid = Object.create(null);
options.reserved.forEach(to_avoid); options.reserved.forEach(to_avoid);
this.globals.each(add_def); this.globals.each(add_def);
this.walk(new TreeWalker(function(node) { this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(add_def); if (node instanceof AST.Scope) node.variables.each(add_def);
if (node instanceof AST_SymbolCatch) add_def(node.definition()); if (node instanceof AST.SymbolCatch) add_def(node.definition());
})); }));
return avoid; return avoid;
@ -520,7 +496,7 @@ AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
} }
}); });
AST_Toplevel.DEFMETHOD("expand_names", function(options) { AST.Toplevel.DEFMETHOD("expand_names", function(options) {
base54.reset(); base54.reset();
base54.sort(); base54.sort();
options = _default_mangler_options(options); options = _default_mangler_options(options);
@ -528,8 +504,8 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
var cname = 0; var cname = 0;
this.globals.each(rename); this.globals.each(rename);
this.walk(new TreeWalker(function(node) { this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(rename); if (node instanceof AST.Scope) node.variables.each(rename);
if (node instanceof AST_SymbolCatch) rename(node.definition()); if (node instanceof AST.SymbolCatch) rename(node.definition());
})); }));
function next_name() { function next_name() {
@ -555,40 +531,40 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) {
} }
}); });
AST_Node.DEFMETHOD("tail_node", return_this); AST.Node.DEFMETHOD("tail_node", return_this);
AST_Sequence.DEFMETHOD("tail_node", function() { AST.Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1]; return this.expressions[this.expressions.length - 1];
}); });
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) { AST.Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
options = _default_mangler_options(options); options = _default_mangler_options(options);
base54.reset(); base54.reset();
try { try {
AST_Node.prototype.print = function(stream, force_parens) { AST.Node.prototype.print = function(stream, force_parens) {
this._print(stream, force_parens); this._print(stream, force_parens);
if (this instanceof AST_Symbol && !this.unmangleable(options)) { if (this instanceof AST.Symbol && !this.unmangleable(options)) {
base54.consider(this.name, -1); base54.consider(this.name, -1);
} else if (options.properties) { } else if (options.properties) {
if (this instanceof AST_Dot) { if (this instanceof AST.Dot) {
base54.consider(this.property, -1); base54.consider(this.property, -1);
} else if (this instanceof AST_Sub) { } else if (this instanceof AST.Sub) {
skip_string(this.property); skip_string(this.property);
} }
} }
}; };
base54.consider(this.print_to_string(), 1); base54.consider(this.print_to_string(), 1);
} finally { } finally {
AST_Node.prototype.print = AST_Node.prototype._print; AST.Node.prototype.print = AST.Node.prototype._print;
} }
base54.sort(); base54.sort();
function skip_string(node) { function skip_string(node) {
if (node instanceof AST_String) { if (node instanceof AST.String) {
base54.consider(node.value, -1); base54.consider(node.value, -1);
} else if (node instanceof AST_Conditional) { } else if (node instanceof AST.Conditional) {
skip_string(node.consequent); skip_string(node.consequent);
skip_string(node.alternative); skip_string(node.alternative);
} else if (node instanceof AST_Sequence) { } else if (node instanceof AST.Sequence) {
skip_string(node.tail_node()); skip_string(node.tail_node());
} }
} }

View File

@ -594,7 +594,7 @@ describe("bin/uglifyjs", function() {
exec(command, function(err, stdout) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
var ast = JSON.parse(stdout); var ast = JSON.parse(stdout);
assert.strictEqual(ast._class, "AST_Toplevel"); assert.strictEqual(ast._class, "AST.Toplevel");
assert.ok(Array.isArray(ast.body)); assert.ok(Array.isArray(ast.body));
done(); done();
}); });

View File

@ -10,7 +10,7 @@ describe("spidermonkey export/import sanity test", function() {
var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " + var command = uglifyjs + " --self -cm --wrap SpiderUglify -o spidermonkey | " +
uglifyjs + " -p spidermonkey -cm"; uglifyjs + " -p spidermonkey -cm";
exec(command, function(err, stdout) { exec(command, {maxBuffer: 1024 * 300}, function(err, stdout) {
if (err) throw err; if (err) throw err;
eval(stdout); eval(stdout);

View File

@ -1,6 +1,4 @@
var orig = require("../tools/node"); var orig = require("../tools/node");
// Get all AST-nodes
orig.utils.merge(orig, orig.ast);
orig.SourceMap = require("../lib/sourcemap").SourceMap; orig.SourceMap = require("../lib/sourcemap").SourceMap;
orig.base54 = orig.utils.base54; orig.base54 = orig.utils.base54;
orig.defaults = orig.utils.defaults; orig.defaults = orig.utils.defaults;

View File

@ -38,9 +38,11 @@ UglifyJS.FILES.forEach(function(filepath){
if (exportNames.length == 0) if (exportNames.length == 0)
return; return;
// Use (utils.)merge instead of Object.assign for (very) old node // Use (utils.)merge instead of Object.assign for (very) old node
var exports = "merge(exports, {\n" + exportNames.map(function(name){ var exports = "merge(exports, {\n" + exportNames.map(
return UglifyJS.string_template(' {name} : {name},', { name: name }); name => UglifyJS.string_template(' {name} : {name},', { name: name })
}).join("\n") + "\n});"; ).concat(exportNames.filter(name => name.indexOf("AST_") == 0).map(
name => UglifyJS.string_template(' {expName} : {name},', { expName: name.substr(4), name: name })
)).join("\n") + "\n});";
var imports = exportNames.map(function(name){ var imports = exportNames.map(function(name){
return UglifyJS.string_template(UglifyJS.string_template('var {name} = {fn}.{name};', { name: name, fn: filename})); return UglifyJS.string_template(UglifyJS.string_template('var {name} = {fn}.{name};', { name: name, fn: filename}));
}); });

View File

@ -17,22 +17,11 @@ var FILES = UglifyJS.FILES = [
return require.resolve(file); return require.resolve(file);
}); });
/*new Function("MOZ_SourceMap", "exports", function() {
var code = FILES.map(function(file) {
return fs.readFileSync(file, "utf8");
});
code.push("exports.describe_ast = " + describe_ast.toString());
return code.join("\n\n");
}())(
require("source-map"),
UglifyJS
);*/
var utils = require("../lib/utils"); var utils = require("../lib/utils");
var output = require("../lib/output"); var output = require("../lib/output");
var OutputStream = output.OutputStream; var OutputStream = output.OutputStream;
var minify = require("../lib/minify").minify; var minify = require("../lib/minify").minify;
var ast = require("../lib/ast"); var AST = require("../lib/ast");
var compress = require("../lib/compress"); var compress = require("../lib/compress");
var parse = require("../lib/parse"); var parse = require("../lib/parse");
var propmangle = require("../lib/propmangle"); var propmangle = require("../lib/propmangle");
@ -42,22 +31,28 @@ require("../lib/mozilla-ast");
exports.utils = utils; exports.utils = utils;
exports.OutputStream = OutputStream; exports.OutputStream = OutputStream;
exports.minify = minify; exports.minify = minify;
exports.ast = ast; exports.AST = AST;
exports.parser = parse; exports.parser = parse;
exports.parse = parse.parse; exports.parse = parse.parse;
exports.Compressor = compress.Compressor; exports.Compressor = compress.Compressor;
exports.Dictionary = utils.Dictionary; exports.Dictionary = utils.Dictionary;
exports.TreeWalker = ast.TreeWalker; exports.TreeWalker = AST.TreeWalker;
exports.TreeTransformer = ast.TreeTransformer; exports.TreeTransformer = AST.TreeTransformer;
exports.push_uniq = utils.push_uniq; exports.push_uniq = utils.push_uniq;
exports.string_template = utils.string_template; exports.string_template = utils.string_template;
exports.describe_ast = describe_ast; exports.describe_ast = describe_ast;
exports.propmangle = propmangle; exports.propmangle = propmangle;
// Backwards compatibility: Add all AST_
for (var name in AST) if (utils.HOP(AST, name)) {
if (name.indexOf("AST_") == 0)
exports[name] = AST[name];
}
function describe_ast() { function describe_ast() {
var out = OutputStream({ beautify: true }); var out = OutputStream({ beautify: true });
function doitem(ctor) { function doitem(ctor) {
out.print("AST_" + ctor.TYPE); out.print("AST." + ctor.TYPE);
var props = ctor.SELF_PROPS.filter(function(prop) { var props = ctor.SELF_PROPS.filter(function(prop) {
return !/^\$/.test(prop); return !/^\$/.test(prop);
}); });
@ -85,7 +80,7 @@ function describe_ast() {
}); });
} }
}; };
doitem(AST_Node); doitem(AST.Node);
return out + "\n"; return out + "\n";
} }