Merge 13196026eb into 9e19e63551
This commit is contained in:
commit
364af7fa0f
|
|
@ -1047,7 +1047,7 @@ var result = UglifyJS.minify(ast, {
|
||||||
|
|
||||||
Transversal and transformation of the native AST can be performed through
|
Transversal and transformation of the native AST can be performed through
|
||||||
[`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
|
[`TreeWalker`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js) and
|
||||||
[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/transform.js)
|
[`TreeTransformer`](https://github.com/mishoo/UglifyJS2/blob/master/lib/ast.js)
|
||||||
respectively.
|
respectively.
|
||||||
|
|
||||||
### ESTree / SpiderMonkey AST
|
### ESTree / SpiderMonkey AST
|
||||||
|
|
|
||||||
34
bin/uglifyjs
34
bin/uglifyjs
|
|
@ -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 = {};
|
||||||
|
|
@ -100,7 +101,7 @@ if (program.mangleProps) {
|
||||||
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
if (typeof program.mangleProps != "object") program.mangleProps = {};
|
||||||
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
|
||||||
require("../tools/domprops").forEach(function(name) {
|
require("../tools/domprops").forEach(function(name) {
|
||||||
UglifyJS._push_uniq(program.mangleProps.reserved, name);
|
UglifyJS.push_uniq(program.mangleProps.reserved, name);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (typeof options.mangle != "object") options.mangle = {};
|
if (typeof options.mangle != "object") options.mangle = {};
|
||||||
|
|
@ -144,12 +145,23 @@ if (program.verbose) {
|
||||||
} else if (program.warn) {
|
} else if (program.warn) {
|
||||||
options.warnings = true;
|
options.warnings = true;
|
||||||
}
|
}
|
||||||
|
function getVarNameFromPath(filename) {
|
||||||
|
var name = /((\w|-)+)(\.js)?$/.exec(filename)[1].replace("-", "_");
|
||||||
|
return "__" + name + "_exports";
|
||||||
|
}
|
||||||
if (program.self) {
|
if (program.self) {
|
||||||
if (program.args.length) {
|
if (program.args.length) {
|
||||||
print_error("WARN: Ignoring input files since --self was passed");
|
print_error("WARN: Ignoring input files since --self was passed");
|
||||||
}
|
}
|
||||||
if (!options.wrap) options.wrap = "UglifyJS";
|
if (!options.wrap) options.wrap = "UglifyJS";
|
||||||
|
files["__require_emulation"] = "var __origExports = exports;" + getVarNameFromPath + "function require(filename){return require[getVarNameFromPath(filename)];}";
|
||||||
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
simple_glob(UglifyJS.FILES).forEach(function(name) {
|
||||||
|
var exportCode;
|
||||||
|
if (/exports\.js$/.test(name))
|
||||||
|
exportCode = "var exports = __origExports";
|
||||||
|
else
|
||||||
|
exportCode = "var exports = require['" + getVarNameFromPath(name) + "'] = {};";
|
||||||
|
files["_" + name + "_exports"] = exportCode;
|
||||||
files[convert_path(name)] = read_file(name);
|
files[convert_path(name)] = read_file(name);
|
||||||
});
|
});
|
||||||
run();
|
run();
|
||||||
|
|
@ -171,11 +183,11 @@ if (program.self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function convert_ast(fn) {
|
function convert_ast(fn) {
|
||||||
return UglifyJS.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_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;
|
||||||
|
|
@ -249,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_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_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];
|
||||||
|
|
@ -348,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_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_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_Symbol || node instanceof UglifyJS.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_Sequence)) throw node;
|
if (!(node instanceof AST.Sequence)) throw node;
|
||||||
|
|
||||||
function to_string(value) {
|
function to_string(value) {
|
||||||
return value instanceof UglifyJS.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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
383
lib/ast.js
383
lib/ast.js
|
|
@ -43,6 +43,13 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var utils = require("./utils");
|
||||||
|
var noop = utils.noop;
|
||||||
|
var string_template = utils.string_template;
|
||||||
|
var HOP = utils.HOP;
|
||||||
|
var MAP = utils.MAP;
|
||||||
|
var merge = utils.merge;
|
||||||
|
|
||||||
function DEFNODE(type, props, methods, base) {
|
function DEFNODE(type, props, methods, base) {
|
||||||
if (typeof base === "undefined") base = AST_Node;
|
if (typeof base === "undefined") base = AST_Node;
|
||||||
props = props ? props.split(/\s+/) : [];
|
props = props ? props.split(/\s+/) : [];
|
||||||
|
|
@ -323,34 +330,6 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
|
||||||
$documentation: "The toplevel scope",
|
$documentation: "The toplevel scope",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
globals: "[Object/S] a map of name -> SymbolDef for all undeclared names",
|
||||||
},
|
|
||||||
wrap_commonjs: function(name) {
|
|
||||||
var body = this.body;
|
|
||||||
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
|
|
||||||
wrapped_tl = parse(wrapped_tl);
|
|
||||||
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
|
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
|
||||||
return MAP.splice(body);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
return wrapped_tl;
|
|
||||||
},
|
|
||||||
wrap_enclose: function(args_values) {
|
|
||||||
if (typeof args_values != "string") args_values = "";
|
|
||||||
var index = args_values.indexOf(":");
|
|
||||||
if (index < 0) index = args_values.length;
|
|
||||||
var body = this.body;
|
|
||||||
return parse([
|
|
||||||
"(function(",
|
|
||||||
args_values.slice(0, index),
|
|
||||||
'){"$ORIG"})(',
|
|
||||||
args_values.slice(index + 1),
|
|
||||||
")"
|
|
||||||
].join("")).transform(new TreeTransformer(function(node) {
|
|
||||||
if (node instanceof AST_Directive && node.value == "$ORIG") {
|
|
||||||
return MAP.splice(body);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}, AST_Scope);
|
}, AST_Scope);
|
||||||
|
|
||||||
|
|
@ -952,3 +931,351 @@ TreeWalker.prototype = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function TreeTransformer(before, after) {
|
||||||
|
TreeWalker.call(this);
|
||||||
|
this.before = before;
|
||||||
|
this.after = after;
|
||||||
|
}
|
||||||
|
TreeTransformer.prototype = new TreeWalker;
|
||||||
|
|
||||||
|
(function(DEF) {
|
||||||
|
function do_list(list, tw) {
|
||||||
|
return MAP(list, function(node) {
|
||||||
|
return node.transform(tw, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF(AST_Node, noop);
|
||||||
|
DEF(AST_LabeledStatement, function(self, tw) {
|
||||||
|
self.label = self.label.transform(tw);
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_SimpleStatement, function(self, tw) {
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Block, function(self, tw) {
|
||||||
|
self.body = do_list(self.body, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Do, function(self, tw) {
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
self.condition = self.condition.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_While, function(self, tw) {
|
||||||
|
self.condition = self.condition.transform(tw);
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_For, function(self, tw) {
|
||||||
|
if (self.init) self.init = self.init.transform(tw);
|
||||||
|
if (self.condition) self.condition = self.condition.transform(tw);
|
||||||
|
if (self.step) self.step = self.step.transform(tw);
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_ForIn, function(self, tw) {
|
||||||
|
self.init = self.init.transform(tw);
|
||||||
|
self.object = self.object.transform(tw);
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_With, function(self, tw) {
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Exit, function(self, tw) {
|
||||||
|
if (self.value) self.value = self.value.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_LoopControl, function(self, tw) {
|
||||||
|
if (self.label) self.label = self.label.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_If, function(self, tw) {
|
||||||
|
self.condition = self.condition.transform(tw);
|
||||||
|
self.body = self.body.transform(tw);
|
||||||
|
if (self.alternative) self.alternative = self.alternative.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Switch, function(self, tw) {
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
self.body = do_list(self.body, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Case, function(self, tw) {
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
self.body = do_list(self.body, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Try, function(self, tw) {
|
||||||
|
self.body = do_list(self.body, tw);
|
||||||
|
if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
|
||||||
|
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Catch, function(self, tw) {
|
||||||
|
self.argname = self.argname.transform(tw);
|
||||||
|
self.body = do_list(self.body, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Definitions, function(self, tw) {
|
||||||
|
self.definitions = do_list(self.definitions, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_VarDef, function(self, tw) {
|
||||||
|
self.name = self.name.transform(tw);
|
||||||
|
if (self.value) self.value = self.value.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Lambda, function(self, tw) {
|
||||||
|
if (self.name) self.name = self.name.transform(tw);
|
||||||
|
self.argnames = do_list(self.argnames, tw);
|
||||||
|
self.body = do_list(self.body, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Call, function(self, tw) {
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
self.args = do_list(self.args, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Sequence, function(self, tw) {
|
||||||
|
self.expressions = do_list(self.expressions, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Dot, function(self, tw) {
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Sub, function(self, tw) {
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
self.property = self.property.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Unary, function(self, tw) {
|
||||||
|
self.expression = self.expression.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Binary, function(self, tw) {
|
||||||
|
self.left = self.left.transform(tw);
|
||||||
|
self.right = self.right.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Conditional, function(self, tw) {
|
||||||
|
self.condition = self.condition.transform(tw);
|
||||||
|
self.consequent = self.consequent.transform(tw);
|
||||||
|
self.alternative = self.alternative.transform(tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Array, function(self, tw) {
|
||||||
|
self.elements = do_list(self.elements, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_Object, function(self, tw) {
|
||||||
|
self.properties = do_list(self.properties, tw);
|
||||||
|
});
|
||||||
|
DEF(AST_ObjectProperty, function(self, tw) {
|
||||||
|
self.value = self.value.transform(tw);
|
||||||
|
});
|
||||||
|
})(function(node, descend) {
|
||||||
|
node.DEFMETHOD("transform", function(tw, in_list) {
|
||||||
|
var x, y;
|
||||||
|
tw.push(this);
|
||||||
|
if (tw.before) x = tw.before(this, descend, in_list);
|
||||||
|
if (typeof x === "undefined") {
|
||||||
|
x = this;
|
||||||
|
descend(x, tw);
|
||||||
|
if (tw.after) {
|
||||||
|
y = tw.after(x, in_list);
|
||||||
|
if (typeof y !== "undefined") x = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tw.pop();
|
||||||
|
return x;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
/* Helpers
|
||||||
|
/**********************************************************************/
|
||||||
|
|
||||||
|
// return true if the node at the top of the stack (that means the
|
||||||
|
// innermost node in the current output) is lexically the first in
|
||||||
|
// a statement.
|
||||||
|
function first_in_statement(stack) {
|
||||||
|
var node = stack.parent(-1);
|
||||||
|
for (var i = 0, p; p = stack.parent(i++); node = p) {
|
||||||
|
if (p.TYPE == "Call") {
|
||||||
|
if (p.expression === node) continue;
|
||||||
|
} else if (p instanceof AST_Binary) {
|
||||||
|
if (p.left === node) continue;
|
||||||
|
} else if (p instanceof AST_Conditional) {
|
||||||
|
if (p.condition === node) continue;
|
||||||
|
} else if (p instanceof AST_PropAccess) {
|
||||||
|
if (p.expression === node) continue;
|
||||||
|
} else if (p instanceof AST_Sequence) {
|
||||||
|
if (p.expressions[0] === node) continue;
|
||||||
|
} else if (p instanceof AST_Statement) {
|
||||||
|
return p.body === node;
|
||||||
|
} else if (p instanceof AST_UnaryPostfix) {
|
||||||
|
if (p.expression === node) continue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
merge(exports, {
|
||||||
|
DEFNODE : DEFNODE,
|
||||||
|
AST_Token : AST_Token,
|
||||||
|
AST_Node : AST_Node,
|
||||||
|
AST_Statement : AST_Statement,
|
||||||
|
AST_Debugger : AST_Debugger,
|
||||||
|
AST_Directive : AST_Directive,
|
||||||
|
AST_SimpleStatement : AST_SimpleStatement,
|
||||||
|
walk_body : walk_body,
|
||||||
|
AST_Block : AST_Block,
|
||||||
|
AST_BlockStatement : AST_BlockStatement,
|
||||||
|
AST_EmptyStatement : AST_EmptyStatement,
|
||||||
|
AST_StatementWithBody : AST_StatementWithBody,
|
||||||
|
AST_LabeledStatement : AST_LabeledStatement,
|
||||||
|
AST_IterationStatement : AST_IterationStatement,
|
||||||
|
AST_DWLoop : AST_DWLoop,
|
||||||
|
AST_Do : AST_Do,
|
||||||
|
AST_While : AST_While,
|
||||||
|
AST_For : AST_For,
|
||||||
|
AST_ForIn : AST_ForIn,
|
||||||
|
AST_With : AST_With,
|
||||||
|
AST_Scope : AST_Scope,
|
||||||
|
AST_Toplevel : AST_Toplevel,
|
||||||
|
AST_Lambda : AST_Lambda,
|
||||||
|
AST_Accessor : AST_Accessor,
|
||||||
|
AST_Function : AST_Function,
|
||||||
|
AST_Defun : AST_Defun,
|
||||||
|
AST_Jump : AST_Jump,
|
||||||
|
AST_Exit : AST_Exit,
|
||||||
|
AST_Return : AST_Return,
|
||||||
|
AST_Throw : AST_Throw,
|
||||||
|
AST_LoopControl : AST_LoopControl,
|
||||||
|
AST_Break : AST_Break,
|
||||||
|
AST_Continue : AST_Continue,
|
||||||
|
AST_If : AST_If,
|
||||||
|
AST_Switch : AST_Switch,
|
||||||
|
AST_SwitchBranch : AST_SwitchBranch,
|
||||||
|
AST_Default : AST_Default,
|
||||||
|
AST_Case : AST_Case,
|
||||||
|
AST_Try : AST_Try,
|
||||||
|
AST_Catch : AST_Catch,
|
||||||
|
AST_Finally : AST_Finally,
|
||||||
|
AST_Definitions : AST_Definitions,
|
||||||
|
AST_Var : AST_Var,
|
||||||
|
AST_VarDef : AST_VarDef,
|
||||||
|
AST_Call : AST_Call,
|
||||||
|
AST_New : AST_New,
|
||||||
|
AST_Sequence : AST_Sequence,
|
||||||
|
AST_PropAccess : AST_PropAccess,
|
||||||
|
AST_Dot : AST_Dot,
|
||||||
|
AST_Sub : AST_Sub,
|
||||||
|
AST_Unary : AST_Unary,
|
||||||
|
AST_UnaryPrefix : AST_UnaryPrefix,
|
||||||
|
AST_UnaryPostfix : AST_UnaryPostfix,
|
||||||
|
AST_Binary : AST_Binary,
|
||||||
|
AST_Conditional : AST_Conditional,
|
||||||
|
AST_Assign : AST_Assign,
|
||||||
|
AST_Array : AST_Array,
|
||||||
|
AST_Object : AST_Object,
|
||||||
|
AST_ObjectProperty : AST_ObjectProperty,
|
||||||
|
AST_ObjectKeyVal : AST_ObjectKeyVal,
|
||||||
|
AST_ObjectSetter : AST_ObjectSetter,
|
||||||
|
AST_ObjectGetter : AST_ObjectGetter,
|
||||||
|
AST_Symbol : AST_Symbol,
|
||||||
|
AST_SymbolAccessor : AST_SymbolAccessor,
|
||||||
|
AST_SymbolDeclaration : AST_SymbolDeclaration,
|
||||||
|
AST_SymbolVar : AST_SymbolVar,
|
||||||
|
AST_SymbolFunarg : AST_SymbolFunarg,
|
||||||
|
AST_SymbolDefun : AST_SymbolDefun,
|
||||||
|
AST_SymbolLambda : AST_SymbolLambda,
|
||||||
|
AST_SymbolCatch : AST_SymbolCatch,
|
||||||
|
AST_Label : AST_Label,
|
||||||
|
AST_SymbolRef : AST_SymbolRef,
|
||||||
|
AST_LabelRef : AST_LabelRef,
|
||||||
|
AST_This : AST_This,
|
||||||
|
AST_Constant : AST_Constant,
|
||||||
|
AST_String : AST_String,
|
||||||
|
AST_Number : AST_Number,
|
||||||
|
AST_RegExp : AST_RegExp,
|
||||||
|
AST_Atom : AST_Atom,
|
||||||
|
AST_Null : AST_Null,
|
||||||
|
AST_NaN : AST_NaN,
|
||||||
|
AST_Undefined : AST_Undefined,
|
||||||
|
AST_Hole : AST_Hole,
|
||||||
|
AST_Infinity : AST_Infinity,
|
||||||
|
AST_Boolean : AST_Boolean,
|
||||||
|
AST_False : AST_False,
|
||||||
|
AST_True : AST_True,
|
||||||
|
TreeWalker : TreeWalker,
|
||||||
|
TreeTransformer : TreeTransformer,
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
|
|
||||||
2141
lib/compress.js
2141
lib/compress.js
File diff suppressed because it is too large
Load Diff
|
|
@ -1,5 +1,27 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var utils = require("./utils");
|
||||||
|
var defaults = utils.defaults;
|
||||||
|
var Dictionary = utils.Dictionary;
|
||||||
|
var HOP = utils.HOP;
|
||||||
|
var MAP = utils.MAP;
|
||||||
|
var merge = utils.merge;
|
||||||
|
|
||||||
|
var AST = require("./ast");
|
||||||
|
var TreeTransformer = AST.TreeTransformer;
|
||||||
|
|
||||||
|
var parse = require("./parse");
|
||||||
|
var parse = parse.parse;
|
||||||
|
|
||||||
|
var OutputStream = require("./output").OutputStream;
|
||||||
|
var Compressor = require("./compress").Compressor;
|
||||||
|
|
||||||
|
var SourceMap = require("./sourcemap").SourceMap;
|
||||||
|
|
||||||
|
var propmangle = require("./propmangle");
|
||||||
|
var reserve_quoted_keys = propmangle.reserve_quoted_keys;
|
||||||
|
var mangle_properties = propmangle.mangle_properties;
|
||||||
|
|
||||||
var to_ascii = typeof atob == "undefined" ? function(b64) {
|
var to_ascii = typeof atob == "undefined" ? function(b64) {
|
||||||
return new Buffer(b64, "base64").toString();
|
return new Buffer(b64, "base64").toString();
|
||||||
} : atob;
|
} : atob;
|
||||||
|
|
@ -10,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]);
|
||||||
|
|
@ -51,7 +73,36 @@ function to_json(cache) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function minify(files, options) {
|
function minify(files, options) {
|
||||||
var warn_function = AST_Node.warn_function;
|
function wrap_commonjs(toplevel_node, name) {
|
||||||
|
var body = toplevel_node.body;
|
||||||
|
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
|
||||||
|
wrapped_tl = parse(wrapped_tl);
|
||||||
|
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
|
||||||
|
if (node instanceof AST.Directive && node.value == "$ORIG") {
|
||||||
|
return MAP.splice(body);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return wrapped_tl;
|
||||||
|
}
|
||||||
|
function wrap_enclose(toplevel_node, args_values) {
|
||||||
|
if (typeof args_values != "string") args_values = "";
|
||||||
|
var index = args_values.indexOf(":");
|
||||||
|
if (index < 0) index = args_values.length;
|
||||||
|
var body = toplevel_node.body;
|
||||||
|
return parse([
|
||||||
|
"(function(",
|
||||||
|
args_values.slice(0, index),
|
||||||
|
'){"$ORIG"})(',
|
||||||
|
args_values.slice(index + 1),
|
||||||
|
")"
|
||||||
|
].join("")).transform(new TreeTransformer(function(node) {
|
||||||
|
if (node instanceof AST.Directive && node.value == "$ORIG") {
|
||||||
|
return MAP.splice(body);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
var warn_function = AST.Node.warn_function;
|
||||||
try {
|
try {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
compress: {},
|
compress: {},
|
||||||
|
|
@ -116,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") {
|
||||||
|
|
@ -156,10 +207,10 @@ function minify(files, options) {
|
||||||
reserve_quoted_keys(toplevel, quoted_props);
|
reserve_quoted_keys(toplevel, quoted_props);
|
||||||
}
|
}
|
||||||
if (options.wrap) {
|
if (options.wrap) {
|
||||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
toplevel = wrap_commonjs(toplevel, options.wrap);
|
||||||
}
|
}
|
||||||
if (options.enclose) {
|
if (options.enclose) {
|
||||||
toplevel = toplevel.wrap_enclose(options.enclose);
|
toplevel = wrap_enclose(toplevel, options.enclose);
|
||||||
}
|
}
|
||||||
if (timings) timings.rename = Date.now();
|
if (timings) timings.rename = Date.now();
|
||||||
if (options.rename) {
|
if (options.rename) {
|
||||||
|
|
@ -192,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]);
|
||||||
|
|
@ -241,6 +292,17 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
merge(exports, {
|
||||||
|
to_ascii : to_ascii,
|
||||||
|
to_base64 : to_base64,
|
||||||
|
read_source_map : read_source_map,
|
||||||
|
parse_source_map : parse_source_map,
|
||||||
|
set_shorthand : set_shorthand,
|
||||||
|
init_cache : init_cache,
|
||||||
|
to_json : to_json,
|
||||||
|
minify : minify,
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -43,17 +43,20 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var AST = require("./ast");
|
||||||
|
var TreeWalker = AST.TreeWalker;
|
||||||
|
|
||||||
(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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,14 +65,14 @@
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -78,7 +81,7 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
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),
|
||||||
|
|
@ -87,7 +90,7 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
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)
|
||||||
|
|
@ -98,12 +101,12 @@
|
||||||
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) {
|
||||||
|
|
@ -114,25 +117,25 @@
|
||||||
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) {
|
||||||
|
|
@ -142,14 +145,14 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
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,
|
||||||
|
|
@ -157,7 +160,7 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
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),
|
||||||
|
|
@ -165,7 +168,7 @@
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
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)
|
||||||
|
|
@ -176,38 +179,38 @@
|
||||||
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
|
||||||
|
|
@ -219,7 +222,7 @@
|
||||||
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,
|
||||||
|
|
@ -227,37 +230,37 @@
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -266,7 +269,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -275,7 +278,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
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: {
|
||||||
|
|
@ -285,14 +288,14 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -300,7 +303,7 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -310,7 +313,7 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -319,7 +322,7 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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",
|
||||||
|
|
@ -327,15 +330,15 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -344,16 +347,16 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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),
|
||||||
|
|
@ -362,33 +365,33 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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 {
|
||||||
|
|
@ -399,7 +402,7 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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",
|
||||||
|
|
@ -407,7 +410,7 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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 {
|
||||||
|
|
@ -421,7 +424,7 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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 {
|
||||||
|
|
@ -442,19 +445,19 @@
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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 ]----- */
|
||||||
|
|
||||||
|
|
@ -467,7 +470,7 @@
|
||||||
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,
|
||||||
|
|
@ -482,7 +485,7 @@
|
||||||
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,
|
||||||
|
|
@ -540,7 +543,7 @@
|
||||||
//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 + ")")(
|
||||||
exports, 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
|
||||||
|
|
@ -558,16 +561,16 @@
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
@ -618,8 +621,8 @@
|
||||||
|
|
||||||
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,
|
||||||
|
|
|
||||||
354
lib/output.js
354
lib/output.js
|
|
@ -43,6 +43,28 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var utils = require("./utils");
|
||||||
|
var repeat_string = utils.repeat_string;
|
||||||
|
var defaults = utils.defaults;
|
||||||
|
var noop = utils.noop;
|
||||||
|
var return_false = utils.return_false;
|
||||||
|
var return_true = utils.return_true;
|
||||||
|
var makePredicate = utils.makePredicate;
|
||||||
|
var all = utils.all;
|
||||||
|
var merge = utils.merge;
|
||||||
|
|
||||||
|
var AST = require("./ast");
|
||||||
|
var first_in_statement = AST.first_in_statement;
|
||||||
|
var TreeWalker = AST.TreeWalker;
|
||||||
|
|
||||||
|
var parse = require("./parse");
|
||||||
|
var is_surrogate_pair_head = parse.is_surrogate_pair_head;
|
||||||
|
var is_surrogate_pair_tail = parse.is_surrogate_pair_tail;
|
||||||
|
var is_identifier_char = parse.is_identifier_char;
|
||||||
|
var is_identifier_string = parse.is_identifier_string;
|
||||||
|
var PRECEDENCE = parse.PRECEDENCE;
|
||||||
|
var RESERVED_WORDS = parse.RESERVED_WORDS;
|
||||||
|
|
||||||
var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
|
var EXPECT_DIRECTIVE = /^$|[;{][\s\n]*$/;
|
||||||
|
|
||||||
function is_some_comments(comment) {
|
function is_some_comments(comment) {
|
||||||
|
|
@ -217,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,
|
||||||
|
|
@ -248,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) {
|
||||||
|
|
@ -477,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;
|
||||||
|
|
@ -550,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;
|
||||||
|
|
@ -643,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() {
|
||||||
|
|
@ -668,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();
|
||||||
|
|
@ -688,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;
|
||||||
|
|
@ -714,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
|
||||||
|
|
@ -761,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
|
||||||
|
|
@ -772,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;
|
||||||
}
|
}
|
||||||
|
|
@ -782,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;
|
||||||
|
|
@ -814,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();
|
||||||
});
|
});
|
||||||
|
|
@ -850,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)) {
|
||||||
|
|
@ -865,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;
|
||||||
}
|
}
|
||||||
|
|
@ -874,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();
|
||||||
});
|
});
|
||||||
|
|
@ -909,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);
|
||||||
|
|
@ -927,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() {
|
||||||
|
|
@ -936,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);
|
||||||
|
|
@ -965,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() {
|
||||||
|
|
@ -978,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() {
|
||||||
|
|
@ -989,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");
|
||||||
|
|
@ -1007,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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1021,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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1038,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
|
||||||
|
|
@ -1049,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() {
|
||||||
|
|
@ -1075,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);
|
||||||
|
|
@ -1085,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() {
|
||||||
|
|
@ -1103,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();
|
||||||
|
|
@ -1111,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);
|
||||||
|
|
@ -1124,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);
|
||||||
|
|
@ -1137,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() {
|
||||||
|
|
@ -1146,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) {
|
||||||
|
|
@ -1160,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) {
|
||||||
|
|
@ -1168,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;
|
||||||
}
|
}
|
||||||
|
|
@ -1177,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() {
|
||||||
|
|
@ -1204,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();
|
||||||
|
|
@ -1221,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;
|
||||||
|
|
@ -1231,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(".");
|
||||||
}
|
}
|
||||||
|
|
@ -1242,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(" ");
|
||||||
|
|
@ -1277,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(" ");
|
||||||
|
|
@ -1289,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("?");
|
||||||
|
|
@ -1301,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();
|
||||||
|
|
@ -1311,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) {
|
||||||
|
|
@ -1337,7 +1359,7 @@ function OutputStream(options) {
|
||||||
output.print_string(key);
|
output.print_string(key);
|
||||||
} else if ("" + +key == key && key >= 0) {
|
} else if ("" + +key == key && key >= 0) {
|
||||||
output.print(make_num(key));
|
output.print(make_num(key));
|
||||||
} else if (RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) {
|
} else if (parse.RESERVED_WORDS[key] ? !output.option("ie8") : is_identifier_string(key)) {
|
||||||
if (quote && output.option("keep_quoted_props")) {
|
if (quote && output.option("keep_quoted_props")) {
|
||||||
output.print_string(key, quote);
|
output.print_string(key, quote);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1348,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 {
|
||||||
|
|
@ -1387,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) {
|
||||||
|
|
@ -1396,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(" ");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1404,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;
|
||||||
|
|
@ -1455,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();
|
||||||
|
|
@ -1477,44 +1499,50 @@ 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);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
merge(exports, {
|
||||||
|
EXPECT_DIRECTIVE : EXPECT_DIRECTIVE,
|
||||||
|
is_some_comments : is_some_comments,
|
||||||
|
OutputStream : OutputStream,
|
||||||
|
});
|
||||||
|
|
|
||||||
190
lib/parse.js
190
lib/parse.js
|
|
@ -44,6 +44,18 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var utils = require("./utils");
|
||||||
|
var characters = utils.characters;
|
||||||
|
var find_if = utils.find_if;
|
||||||
|
var configure_error_stack = utils.configure_error_stack;
|
||||||
|
var defaults = utils.defaults;
|
||||||
|
var makePredicate = utils.makePredicate;
|
||||||
|
var all = utils.all;
|
||||||
|
var HOP = utils.HOP;
|
||||||
|
var merge = utils.merge;
|
||||||
|
|
||||||
|
var AST = require("./ast");
|
||||||
|
|
||||||
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';
|
||||||
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield'
|
var RESERVED_WORDS = 'abstract boolean byte char class double enum export extends final float goto implements import int interface let long native package private protected public short static super synchronized this throws transient volatile yield'
|
||||||
|
|
@ -322,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() {
|
||||||
|
|
@ -833,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":
|
||||||
|
|
@ -848,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()
|
||||||
|
|
@ -859,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();
|
||||||
}
|
}
|
||||||
|
|
@ -868,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();
|
||||||
|
|
@ -885,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)
|
||||||
});
|
});
|
||||||
|
|
@ -906,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();
|
||||||
|
|
@ -923,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_)
|
||||||
});
|
});
|
||||||
|
|
@ -940,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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -959,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()
|
||||||
});
|
});
|
||||||
|
|
@ -969,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;
|
||||||
})) {
|
})) {
|
||||||
|
|
@ -983,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) {
|
||||||
|
|
@ -1028,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)) {
|
||||||
|
|
@ -1047,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,
|
||||||
|
|
@ -1058,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)
|
||||||
|
|
@ -1066,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;
|
||||||
|
|
@ -1108,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
|
||||||
|
|
@ -1134,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
|
||||||
|
|
@ -1145,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
|
||||||
});
|
});
|
||||||
|
|
@ -1167,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_(),
|
||||||
|
|
@ -1179,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()
|
||||||
|
|
@ -1187,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
|
||||||
|
|
@ -1197,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()
|
||||||
}));
|
}));
|
||||||
|
|
@ -1211,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()
|
||||||
|
|
@ -1228,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,
|
||||||
|
|
@ -1242,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,
|
||||||
|
|
@ -1256,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;
|
||||||
|
|
@ -1305,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);
|
||||||
|
|
@ -1316,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);
|
||||||
|
|
@ -1333,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));
|
||||||
}
|
}
|
||||||
|
|
@ -1344,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() {
|
||||||
|
|
@ -1365,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(),
|
||||||
|
|
@ -1380,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(),
|
||||||
|
|
@ -1390,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,
|
||||||
|
|
@ -1399,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() {
|
||||||
|
|
@ -1428,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
|
||||||
|
|
@ -1446,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();
|
||||||
|
|
@ -1470,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(),
|
||||||
|
|
@ -1481,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,
|
||||||
|
|
@ -1490,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(")"),
|
||||||
|
|
@ -1507,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();
|
||||||
|
|
@ -1531,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;
|
||||||
}
|
}
|
||||||
|
|
@ -1545,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,
|
||||||
|
|
@ -1567,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,
|
||||||
|
|
@ -1579,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) {
|
||||||
|
|
@ -1588,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,
|
||||||
|
|
@ -1610,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()
|
||||||
|
|
@ -1641,8 +1653,48 @@ 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;
|
||||||
}();
|
}();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
merge(exports, {
|
||||||
|
KEYWORDS : KEYWORDS,
|
||||||
|
KEYWORDS_ATOM : KEYWORDS_ATOM,
|
||||||
|
RESERVED_WORDS : RESERVED_WORDS,
|
||||||
|
KEYWORDS_BEFORE_EXPRESSION : KEYWORDS_BEFORE_EXPRESSION,
|
||||||
|
OPERATOR_CHARS : OPERATOR_CHARS,
|
||||||
|
RE_HEX_NUMBER : RE_HEX_NUMBER,
|
||||||
|
RE_OCT_NUMBER : RE_OCT_NUMBER,
|
||||||
|
OPERATORS : OPERATORS,
|
||||||
|
WHITESPACE_CHARS : WHITESPACE_CHARS,
|
||||||
|
NEWLINE_CHARS : NEWLINE_CHARS,
|
||||||
|
PUNC_BEFORE_EXPRESSION : PUNC_BEFORE_EXPRESSION,
|
||||||
|
PUNC_CHARS : PUNC_CHARS,
|
||||||
|
UNICODE : UNICODE,
|
||||||
|
is_letter : is_letter,
|
||||||
|
is_surrogate_pair_head : is_surrogate_pair_head,
|
||||||
|
is_surrogate_pair_tail : is_surrogate_pair_tail,
|
||||||
|
is_digit : is_digit,
|
||||||
|
is_alphanumeric_char : is_alphanumeric_char,
|
||||||
|
is_unicode_digit : is_unicode_digit,
|
||||||
|
is_unicode_combining_mark : is_unicode_combining_mark,
|
||||||
|
is_unicode_connector_punctuation : is_unicode_connector_punctuation,
|
||||||
|
is_identifier : is_identifier,
|
||||||
|
is_identifier_start : is_identifier_start,
|
||||||
|
is_identifier_char : is_identifier_char,
|
||||||
|
is_identifier_string : is_identifier_string,
|
||||||
|
parse_js_number : parse_js_number,
|
||||||
|
JS_Parse_Error : JS_Parse_Error,
|
||||||
|
js_error : js_error,
|
||||||
|
is_token : is_token,
|
||||||
|
EX_EOF : EX_EOF,
|
||||||
|
tokenizer : tokenizer,
|
||||||
|
UNARY_PREFIX : UNARY_PREFIX,
|
||||||
|
UNARY_POSTFIX : UNARY_POSTFIX,
|
||||||
|
ASSIGNMENT : ASSIGNMENT,
|
||||||
|
PRECEDENCE : PRECEDENCE,
|
||||||
|
ATOMIC_START_TOKEN : ATOMIC_START_TOKEN,
|
||||||
|
parse : parse,
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,19 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var utils = require("./utils");
|
||||||
|
var defaults = utils.defaults;
|
||||||
|
var push_uniq = utils.push_uniq;
|
||||||
|
var Dictionary = utils.Dictionary;
|
||||||
|
var merge = utils.merge;
|
||||||
|
|
||||||
|
var scope = require("./scope");
|
||||||
|
var base54 = scope.base54;
|
||||||
|
|
||||||
|
var AST = require("./ast");
|
||||||
|
var TreeWalker = AST.TreeWalker;
|
||||||
|
var TreeTransformer = AST.TreeTransformer;
|
||||||
|
|
||||||
function find_builtins(reserved) {
|
function find_builtins(reserved) {
|
||||||
// NaN will be included due to Number.NaN
|
// NaN will be included due to Number.NaN
|
||||||
[
|
[
|
||||||
|
|
@ -73,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);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
@ -83,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);
|
||||||
}
|
}
|
||||||
|
|
@ -137,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);
|
||||||
}
|
}
|
||||||
|
|
@ -158,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]);
|
||||||
}
|
}
|
||||||
|
|
@ -235,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);
|
||||||
}
|
}
|
||||||
|
|
@ -250,3 +263,10 @@ function mangle_properties(ast, options) {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
merge(exports, {
|
||||||
|
find_builtins : find_builtins,
|
||||||
|
reserve_quoted_keys : reserve_quoted_keys,
|
||||||
|
addStrings : addStrings,
|
||||||
|
mangle_properties : mangle_properties,
|
||||||
|
});
|
||||||
|
|
|
||||||
161
lib/scope.js
161
lib/scope.js
|
|
@ -43,6 +43,22 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var utils = require("./utils");
|
||||||
|
var defaults = utils.defaults;
|
||||||
|
var return_false = utils.return_false;
|
||||||
|
var return_this = utils.return_this;
|
||||||
|
var push_uniq = utils.push_uniq;
|
||||||
|
var makePredicate = utils.makePredicate;
|
||||||
|
var Dictionary = utils.Dictionary;
|
||||||
|
var merge = utils.merge;
|
||||||
|
|
||||||
|
var AST = require("./ast");
|
||||||
|
var TreeWalker = AST.TreeWalker;
|
||||||
|
|
||||||
|
var parse = require("./parse");
|
||||||
|
var is_identifier = parse.is_identifier;
|
||||||
|
var parse = parse.parse;
|
||||||
|
|
||||||
function SymbolDef(scope, orig, init) {
|
function SymbolDef(scope, orig, init) {
|
||||||
this.name = orig.name;
|
this.name = orig.name;
|
||||||
this.orig = [ orig ];
|
this.orig = [ orig ];
|
||||||
|
|
@ -67,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;
|
||||||
|
|
@ -91,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,
|
||||||
|
|
@ -102,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;
|
||||||
|
|
@ -120,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);
|
||||||
|
|
@ -154,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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -163,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;
|
||||||
}
|
}
|
||||||
|
|
@ -177,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;
|
||||||
|
|
@ -186,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);
|
||||||
|
|
@ -200,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;
|
||||||
|
|
@ -217,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);
|
||||||
|
|
@ -230,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
|
||||||
|
|
@ -240,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) {
|
||||||
|
|
@ -265,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 {
|
||||||
|
|
@ -317,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;
|
||||||
|
|
@ -349,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;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -390,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) {
|
||||||
|
|
@ -408,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) {
|
||||||
|
|
@ -457,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;
|
||||||
|
|
||||||
|
|
@ -480,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);
|
||||||
|
|
@ -488,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() {
|
||||||
|
|
@ -515,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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -597,3 +613,10 @@ var base54 = (function() {
|
||||||
}
|
}
|
||||||
return base54;
|
return base54;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
merge(exports, {
|
||||||
|
SymbolDef : SymbolDef,
|
||||||
|
names_in_use : names_in_use,
|
||||||
|
next_mangled_name : next_mangled_name,
|
||||||
|
base54 : base54,
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,11 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var MOZ_SourceMap = require("source-map");
|
||||||
|
var utils = require("./utils");
|
||||||
|
var defaults = utils.defaults;
|
||||||
|
var merge = utils.merge;
|
||||||
|
|
||||||
// a small wrapper around fitzgen's source-map library
|
// a small wrapper around fitzgen's source-map library
|
||||||
function SourceMap(options) {
|
function SourceMap(options) {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
|
|
@ -102,3 +107,7 @@ function SourceMap(options) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
merge(exports, {
|
||||||
|
SourceMap : SourceMap,
|
||||||
|
});
|
||||||
|
|
|
||||||
185
lib/transform.js
185
lib/transform.js
|
|
@ -1,185 +0,0 @@
|
||||||
/***********************************************************************
|
|
||||||
|
|
||||||
A JavaScript tokenizer / parser / beautifier / compressor.
|
|
||||||
https://github.com/mishoo/UglifyJS2
|
|
||||||
|
|
||||||
-------------------------------- (C) ---------------------------------
|
|
||||||
|
|
||||||
Author: Mihai Bazon
|
|
||||||
<mihai.bazon@gmail.com>
|
|
||||||
http://mihai.bazon.net/blog
|
|
||||||
|
|
||||||
Distributed under the BSD license:
|
|
||||||
|
|
||||||
Copyright 2012 (c) Mihai Bazon <mihai.bazon@gmail.com>
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer in the documentation and/or other materials
|
|
||||||
provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
||||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
|
||||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
||||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
|
||||||
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
SUCH DAMAGE.
|
|
||||||
|
|
||||||
***********************************************************************/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
function TreeTransformer(before, after) {
|
|
||||||
TreeWalker.call(this);
|
|
||||||
this.before = before;
|
|
||||||
this.after = after;
|
|
||||||
}
|
|
||||||
TreeTransformer.prototype = new TreeWalker;
|
|
||||||
|
|
||||||
(function(DEF) {
|
|
||||||
function do_list(list, tw) {
|
|
||||||
return MAP(list, function(node) {
|
|
||||||
return node.transform(tw, true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
DEF(AST_Node, noop);
|
|
||||||
DEF(AST_LabeledStatement, function(self, tw) {
|
|
||||||
self.label = self.label.transform(tw);
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_SimpleStatement, function(self, tw) {
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Block, function(self, tw) {
|
|
||||||
self.body = do_list(self.body, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Do, function(self, tw) {
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
self.condition = self.condition.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_While, function(self, tw) {
|
|
||||||
self.condition = self.condition.transform(tw);
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_For, function(self, tw) {
|
|
||||||
if (self.init) self.init = self.init.transform(tw);
|
|
||||||
if (self.condition) self.condition = self.condition.transform(tw);
|
|
||||||
if (self.step) self.step = self.step.transform(tw);
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_ForIn, function(self, tw) {
|
|
||||||
self.init = self.init.transform(tw);
|
|
||||||
self.object = self.object.transform(tw);
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_With, function(self, tw) {
|
|
||||||
self.expression = self.expression.transform(tw);
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Exit, function(self, tw) {
|
|
||||||
if (self.value) self.value = self.value.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_LoopControl, function(self, tw) {
|
|
||||||
if (self.label) self.label = self.label.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_If, function(self, tw) {
|
|
||||||
self.condition = self.condition.transform(tw);
|
|
||||||
self.body = self.body.transform(tw);
|
|
||||||
if (self.alternative) self.alternative = self.alternative.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Switch, function(self, tw) {
|
|
||||||
self.expression = self.expression.transform(tw);
|
|
||||||
self.body = do_list(self.body, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Case, function(self, tw) {
|
|
||||||
self.expression = self.expression.transform(tw);
|
|
||||||
self.body = do_list(self.body, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Try, function(self, tw) {
|
|
||||||
self.body = do_list(self.body, tw);
|
|
||||||
if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
|
|
||||||
if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Catch, function(self, tw) {
|
|
||||||
self.argname = self.argname.transform(tw);
|
|
||||||
self.body = do_list(self.body, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Definitions, function(self, tw) {
|
|
||||||
self.definitions = do_list(self.definitions, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_VarDef, function(self, tw) {
|
|
||||||
self.name = self.name.transform(tw);
|
|
||||||
if (self.value) self.value = self.value.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Lambda, function(self, tw) {
|
|
||||||
if (self.name) self.name = self.name.transform(tw);
|
|
||||||
self.argnames = do_list(self.argnames, tw);
|
|
||||||
self.body = do_list(self.body, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Call, function(self, tw) {
|
|
||||||
self.expression = self.expression.transform(tw);
|
|
||||||
self.args = do_list(self.args, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Sequence, function(self, tw) {
|
|
||||||
self.expressions = do_list(self.expressions, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Dot, function(self, tw) {
|
|
||||||
self.expression = self.expression.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Sub, function(self, tw) {
|
|
||||||
self.expression = self.expression.transform(tw);
|
|
||||||
self.property = self.property.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Unary, function(self, tw) {
|
|
||||||
self.expression = self.expression.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Binary, function(self, tw) {
|
|
||||||
self.left = self.left.transform(tw);
|
|
||||||
self.right = self.right.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Conditional, function(self, tw) {
|
|
||||||
self.condition = self.condition.transform(tw);
|
|
||||||
self.consequent = self.consequent.transform(tw);
|
|
||||||
self.alternative = self.alternative.transform(tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Array, function(self, tw) {
|
|
||||||
self.elements = do_list(self.elements, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_Object, function(self, tw) {
|
|
||||||
self.properties = do_list(self.properties, tw);
|
|
||||||
});
|
|
||||||
DEF(AST_ObjectProperty, function(self, tw) {
|
|
||||||
self.value = self.value.transform(tw);
|
|
||||||
});
|
|
||||||
})(function(node, descend) {
|
|
||||||
node.DEFMETHOD("transform", function(tw, in_list) {
|
|
||||||
var x, y;
|
|
||||||
tw.push(this);
|
|
||||||
if (tw.before) x = tw.before(this, descend, in_list);
|
|
||||||
if (typeof x === "undefined") {
|
|
||||||
x = this;
|
|
||||||
descend(x, tw);
|
|
||||||
if (tw.after) {
|
|
||||||
y = tw.after(x, in_list);
|
|
||||||
if (typeof y !== "undefined") x = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tw.pop();
|
|
||||||
return x;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
47
lib/utils.js
47
lib/utils.js
|
|
@ -255,27 +255,26 @@ function HOP(obj, prop) {
|
||||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if the node at the top of the stack (that means the
|
merge(exports, {
|
||||||
// innermost node in the current output) is lexically the first in
|
characters : characters,
|
||||||
// a statement.
|
member : member,
|
||||||
function first_in_statement(stack) {
|
find_if : find_if,
|
||||||
var node = stack.parent(-1);
|
repeat_string : repeat_string,
|
||||||
for (var i = 0, p; p = stack.parent(i++); node = p) {
|
configure_error_stack : configure_error_stack,
|
||||||
if (p.TYPE == "Call") {
|
DefaultsError : DefaultsError,
|
||||||
if (p.expression === node) continue;
|
defaults : defaults,
|
||||||
} else if (p instanceof AST_Binary) {
|
merge : merge,
|
||||||
if (p.left === node) continue;
|
noop : noop,
|
||||||
} else if (p instanceof AST_Conditional) {
|
return_false : return_false,
|
||||||
if (p.condition === node) continue;
|
return_true : return_true,
|
||||||
} else if (p instanceof AST_PropAccess) {
|
return_this : return_this,
|
||||||
if (p.expression === node) continue;
|
return_null : return_null,
|
||||||
} else if (p instanceof AST_Sequence) {
|
MAP : MAP,
|
||||||
if (p.expressions[0] === node) continue;
|
push_uniq : push_uniq,
|
||||||
} else if (p instanceof AST_Statement) {
|
string_template : string_template,
|
||||||
return p.body === node;
|
remove : remove,
|
||||||
} else if (p instanceof AST_UnaryPostfix) {
|
makePredicate : makePredicate,
|
||||||
if (p.expression === node) continue;
|
all : all,
|
||||||
}
|
Dictionary : Dictionary,
|
||||||
return false;
|
HOP : HOP,
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
exports["Compressor"] = Compressor;
|
|
||||||
exports["JS_Parse_Error"] = JS_Parse_Error;
|
|
||||||
exports["OutputStream"] = OutputStream;
|
|
||||||
exports["SourceMap"] = SourceMap;
|
|
||||||
exports["TreeWalker"] = TreeWalker;
|
|
||||||
exports["base54"] = base54;
|
|
||||||
exports["defaults"] = defaults;
|
|
||||||
exports["mangle_properties"] = mangle_properties;
|
|
||||||
exports["minify"] = minify;
|
|
||||||
exports["parse"] = parse;
|
|
||||||
exports["reserve_quoted_keys"] = reserve_quoted_keys;
|
|
||||||
exports["string_template"] = string_template;
|
|
||||||
exports["tokenizer"] = tokenizer;
|
|
||||||
exports["is_identifier"] = is_identifier;
|
|
||||||
|
|
@ -22,6 +22,7 @@ it = function(title, fn) {
|
||||||
tasks.push(fn);
|
tasks.push(fn);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
fs.readdirSync("test/mocha").filter(function(file) {
|
fs.readdirSync("test/mocha").filter(function(file) {
|
||||||
return /\.js$/.test(file);
|
return /\.js$/.test(file);
|
||||||
}).forEach(function(file) {
|
}).forEach(function(file) {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ describe("bin/uglifyjs", function() {
|
||||||
it("should produce a functional build when using --self", function(done) {
|
it("should produce a functional build when using --self", function(done) {
|
||||||
this.timeout(30000);
|
this.timeout(30000);
|
||||||
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
var command = uglifyjscmd + ' --self -cm --wrap WrappedUglifyJS';
|
||||||
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);
|
||||||
assert.strictEqual(typeof WrappedUglifyJS, "object");
|
assert.strictEqual(typeof WrappedUglifyJS, "object");
|
||||||
|
|
@ -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();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
16
test/node.js
16
test/node.js
|
|
@ -1,6 +1,10 @@
|
||||||
var fs = require("fs");
|
var orig = require("../tools/node");
|
||||||
|
orig.SourceMap = require("../lib/sourcemap").SourceMap;
|
||||||
new Function("MOZ_SourceMap", "exports", require("../tools/node").FILES.map(function(file) {
|
orig.base54 = orig.utils.base54;
|
||||||
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
|
orig.defaults = orig.utils.defaults;
|
||||||
return fs.readFileSync(file, "utf8");
|
orig.mangle_properties = orig.propmangle.mangle_properties;
|
||||||
}).join("\n\n"))(require("source-map"), exports);
|
orig.reserve_quoted_keys = orig.propmangle.reserve_quoted_keys;
|
||||||
|
orig.JS_Parse_Error = orig.parser.JS_Parse_Error;
|
||||||
|
orig.tokenizer = orig.parser.tokenizer;
|
||||||
|
orig.is_identifier = orig.parser.is_identifier;
|
||||||
|
module.exports = orig;
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
exports["Compressor"] = Compressor;
|
||||||
exports["Dictionary"] = Dictionary;
|
exports["Dictionary"] = Dictionary;
|
||||||
exports["TreeWalker"] = TreeWalker;
|
exports["TreeWalker"] = TreeWalker;
|
||||||
exports["TreeTransformer"] = TreeTransformer;
|
exports["TreeTransformer"] = TreeTransformer;
|
||||||
exports["minify"] = minify;
|
exports["minify"] = minify;
|
||||||
exports["parse"] = parse;
|
exports["parse"] = parse;
|
||||||
exports["_push_uniq"] = push_uniq;
|
exports["_push_uniq"] = push_uniq;
|
||||||
|
exports["string_template"] = string_template;
|
||||||
|
|
|
||||||
61
tools/generate-exports.js
Normal file
61
tools/generate-exports.js
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var UglifyJS = require("../tools/node");
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
console.log = function (d) {
|
||||||
|
process.stdout.write(d + '\n');
|
||||||
|
};
|
||||||
|
|
||||||
|
UglifyJS.FILES.forEach(function(filepath){
|
||||||
|
var code = fs.readFileSync(filepath, "utf8");
|
||||||
|
var filename = filepath.replace(/^.*?([-a-z]+)\.js$/g, "$1");
|
||||||
|
|
||||||
|
var AST = UglifyJS.parse(code, {filename: filepath});
|
||||||
|
|
||||||
|
var exportNames = [];
|
||||||
|
var walker = new UglifyJS.TreeWalker(function(node){
|
||||||
|
if (node instanceof UglifyJS.ast.AST_Defun) {
|
||||||
|
exportNames.push(node.name.name);
|
||||||
|
}
|
||||||
|
if (node instanceof UglifyJS.ast.AST_Var) {
|
||||||
|
var def = node.definitions[0];
|
||||||
|
var name = def.name.name;
|
||||||
|
var value = def.value;
|
||||||
|
// Skip <var> = foo.<var>
|
||||||
|
if (value instanceof UglifyJS.ast.AST_Dot && value.property == name)
|
||||||
|
return true;
|
||||||
|
// Skip <var> = require(...)
|
||||||
|
if (value instanceof UglifyJS.ast.AST_Call && value.expression instanceof UglifyJS.ast.AST_SymbolRef && value.expression.name == "require")
|
||||||
|
return true;
|
||||||
|
exportNames.push(name);
|
||||||
|
}
|
||||||
|
return !(node instanceof UglifyJS.ast.AST_Toplevel);
|
||||||
|
});
|
||||||
|
AST.walk(walker);
|
||||||
|
// Don't export identifiers starting with underscore
|
||||||
|
exportNames = exportNames.filter(name => name[0] != "_");
|
||||||
|
if (exportNames.length == 0)
|
||||||
|
return;
|
||||||
|
// Use (utils.)merge instead of Object.assign for (very) old node
|
||||||
|
var exports = "merge(exports, {\n" + exportNames.map(
|
||||||
|
name => UglifyJS.string_template(' {name} : {name},', { name: name })
|
||||||
|
).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){
|
||||||
|
return UglifyJS.string_template(UglifyJS.string_template('var {name} = {fn}.{name};', { name: name, fn: filename}));
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("\n// Exports for " + filename);
|
||||||
|
console.log(exports);
|
||||||
|
console.log("\n\n// Usage:")
|
||||||
|
console.log(UglifyJS.string_template('var {fn} = require("../lib/{fn}");', { fn: filename}));
|
||||||
|
console.log(imports.join("\n"));
|
||||||
|
|
||||||
|
var result = code.replace(/\n+(exports\.\w+ = \w+;\n+)+$/, "");
|
||||||
|
result = result.replace(/\n+Object\.assign\(exports, \{[\s\S]*?\}\);\n*$/, "");
|
||||||
|
result = result.replace(/\n+merge\(exports, \{[\s\S]*?\}\);\n*$/, "");
|
||||||
|
result += "\n\n" + exports + "\n";
|
||||||
|
fs.writeFileSync(filepath, result, "utf8");
|
||||||
|
});
|
||||||
|
|
@ -5,7 +5,6 @@ var FILES = UglifyJS.FILES = [
|
||||||
"../lib/utils.js",
|
"../lib/utils.js",
|
||||||
"../lib/ast.js",
|
"../lib/ast.js",
|
||||||
"../lib/parse.js",
|
"../lib/parse.js",
|
||||||
"../lib/transform.js",
|
|
||||||
"../lib/scope.js",
|
"../lib/scope.js",
|
||||||
"../lib/output.js",
|
"../lib/output.js",
|
||||||
"../lib/compress.js",
|
"../lib/compress.js",
|
||||||
|
|
@ -18,21 +17,42 @@ var FILES = UglifyJS.FILES = [
|
||||||
return require.resolve(file);
|
return require.resolve(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
new Function("MOZ_SourceMap", "exports", function() {
|
var utils = require("../lib/utils");
|
||||||
var code = FILES.map(function(file) {
|
var output = require("../lib/output");
|
||||||
return fs.readFileSync(file, "utf8");
|
var OutputStream = output.OutputStream;
|
||||||
});
|
var minify = require("../lib/minify").minify;
|
||||||
code.push("exports.describe_ast = " + describe_ast.toString());
|
var AST = require("../lib/ast");
|
||||||
return code.join("\n\n");
|
var compress = require("../lib/compress");
|
||||||
}())(
|
var parse = require("../lib/parse");
|
||||||
require("source-map"),
|
var propmangle = require("../lib/propmangle");
|
||||||
UglifyJS
|
require("../lib/mozilla-ast");
|
||||||
);
|
|
||||||
|
|
||||||
|
exports.utils = utils;
|
||||||
|
exports.OutputStream = OutputStream;
|
||||||
|
exports.minify = minify;
|
||||||
|
exports.AST = AST;
|
||||||
|
exports.parser = parse;
|
||||||
|
exports.parse = parse.parse;
|
||||||
|
exports.Compressor = compress.Compressor;
|
||||||
|
exports.Dictionary = utils.Dictionary;
|
||||||
|
exports.TreeWalker = AST.TreeWalker;
|
||||||
|
exports.TreeTransformer = AST.TreeTransformer;
|
||||||
|
exports.push_uniq = utils.push_uniq;
|
||||||
|
exports.string_template = utils.string_template;
|
||||||
|
exports.describe_ast = describe_ast;
|
||||||
|
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);
|
||||||
});
|
});
|
||||||
|
|
@ -60,7 +80,7 @@ function describe_ast() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
doitem(AST_Node);
|
doitem(AST.Node);
|
||||||
return out + "\n";
|
return out + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user