Compare commits

...

7 Commits

Author SHA1 Message Date
Alex Lam S.L
88c8f4e363 v3.4.2 2018-06-26 01:29:48 +08:00
Alex Lam S.L
ab36b9b10a fix corner case in ie8 (#3198)
fixes #3197
2018-06-24 04:00:36 +08:00
Alex Lam S.L
28330913d8 improve mocha tests (#3195) 2018-06-24 04:00:36 +08:00
Alex Lam S.L
766a4147d4 enhance arguments (#3193)
fixes #3192
2018-06-24 04:00:21 +08:00
Alex Lam S.L
915c7e234d v3.4.1 2018-06-19 18:35:48 +00:00
Alex Lam S.L
e54ddcbb8a fix corner cases in properties (#3189)
fixes #3188
2018-06-19 18:20:11 +08:00
Alex Lam S.L
9e19e63551 general clean-ups (#3175) 2018-06-06 17:50:56 +08:00
47 changed files with 1858 additions and 1614 deletions

View File

@@ -44,21 +44,21 @@
"use strict"; "use strict";
function DEFNODE(type, props, methods, base) { function DEFNODE(type, props, methods, base) {
if (arguments.length < 4) base = AST_Node; if (typeof base === "undefined") base = AST_Node;
if (!props) props = []; props = props ? props.split(/\s+/) : [];
else props = props.split(/\s+/);
var self_props = props; var self_props = props;
if (base && base.PROPS) if (base && base.PROPS) props = props.concat(base.PROPS);
props = props.concat(base.PROPS); var code = [
var code = "return function AST_" + type + "(props){ if (props) { "; "return function AST_", type, "(props){",
for (var i = props.length; --i >= 0;) { "if(props){",
code += "this." + props[i] + " = props." + props[i] + ";"; ];
} props.forEach(function(prop) {
code.push("this.", prop, "=props.", prop, ";");
});
var proto = base && new base; var proto = base && new base;
if (proto && proto.initialize || (methods && methods.initialize)) if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();");
code += "this.initialize();"; code.push("}}");
code += "}}"; var ctor = new Function(code.join(""))();
var ctor = new Function(code)();
if (proto) { if (proto) {
ctor.prototype = proto; ctor.prototype = proto;
ctor.BASE = base; ctor.BASE = base;
@@ -71,11 +71,11 @@ function DEFNODE(type, props, methods, base) {
if (type) { if (type) {
ctor.prototype.TYPE = ctor.TYPE = type; ctor.prototype.TYPE = ctor.TYPE = type;
} }
if (methods) for (i in methods) if (HOP(methods, i)) { if (methods) for (var name in methods) if (HOP(methods, name)) {
if (/^\$/.test(i)) { if (/^\$/.test(name)) {
ctor[i.substr(1)] = methods[i]; ctor[name.substr(1)] = methods[name];
} else { } else {
ctor.prototype[i] = methods[i]; ctor.prototype[name] = methods[name];
} }
} }
ctor.DEFMETHOD = function(name, method) { ctor.DEFMETHOD = function(name, method) {
@@ -85,7 +85,7 @@ function DEFNODE(type, props, methods, base) {
exports["AST_" + type] = ctor; exports["AST_" + type] = ctor;
} }
return ctor; return ctor;
}; }
var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", { var AST_Token = DEFNODE("Token", "type value line col pos endline endcol endpos nlb comments_before comments_after file raw", {
}, null); }, null);
@@ -148,7 +148,7 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)" body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.body._walk(visitor); this.body._walk(visitor);
}); });
} }
@@ -158,11 +158,10 @@ function walk_body(node, visitor) {
var body = node.body; var body = node.body;
if (body instanceof AST_Statement) { if (body instanceof AST_Statement) {
body._walk(visitor); body._walk(visitor);
} } else body.forEach(function(node) {
else for (var i = 0, len = body.length; i < len; i++) { node._walk(visitor);
body[i]._walk(visitor); });
} }
};
var AST_Block = DEFNODE("Block", "body", { var AST_Block = DEFNODE("Block", "body", {
$documentation: "A body of statements (usually braced)", $documentation: "A body of statements (usually braced)",
@@ -170,7 +169,7 @@ var AST_Block = DEFNODE("Block", "body", {
body: "[AST_Statement*] an array of statements" body: "[AST_Statement*] an array of statements"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
walk_body(this, visitor); walk_body(this, visitor);
}); });
} }
@@ -197,7 +196,7 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
label: "[AST_Label] a label definition" label: "[AST_Label] a label definition"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.label._walk(visitor); this.label._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
}); });
@@ -233,7 +232,7 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", {
var AST_Do = DEFNODE("Do", null, { var AST_Do = DEFNODE("Do", null, {
$documentation: "A `do` statement", $documentation: "A `do` statement",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.body._walk(visitor); this.body._walk(visitor);
this.condition._walk(visitor); this.condition._walk(visitor);
}); });
@@ -243,7 +242,7 @@ var AST_Do = DEFNODE("Do", null, {
var AST_While = DEFNODE("While", null, { var AST_While = DEFNODE("While", null, {
$documentation: "A `while` statement", $documentation: "A `while` statement",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.condition._walk(visitor); this.condition._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
}); });
@@ -258,7 +257,7 @@ var AST_For = DEFNODE("For", "init condition step", {
step: "[AST_Node?] the `for` update clause, or null if empty" step: "[AST_Node?] the `for` update clause, or null if empty"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
if (this.init) this.init._walk(visitor); if (this.init) this.init._walk(visitor);
if (this.condition) this.condition._walk(visitor); if (this.condition) this.condition._walk(visitor);
if (this.step) this.step._walk(visitor); if (this.step) this.step._walk(visitor);
@@ -274,7 +273,7 @@ var AST_ForIn = DEFNODE("ForIn", "init object", {
object: "[AST_Node] the object that we're looping through" object: "[AST_Node] the object that we're looping through"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.init._walk(visitor); this.init._walk(visitor);
this.object._walk(visitor); this.object._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
@@ -288,7 +287,7 @@ var AST_With = DEFNODE("With", "expression", {
expression: "[AST_Node] the `with` expression" expression: "[AST_Node] the `with` expression"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
}); });
@@ -329,7 +328,7 @@ var AST_Toplevel = DEFNODE("Toplevel", "globals", {
var body = this.body; var body = this.body;
var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");"; var wrapped_tl = "(function(exports){'$ORIG';})(typeof " + name + "=='undefined'?(" + name + "={}):" + name + ");";
wrapped_tl = parse(wrapped_tl); wrapped_tl = parse(wrapped_tl);
wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node){ wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
if (node instanceof AST_Directive && node.value == "$ORIG") { if (node instanceof AST_Directive && node.value == "$ORIG") {
return MAP.splice(body); return MAP.splice(body);
} }
@@ -363,12 +362,11 @@ var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array" uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
if (this.name) this.name._walk(visitor); if (this.name) this.name._walk(visitor);
var argnames = this.argnames; this.argnames.forEach(function(argname) {
for (var i = 0, len = argnames.length; i < len; i++) { argname._walk(visitor);
argnames[i]._walk(visitor); });
}
walk_body(this, visitor); walk_body(this, visitor);
}); });
} }
@@ -398,7 +396,7 @@ var AST_Exit = DEFNODE("Exit", "value", {
value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return" value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, this.value && function(){ return visitor._visit(this, this.value && function() {
this.value._walk(visitor); this.value._walk(visitor);
}); });
} }
@@ -418,7 +416,7 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", {
label: "[AST_LabelRef?] the label, or null if none", label: "[AST_LabelRef?] the label, or null if none",
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, this.label && function(){ return visitor._visit(this, this.label && function() {
this.label._walk(visitor); this.label._walk(visitor);
}); });
} }
@@ -441,7 +439,7 @@ var AST_If = DEFNODE("If", "condition alternative", {
alternative: "[AST_Statement?] the `else` part, or null if not present" alternative: "[AST_Statement?] the `else` part, or null if not present"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.condition._walk(visitor); this.condition._walk(visitor);
this.body._walk(visitor); this.body._walk(visitor);
if (this.alternative) this.alternative._walk(visitor); if (this.alternative) this.alternative._walk(visitor);
@@ -457,7 +455,7 @@ var AST_Switch = DEFNODE("Switch", "expression", {
expression: "[AST_Node] the `switch` “discriminant”" expression: "[AST_Node] the `switch` “discriminant”"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
walk_body(this, visitor); walk_body(this, visitor);
}); });
@@ -478,7 +476,7 @@ var AST_Case = DEFNODE("Case", "expression", {
expression: "[AST_Node] the `case` expression" expression: "[AST_Node] the `case` expression"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
walk_body(this, visitor); walk_body(this, visitor);
}); });
@@ -494,7 +492,7 @@ var AST_Try = DEFNODE("Try", "bcatch bfinally", {
bfinally: "[AST_Finally?] the finally block, or null if not present" bfinally: "[AST_Finally?] the finally block, or null if not present"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
walk_body(this, visitor); walk_body(this, visitor);
if (this.bcatch) this.bcatch._walk(visitor); if (this.bcatch) this.bcatch._walk(visitor);
if (this.bfinally) this.bfinally._walk(visitor); if (this.bfinally) this.bfinally._walk(visitor);
@@ -508,7 +506,7 @@ var AST_Catch = DEFNODE("Catch", "argname", {
argname: "[AST_SymbolCatch] symbol for the exception" argname: "[AST_SymbolCatch] symbol for the exception"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.argname._walk(visitor); this.argname._walk(visitor);
walk_body(this, visitor); walk_body(this, visitor);
}); });
@@ -527,11 +525,10 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", {
definitions: "[AST_VarDef*] array of variable definitions" definitions: "[AST_VarDef*] array of variable definitions"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
var definitions = this.definitions; this.definitions.forEach(function(defn) {
for (var i = 0, len = definitions.length; i < len; i++) { defn._walk(visitor);
definitions[i]._walk(visitor); });
}
}); });
} }
}, AST_Statement); }, AST_Statement);
@@ -547,7 +544,7 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
value: "[AST_Node?] initializer, or null of there's no initializer" value: "[AST_Node?] initializer, or null of there's no initializer"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.name._walk(visitor); this.name._walk(visitor);
if (this.value) this.value._walk(visitor); if (this.value) this.value._walk(visitor);
}); });
@@ -582,7 +579,7 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", {
expressions: "[AST_Node*] array of expressions (at least two)" expressions: "[AST_Node*] array of expressions (at least two)"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expressions.forEach(function(node) { this.expressions.forEach(function(node) {
node._walk(visitor); node._walk(visitor);
}); });
@@ -601,7 +598,7 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
var AST_Dot = DEFNODE("Dot", null, { var AST_Dot = DEFNODE("Dot", null, {
$documentation: "A dotted property access expression", $documentation: "A dotted property access expression",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
}); });
} }
@@ -610,7 +607,7 @@ var AST_Dot = DEFNODE("Dot", null, {
var AST_Sub = DEFNODE("Sub", null, { var AST_Sub = DEFNODE("Sub", null, {
$documentation: "Index-style property access, i.e. `a[\"foo\"]`", $documentation: "Index-style property access, i.e. `a[\"foo\"]`",
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
this.property._walk(visitor); this.property._walk(visitor);
}); });
@@ -624,7 +621,7 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
expression: "[AST_Node] expression that this unary operator applies to" expression: "[AST_Node] expression that this unary operator applies to"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.expression._walk(visitor); this.expression._walk(visitor);
}); });
} }
@@ -646,7 +643,7 @@ var AST_Binary = DEFNODE("Binary", "operator left right", {
right: "[AST_Node] right-hand side expression" right: "[AST_Node] right-hand side expression"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.left._walk(visitor); this.left._walk(visitor);
this.right._walk(visitor); this.right._walk(visitor);
}); });
@@ -661,7 +658,7 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative",
alternative: "[AST_Node]" alternative: "[AST_Node]"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.condition._walk(visitor); this.condition._walk(visitor);
this.consequent._walk(visitor); this.consequent._walk(visitor);
this.alternative._walk(visitor); this.alternative._walk(visitor);
@@ -681,11 +678,10 @@ var AST_Array = DEFNODE("Array", "elements", {
elements: "[AST_Node*] array of elements" elements: "[AST_Node*] array of elements"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
var elements = this.elements; this.elements.forEach(function(element) {
for (var i = 0, len = elements.length; i < len; i++) { element._walk(visitor);
elements[i]._walk(visitor); });
}
}); });
} }
}); });
@@ -696,11 +692,10 @@ var AST_Object = DEFNODE("Object", "properties", {
properties: "[AST_ObjectProperty*] array of properties" properties: "[AST_ObjectProperty*] array of properties"
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
var properties = this.properties; this.properties.forEach(function(prop) {
for (var i = 0, len = properties.length; i < len; i++) { prop._walk(visitor);
properties[i]._walk(visitor); });
}
}); });
} }
}); });
@@ -712,7 +707,7 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor." value: "[AST_Node] property value. For getters and setters this is an AST_Accessor."
}, },
_walk: function(visitor) { _walk: function(visitor) {
return visitor._visit(this, function(){ return visitor._visit(this, function() {
this.value._walk(visitor); this.value._walk(visitor);
}); });
} }
@@ -839,12 +834,12 @@ var AST_NaN = DEFNODE("NaN", null, {
var AST_Undefined = DEFNODE("Undefined", null, { var AST_Undefined = DEFNODE("Undefined", null, {
$documentation: "The `undefined` value", $documentation: "The `undefined` value",
value: (function(){}()) value: function(){}()
}, AST_Atom); }, AST_Atom);
var AST_Hole = DEFNODE("Hole", null, { var AST_Hole = DEFNODE("Hole", null, {
$documentation: "A hole in an array", $documentation: "A hole in an array",
value: (function(){}()) value: function(){}()
}, AST_Atom); }, AST_Atom);
var AST_Infinity = DEFNODE("Infinity", null, { var AST_Infinity = DEFNODE("Infinity", null, {
@@ -872,11 +867,11 @@ function TreeWalker(callback) {
this.visit = callback; this.visit = callback;
this.stack = []; this.stack = [];
this.directives = Object.create(null); this.directives = Object.create(null);
}; }
TreeWalker.prototype = { TreeWalker.prototype = {
_visit: function(node, descend) { _visit: function(node, descend) {
this.push(node); this.push(node);
var ret = this.visit(node, descend ? function(){ var ret = this.visit(node, descend ? function() {
descend.call(node); descend.call(node);
} : noop); } : noop);
if (!ret && descend) { if (!ret && descend) {

File diff suppressed because it is too large Load Diff

View File

@@ -43,11 +43,9 @@
"use strict"; "use strict";
(function(){ (function() {
function normalize_directives(body) {
var normalize_directives = function(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({
@@ -59,9 +57,8 @@
in_directive = false; in_directive = false;
} }
} }
return body; return body;
}; }
var MOZ_TO_ME = { var MOZ_TO_ME = {
Program: function(M) { Program: function(M) {
@@ -129,7 +126,7 @@
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);
}) })
}); });
@@ -138,7 +135,7 @@
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) {
prop.type = "Property"; prop.type = "Property";
return from_moz(prop) return from_moz(prop)
}) })
@@ -480,7 +477,7 @@
endpos : range ? range[0] : moznode.start, endpos : range ? range[0] : moznode.start,
raw : raw_token(moznode), raw : raw_token(moznode),
}); });
}; }
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;
@@ -495,7 +492,7 @@
endpos : range ? range[1] : moznode.end, endpos : range ? range[1] : moznode.end,
raw : raw_token(moznode), raw : raw_token(moznode),
}); });
}; }
function map(moztype, mytype, propmap) { function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
@@ -507,7 +504,7 @@
me_to_moz += "return {\n" + me_to_moz += "return {\n" +
"type: " + JSON.stringify(moztype); "type: " + JSON.stringify(moztype);
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){ if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
if (!m) throw new Error("Can't understand property map: " + prop); if (!m) throw new Error("Can't understand property map: " + prop);
var moz = m[1], how = m[2], my = m[3]; var moz = m[1], how = m[2], my = m[3];
@@ -550,7 +547,7 @@
); );
MOZ_TO_ME[moztype] = moz_to_me; MOZ_TO_ME[moztype] = moz_to_me;
def_to_moz(mytype, me_to_moz); def_to_moz(mytype, me_to_moz);
}; }
var FROM_MOZ_STACK = null; var FROM_MOZ_STACK = null;
@@ -559,9 +556,9 @@
var ret = node != null ? MOZ_TO_ME[node.type](node) : null; var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
FROM_MOZ_STACK.pop(); FROM_MOZ_STACK.pop();
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);
@@ -600,24 +597,24 @@
} }
} }
return moznode; return moznode;
}; }
function def_to_moz(mytype, handler) { function def_to_moz(mytype, handler) {
mytype.DEFMETHOD("to_mozilla_ast", function() { mytype.DEFMETHOD("to_mozilla_ast", function() {
return set_moz_loc(this, handler(this)); return set_moz_loc(this, handler(this));
}); });
}; }
function to_moz(node) { function to_moz(node) {
return node != null ? node.to_mozilla_ast() : null; return node != null ? node.to_mozilla_ast() : null;
}; }
function to_moz_block(node) { function to_moz_block(node) {
return { return {
type: "BlockStatement", type: "BlockStatement",
body: node.body.map(to_moz) body: node.body.map(to_moz)
}; };
}; }
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);
@@ -628,5 +625,5 @@
type: type, type: type,
body: body body: body
}; };
}; }
})(); })();

View File

@@ -137,7 +137,7 @@ function OutputStream(options) {
function make_string(str, quote) { function make_string(str, quote) {
var dq = 0, sq = 0; var dq = 0, sq = 0;
str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g, str = str.replace(/[\\\b\f\n\r\v\t\x22\x27\u2028\u2029\0\ufeff]/g,
function(s, i){ function(s, i) {
switch (s) { switch (s) {
case '"': ++dq; return '"'; case '"': ++dq; return '"';
case "'": ++sq; return "'"; case "'": ++sq; return "'";
@@ -408,7 +408,7 @@ function OutputStream(options) {
var ret; var ret;
print("{"); print("{");
newline(); newline();
with_indent(next_indent(), function(){ with_indent(next_indent(), function() {
ret = cont(); ret = cont();
}); });
indent(); indent();
@@ -631,7 +631,7 @@ function OutputStream(options) {
/* -----[ code generators ]----- */ /* -----[ code generators ]----- */
(function(){ (function() {
/* -----[ utils ]----- */ /* -----[ utils ]----- */
@@ -643,7 +643,7 @@ 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;
@@ -670,7 +670,7 @@ function OutputStream(options) {
}); });
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();
@@ -680,7 +680,7 @@ function OutputStream(options) {
function PARENS(nodetype, func) { function PARENS(nodetype, func) {
if (Array.isArray(nodetype)) { if (Array.isArray(nodetype)) {
nodetype.forEach(function(nodetype){ nodetype.forEach(function(nodetype) {
PARENS(nodetype, func); PARENS(nodetype, func);
}); });
} else { } else {
@@ -692,7 +692,7 @@ function OutputStream(options) {
// 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;
} }
@@ -714,17 +714,17 @@ 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)
@@ -738,7 +738,7 @@ function OutputStream(options) {
; ;
}); });
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)
@@ -761,7 +761,7 @@ 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)
@@ -782,7 +782,7 @@ 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;
@@ -796,7 +796,7 @@ function OutputStream(options) {
&& 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"]()
@@ -804,7 +804,7 @@ function OutputStream(options) {
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();
@@ -814,7 +814,7 @@ 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)
@@ -835,11 +835,11 @@ function OutputStream(options) {
/* -----[ 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();
}); });
@@ -849,7 +849,7 @@ function OutputStream(options) {
function display_body(body, is_toplevel, output, allow_directives) { function display_body(body, is_toplevel, output, allow_directives) {
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)
@@ -874,24 +874,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,37 +909,37 @@ 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);
output.space(); output.space();
output.print("while"); output.print("while");
output.space(); output.space();
output.with_parens(function(){ output.with_parens(function() {
self.condition.print(output); self.condition.print(output);
}); });
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() {
self.condition.print(output); self.condition.print(output);
}); });
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);
@@ -965,10 +965,10 @@ 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() {
self.init.print(output); self.init.print(output);
output.space(); output.space();
output.print("in"); output.print("in");
@@ -978,10 +978,10 @@ 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() {
self.expression.print(output); self.expression.print(output);
}); });
output.space(); output.space();
@@ -989,7 +989,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");
@@ -998,8 +998,8 @@ function OutputStream(options) {
output.space(); output.space();
self.name.print(output); self.name.print(output);
} }
output.with_parens(function(){ output.with_parens(function() {
self.argnames.forEach(function(arg, i){ self.argnames.forEach(function(arg, i) {
if (i) output.comma(); if (i) output.comma();
arg.print(output); arg.print(output);
}); });
@@ -1007,40 +1007,31 @@ 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);
}); });
/* -----[ exits ]----- */ /* -----[ jumps ]----- */
AST_Exit.DEFMETHOD("_do_print", function(output, kind){ function print_jump(output, kind, target) {
output.print(kind); output.print(kind);
if (this.value) { if (target) {
output.space(); output.space();
this.value.print(output); target.print(output);
} }
output.semicolon(); output.semicolon();
}); }
DEFPRINT(AST_Return, function(self, output){
self._do_print(output, "return");
});
DEFPRINT(AST_Throw, function(self, output){
self._do_print(output, "throw");
});
/* -----[ loop control ]----- */ DEFPRINT(AST_Return, function(self, output) {
AST_LoopControl.DEFMETHOD("_do_print", function(output, kind){ print_jump(output, "return", self.value);
output.print(kind);
if (this.label) {
output.space();
this.label.print(output);
}
output.semicolon();
}); });
DEFPRINT(AST_Break, function(self, output){ DEFPRINT(AST_Throw, function(self, output) {
self._do_print(output, "break"); print_jump(output, "throw", self.value);
}); });
DEFPRINT(AST_Continue, function(self, output){ DEFPRINT(AST_Break, function(self, output) {
self._do_print(output, "continue"); print_jump(output, "break", self.label);
});
DEFPRINT(AST_Continue, function(self, output) {
print_jump(output, "continue", self.label);
}); });
/* -----[ if ]----- */ /* -----[ if ]----- */
@@ -1072,10 +1063,10 @@ function OutputStream(options) {
} }
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() {
self.condition.print(output); self.condition.print(output);
}); });
output.space(); output.space();
@@ -1094,17 +1085,17 @@ 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() {
self.expression.print(output); self.expression.print(output);
}); });
output.space(); output.space();
var last = self.body.length - 1; var last = self.body.length - 1;
if (last < 0) print_braced_empty(self, output); if (last < 0) print_braced_empty(self, output);
else output.with_block(function(){ else output.with_block(function() {
self.body.forEach(function(branch, i){ self.body.forEach(function(branch, i) {
output.indent(true); output.indent(true);
branch.print(output); branch.print(output);
if (i < last && branch.body.length > 0) if (i < last && branch.body.length > 0)
@@ -1112,19 +1103,19 @@ 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();
stmt.print(output); stmt.print(output);
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);
@@ -1133,7 +1124,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);
@@ -1146,37 +1137,30 @@ 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() {
self.argname.print(output); self.argname.print(output);
}); });
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);
}); });
/* -----[ var/const ]----- */ DEFPRINT(AST_Var, function(self, output) {
AST_Definitions.DEFMETHOD("_do_print", function(output, kind){ output.print("var");
output.print(kind);
output.space(); output.space();
this.definitions.forEach(function(def, i){ self.definitions.forEach(function(def, i) {
if (i) output.comma(); if (i) output.comma();
def.print(output); def.print(output);
}); });
var p = output.parent(); var p = output.parent();
var in_for = p instanceof AST_For || p instanceof AST_ForIn; if (p.init !== self || !(p instanceof AST_For || p instanceof AST_ForIn)) output.semicolon();
var avoid_semicolon = in_for && p.init === this;
if (!avoid_semicolon)
output.semicolon();
});
DEFPRINT(AST_Var, function(self, output){
self._do_print(output, "var");
}); });
function parenthesize_for_noin(node, output, noin) { function parenthesize_for_noin(node, output, noin) {
@@ -1193,7 +1177,7 @@ 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();
@@ -1206,28 +1190,27 @@ function OutputStream(options) {
}); });
/* -----[ 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() {
self.args.forEach(function(expr, i){ self.args.forEach(function(expr, i) {
if (i) output.comma(); if (i) output.comma();
expr.print(output); expr.print(output);
}); });
}); });
}); });
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) {
AST_Sequence.DEFMETHOD("_do_print", function(output){ self.expressions.forEach(function(node, index) {
this.expressions.forEach(function(node, index) {
if (index > 0) { if (index > 0) {
output.comma(); output.comma();
if (output.should_break()) { if (output.should_break()) {
@@ -1238,18 +1221,7 @@ function OutputStream(options) {
node.print(output); node.print(output);
}); });
}); });
DEFPRINT(AST_Sequence, function(self, output){ DEFPRINT(AST_Dot, function(self, output) {
self._do_print(output);
// var p = output.parent();
// if (p instanceof AST_Statement) {
// output.with_indent(output.next_indent(), function(){
// self._do_print(output);
// });
// } else {
// self._do_print(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;
@@ -1270,13 +1242,13 @@ 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)
@@ -1287,11 +1259,11 @@ function OutputStream(options) {
} }
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] == ">" /* ">>" ">>>" ">" ">=" */
@@ -1317,7 +1289,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("?");
@@ -1329,11 +1301,11 @@ 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();
a.forEach(function(exp, i){ a.forEach(function(exp, i) {
if (i) output.comma(); if (i) output.comma();
exp.print(output); exp.print(output);
// 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
@@ -1345,9 +1317,9 @@ function OutputStream(options) {
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) {
output.print(","); output.print(",");
output.newline(); output.newline();
@@ -1376,7 +1348,7 @@ 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);
@@ -1387,27 +1359,27 @@ function OutputStream(options) {
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 {
@@ -1415,7 +1387,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) {
@@ -1487,7 +1459,7 @@ function OutputStream(options) {
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();
stmt.print(output); stmt.print(output);
output.newline(); output.newline();

View File

@@ -130,7 +130,7 @@ function is_letter(code) {
return (code >= 97 && code <= 122) return (code >= 97 && code <= 122)
|| (code >= 65 && code <= 90) || (code >= 65 && code <= 90)
|| (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code))); || (code >= 0xaa && UNICODE.letter.test(String.fromCharCode(code)));
}; }
function is_surrogate_pair_head(code) { function is_surrogate_pair_head(code) {
if (typeof code == "string") if (typeof code == "string")
@@ -146,11 +146,11 @@ function is_surrogate_pair_tail(code) {
function is_digit(code) { function is_digit(code) {
return code >= 48 && code <= 57; return code >= 48 && code <= 57;
}; }
function is_alphanumeric_char(code) { function is_alphanumeric_char(code) {
return is_digit(code) || is_letter(code); return is_digit(code) || is_letter(code);
}; }
function is_unicode_digit(code) { function is_unicode_digit(code) {
return UNICODE.digit.test(String.fromCharCode(code)); return UNICODE.digit.test(String.fromCharCode(code));
@@ -158,19 +158,19 @@ function is_unicode_digit(code) {
function is_unicode_combining_mark(ch) { function is_unicode_combining_mark(ch) {
return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch); return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
}; }
function is_unicode_connector_punctuation(ch) { function is_unicode_connector_punctuation(ch) {
return UNICODE.connector_punctuation.test(ch); return UNICODE.connector_punctuation.test(ch);
}; }
function is_identifier(name) { function is_identifier(name) {
return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name); return !RESERVED_WORDS[name] && /^[a-z_$][a-z0-9_$]*$/i.test(name);
}; }
function is_identifier_start(code) { function is_identifier_start(code) {
return code == 36 || code == 95 || is_letter(code); return code == 36 || code == 95 || is_letter(code);
}; }
function is_identifier_char(ch) { function is_identifier_char(ch) {
var code = ch.charCodeAt(0); var code = ch.charCodeAt(0);
@@ -182,11 +182,11 @@ function is_identifier_char(ch) {
|| is_unicode_connector_punctuation(ch) || is_unicode_connector_punctuation(ch)
|| is_unicode_digit(code) || is_unicode_digit(code)
; ;
}; }
function is_identifier_string(str){ function is_identifier_string(str) {
return /^[a-z_$][a-z0-9_$]*$/i.test(str); return /^[a-z_$][a-z0-9_$]*$/i.test(str);
}; }
function parse_js_number(num) { function parse_js_number(num) {
if (RE_HEX_NUMBER.test(num)) { if (RE_HEX_NUMBER.test(num)) {
@@ -197,7 +197,7 @@ function parse_js_number(num) {
var val = parseFloat(num); var val = parseFloat(num);
if (val == num) return val; if (val == num) return val;
} }
}; }
function JS_Parse_Error(message, filename, line, col, pos) { function JS_Parse_Error(message, filename, line, col, pos) {
this.message = message; this.message = message;
@@ -205,7 +205,7 @@ function JS_Parse_Error(message, filename, line, col, pos) {
this.line = line; this.line = line;
this.col = col; this.col = col;
this.pos = pos; this.pos = pos;
}; }
JS_Parse_Error.prototype = Object.create(Error.prototype); JS_Parse_Error.prototype = Object.create(Error.prototype);
JS_Parse_Error.prototype.constructor = JS_Parse_Error; JS_Parse_Error.prototype.constructor = JS_Parse_Error;
JS_Parse_Error.prototype.name = "SyntaxError"; JS_Parse_Error.prototype.name = "SyntaxError";
@@ -213,11 +213,11 @@ configure_error_stack(JS_Parse_Error);
function js_error(message, filename, line, col, pos) { function js_error(message, filename, line, col, pos) {
throw new JS_Parse_Error(message, filename, line, col, pos); throw new JS_Parse_Error(message, filename, line, col, pos);
}; }
function is_token(token, type, val) { function is_token(token, type, val) {
return token.type == type && (val == null || token.value == val); return token.type == type && (val == null || token.value == val);
}; }
var EX_EOF = {}; var EX_EOF = {};
@@ -239,7 +239,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
directive_stack : [] directive_stack : []
}; };
function peek() { return S.text.charAt(S.pos); }; function peek() {
return S.text.charAt(S.pos);
}
function next(signal_eof, in_string) { function next(signal_eof, in_string) {
var ch = S.text.charAt(S.pos++); var ch = S.text.charAt(S.pos++);
@@ -258,15 +260,15 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
++S.col; ++S.col;
} }
return ch; return ch;
}; }
function forward(i) { function forward(i) {
while (i-- > 0) next(); while (i-- > 0) next();
}; }
function looking_at(str) { function looking_at(str) {
return S.text.substr(S.pos, str.length) == str; return S.text.substr(S.pos, str.length) == str;
}; }
function find_eol() { function find_eol() {
var text = S.text; var text = S.text;
@@ -276,19 +278,19 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
return i; return i;
} }
return -1; return -1;
}; }
function find(what, signal_eof) { function find(what, signal_eof) {
var pos = S.text.indexOf(what, S.pos); var pos = S.text.indexOf(what, S.pos);
if (signal_eof && pos == -1) throw EX_EOF; if (signal_eof && pos == -1) throw EX_EOF;
return pos; return pos;
}; }
function start_token() { function start_token() {
S.tokline = S.line; S.tokline = S.line;
S.tokcol = S.col; S.tokcol = S.col;
S.tokpos = S.pos; S.tokpos = S.pos;
}; }
var prev_was_dot = false; var prev_was_dot = false;
function token(type, value, is_comment) { function token(type, value, is_comment) {
@@ -321,27 +323,27 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} }
S.newline_before = false; S.newline_before = false;
return new AST_Token(ret); return new AST_Token(ret);
}; }
function skip_whitespace() { function skip_whitespace() {
while (WHITESPACE_CHARS[peek()]) while (WHITESPACE_CHARS[peek()])
next(); next();
}; }
function read_while(pred) { function read_while(pred) {
var ret = "", ch, i = 0; var ret = "", ch, i = 0;
while ((ch = peek()) && pred(ch, i++)) while ((ch = peek()) && pred(ch, i++))
ret += next(); ret += next();
return ret; return ret;
}; }
function parse_error(err) { function parse_error(err) {
js_error(err, filename, S.tokline, S.tokcol, S.tokpos); js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
}; }
function read_num(prefix) { function read_num(prefix) {
var has_e = false, after_e = false, has_x = false, has_dot = prefix == "."; var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
var num = read_while(function(ch, i){ var num = read_while(function(ch, i) {
var code = ch.charCodeAt(0); var code = ch.charCodeAt(0);
switch (code) { switch (code) {
case 120: case 88: // xX case 120: case 88: // xX
@@ -367,7 +369,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} else { } else {
parse_error("Invalid syntax: " + num); parse_error("Invalid syntax: " + num);
} }
}; }
function read_escaped_char(in_string) { function read_escaped_char(in_string) {
var ch = next(true, in_string); var ch = next(true, in_string);
@@ -390,7 +392,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
if (ch >= "0" && ch <= "7") if (ch >= "0" && ch <= "7")
return read_octal_escape_sequence(ch); return read_octal_escape_sequence(ch);
return ch; return ch;
}; }
function read_octal_escape_sequence(ch) { function read_octal_escape_sequence(ch) {
// Read // Read
@@ -417,9 +419,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
num = (num << 4) | digit; num = (num << 4) | digit;
} }
return num; return num;
}; }
var read_string = with_eof_error("Unterminated string constant", function(quote_char){ var read_string = with_eof_error("Unterminated string constant", function(quote_char) {
var quote = next(), ret = ""; var quote = next(), ret = "";
for (;;) { for (;;) {
var ch = next(true, true); var ch = next(true, true);
@@ -447,9 +449,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
S.comments_before.push(token(type, ret, true)); S.comments_before.push(token(type, ret, true));
S.regex_allowed = regex_allowed; S.regex_allowed = regex_allowed;
return next_token; return next_token;
}; }
var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function(){ var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
var regex_allowed = S.regex_allowed; var regex_allowed = S.regex_allowed;
var i = find("*/", true); var i = find("*/", true);
var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n'); var text = S.text.substring(S.pos, i).replace(/\r\n|\r|\u2028|\u2029/g, '\n');
@@ -481,7 +483,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1); name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
} }
return name; return name;
}; }
var read_regexp = with_eof_error("Unterminated regular expression", function(source) { var read_regexp = with_eof_error("Unterminated regular expression", function(source) {
var prev_backslash = false, ch, in_class = false; var prev_backslash = false, ch, in_class = false;
@@ -523,9 +525,9 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} else { } else {
return op; return op;
} }
}; }
return token("operator", grow(prefix || next())); return token("operator", grow(prefix || next()));
}; }
function handle_slash() { function handle_slash() {
next(); next();
@@ -538,14 +540,14 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
return skip_multiline_comment(); return skip_multiline_comment();
} }
return S.regex_allowed ? read_regexp("") : read_operator("/"); return S.regex_allowed ? read_regexp("") : read_operator("/");
}; }
function handle_dot() { function handle_dot() {
next(); next();
return is_digit(peek().charCodeAt(0)) return is_digit(peek().charCodeAt(0))
? read_num(".") ? read_num(".")
: token("punc", "."); : token("punc", ".");
}; }
function read_word() { function read_word() {
var word = read_name(); var word = read_name();
@@ -554,7 +556,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
: !KEYWORDS[word] ? token("name", word) : !KEYWORDS[word] ? token("name", word)
: OPERATORS[word] ? token("operator", word) : OPERATORS[word] ? token("operator", word)
: token("keyword", word); : token("keyword", word);
}; }
function with_eof_error(eof_error, cont) { function with_eof_error(eof_error, cont) {
return function(x) { return function(x) {
@@ -565,7 +567,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
else throw ex; else throw ex;
} }
}; };
}; }
function next_token(force_regexp) { function next_token(force_regexp) {
if (force_regexp != null) if (force_regexp != null)
@@ -609,7 +611,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
break; break;
} }
parse_error("Unexpected character '" + ch + "'"); parse_error("Unexpected character '" + ch + "'");
}; }
next_token.context = function(nc) { next_token.context = function(nc) {
if (nc) S = nc; if (nc) S = nc;
@@ -645,8 +647,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
} }
return next_token; return next_token;
}
};
/* -----[ Parser (constants) ]----- */ /* -----[ Parser (constants) ]----- */
@@ -666,7 +667,7 @@ var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]); var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
var PRECEDENCE = (function(a, ret){ var PRECEDENCE = function(a, ret) {
for (var i = 0; i < a.length; ++i) { for (var i = 0; i < a.length; ++i) {
var b = a[i]; var b = a[i];
for (var j = 0; j < b.length; ++j) { for (var j = 0; j < b.length; ++j) {
@@ -674,8 +675,7 @@ var PRECEDENCE = (function(a, ret){
} }
} }
return ret; return ret;
})( }([
[
["||"], ["||"],
["&&"], ["&&"],
["|"], ["|"],
@@ -686,16 +686,13 @@ var PRECEDENCE = (function(a, ret){
[">>", "<<", ">>>"], [">>", "<<", ">>>"],
["+", "-"], ["+", "-"],
["*", "/", "%"] ["*", "/", "%"]
], ], {});
{}
);
var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]); var ATOMIC_START_TOKEN = makePredicate([ "atom", "num", "string", "regexp", "name" ]);
/* -----[ Parser ]----- */ /* -----[ Parser ]----- */
function parse($TEXT, options) { function parse($TEXT, options) {
options = defaults(options, { options = defaults(options, {
bare_returns : false, bare_returns : false,
expression : false, expression : false,
@@ -724,9 +721,11 @@ function parse($TEXT, options) {
function is(type, value) { function is(type, value) {
return is_token(S.token, type, value); return is_token(S.token, type, value);
}; }
function peek() { return S.peeked || (S.peeked = S.input()); }; function peek() {
return S.peeked || (S.peeked = S.input());
}
function next() { function next() {
S.prev = S.token; S.prev = S.token;
@@ -740,11 +739,11 @@ function parse($TEXT, options) {
S.token.type == "string" || is("punc", ";") S.token.type == "string" || is("punc", ";")
); );
return S.token; return S.token;
}; }
function prev() { function prev() {
return S.prev; return S.prev;
}; }
function croak(msg, line, col, pos) { function croak(msg, line, col, pos) {
var ctx = S.input.context(); var ctx = S.input.context();
@@ -753,26 +752,28 @@ function parse($TEXT, options) {
line != null ? line : ctx.tokline, line != null ? line : ctx.tokline,
col != null ? col : ctx.tokcol, col != null ? col : ctx.tokcol,
pos != null ? pos : ctx.tokpos); pos != null ? pos : ctx.tokpos);
}; }
function token_error(token, msg) { function token_error(token, msg) {
croak(msg, token.line, token.col); croak(msg, token.line, token.col);
}; }
function unexpected(token) { function unexpected(token) {
if (token == null) if (token == null)
token = S.token; token = S.token;
token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")"); token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
}; }
function expect_token(type, val) { function expect_token(type, val) {
if (is(type, val)) { if (is(type, val)) {
return next(); return next();
} }
token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»"); token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
}; }
function expect(punc) { return expect_token("punc", punc); }; function expect(punc) {
return expect_token("punc", punc);
}
function has_newline_before(token) { function has_newline_before(token) {
return token.nlb || !all(token.comments_before, function(comment) { return token.nlb || !all(token.comments_before, function(comment) {
@@ -783,19 +784,19 @@ function parse($TEXT, options) {
function can_insert_semicolon() { function can_insert_semicolon() {
return !options.strict return !options.strict
&& (is("eof") || is("punc", "}") || has_newline_before(S.token)); && (is("eof") || is("punc", "}") || has_newline_before(S.token));
}; }
function semicolon(optional) { function semicolon(optional) {
if (is("punc", ";")) next(); if (is("punc", ";")) next();
else if (!optional && !can_insert_semicolon()) unexpected(); else if (!optional && !can_insert_semicolon()) unexpected();
}; }
function parenthesised() { function parenthesised() {
expect("("); expect("(");
var exp = expression(true); var exp = expression(true);
expect(")"); expect(")");
return exp; return exp;
}; }
function embed_tokens(parser) { function embed_tokens(parser) {
return function() { return function() {
@@ -806,14 +807,14 @@ function parse($TEXT, options) {
expr.end = end; expr.end = end;
return expr; return expr;
}; };
}; }
function handle_regexp() { function handle_regexp() {
if (is("operator", "/") || is("operator", "/=")) { if (is("operator", "/") || is("operator", "/=")) {
S.peeked = null; S.peeked = null;
S.token = S.input(S.token.value.substr(1)); // force regexp S.token = S.input(S.token.value.substr(1)); // force regexp
} }
}; }
var statement = embed_tokens(function(strict_defun) { var statement = embed_tokens(function(strict_defun) {
handle_regexp(); handle_regexp();
@@ -986,7 +987,7 @@ function parse($TEXT, options) {
// 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.",
@@ -995,11 +996,11 @@ function parse($TEXT, options) {
}); });
} }
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;
@@ -1007,18 +1008,17 @@ function parse($TEXT, options) {
label = as_symbol(AST_LabelRef, true); label = as_symbol(AST_LabelRef, true);
} }
if (label != null) { if (label != null) {
ldef = find_if(function(l){ return l.name == label.name }, S.labels); ldef = find_if(function(l) {
if (!ldef) return l.name == label.name;
croak("Undefined label " + label.name); }, S.labels);
if (!ldef) croak("Undefined label " + label.name);
label.thedef = ldef; label.thedef = ldef;
} } else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch");
else if (S.in_loop == 0)
croak(type.TYPE + " not inside a loop or switch");
semicolon(); semicolon();
var stat = new type({ label: label }); var stat = new type({ label: label });
if (ldef) ldef.references.push(stat); if (ldef) ldef.references.push(stat);
return stat; return stat;
}; }
function for_() { function for_() {
expect("("); expect("(");
@@ -1039,7 +1039,7 @@ function parse($TEXT, options) {
} }
} }
return regular_for(init); return regular_for(init);
}; }
function regular_for(init) { function regular_for(init) {
expect(";"); expect(";");
@@ -1053,7 +1053,7 @@ function parse($TEXT, options) {
step : step, step : step,
body : in_loop(statement) body : in_loop(statement)
}); });
}; }
function for_in(init) { function for_in(init) {
var obj = expression(true); var obj = expression(true);
@@ -1063,7 +1063,7 @@ function parse($TEXT, options) {
object : obj, object : obj,
body : in_loop(statement) body : in_loop(statement)
}); });
}; }
var function_ = function(ctor) { var function_ = function(ctor) {
var in_statement = ctor === AST_Defun; var in_statement = ctor === AST_Defun;
@@ -1113,7 +1113,7 @@ function parse($TEXT, options) {
body : body, body : body,
alternative : belse alternative : belse
}); });
}; }
function block_(strict_defun) { function block_(strict_defun) {
expect("{"); expect("{");
@@ -1124,7 +1124,7 @@ function parse($TEXT, options) {
} }
next(); next();
return a; return a;
}; }
function switch_body_() { function switch_body_() {
expect("{"); expect("{");
@@ -1159,7 +1159,7 @@ function parse($TEXT, options) {
if (branch) branch.end = prev(); if (branch) branch.end = prev();
next(); next();
return a; return a;
}; }
function try_() { function try_() {
var body = block_(), bcatch = null, bfinally = null; var body = block_(), bcatch = null, bfinally = null;
@@ -1192,7 +1192,7 @@ function parse($TEXT, options) {
bcatch : bcatch, bcatch : bcatch,
bfinally : bfinally bfinally : bfinally
}); });
}; }
function vardefs(no_in) { function vardefs(no_in) {
var a = []; var a = [];
@@ -1208,7 +1208,7 @@ function parse($TEXT, options) {
next(); next();
} }
return a; return a;
}; }
var var_ = function(no_in) { var var_ = function(no_in) {
return new AST_Var({ return new AST_Var({
@@ -1274,7 +1274,7 @@ function parse($TEXT, options) {
} }
next(); next();
return ret; return ret;
}; }
var expr_atom = function(allow_calls) { var expr_atom = function(allow_calls) {
if (is("operator", "new")) { if (is("operator", "new")) {
@@ -1340,7 +1340,7 @@ function parse($TEXT, options) {
} }
next(); next();
return a; return a;
}; }
var array_ = embed_tokens(function() { var array_ = embed_tokens(function() {
expect("["); expect("[");
@@ -1417,14 +1417,14 @@ function parse($TEXT, options) {
default: default:
unexpected(); unexpected();
} }
}; }
function as_name() { function as_name() {
var tmp = S.token; var tmp = S.token;
if (tmp.type != "name") unexpected(); if (tmp.type != "name") unexpected();
next(); next();
return tmp.value; return tmp.value;
}; }
function _make_symbol(type) { function _make_symbol(type) {
var name = S.token.value; var name = S.token.value;
@@ -1433,7 +1433,7 @@ function parse($TEXT, options) {
start : S.token, start : S.token,
end : S.token end : S.token
}); });
}; }
function strict_verify_symbol(sym) { function strict_verify_symbol(sym) {
if (sym.name == "arguments" || sym.name == "eval") if (sym.name == "arguments" || sym.name == "eval")
@@ -1451,7 +1451,7 @@ function parse($TEXT, options) {
} }
next(); next();
return sym; return sym;
}; }
function mark_pure(call) { function mark_pure(call) {
var start = call.start; var start = call.start;
@@ -1536,7 +1536,7 @@ function parse($TEXT, options) {
break; break;
} }
return new ctor({ operator: op, expression: expr }); return new ctor({ operator: op, expression: expr });
}; }
var expr_op = function(left, min_prec, no_in) { var expr_op = function(left, min_prec, no_in) {
var op = is("operator") ? S.token.value : null; var op = is("operator") ? S.token.value : null;
@@ -1558,7 +1558,7 @@ function parse($TEXT, options) {
function expr_ops(no_in) { function expr_ops(no_in) {
return expr_op(maybe_unary(true), 0, no_in); return expr_op(maybe_unary(true), 0, no_in);
}; }
var maybe_conditional = function(no_in) { var maybe_conditional = function(no_in) {
var start = S.token; var start = S.token;
@@ -1580,7 +1580,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) {
var start = S.token; var start = S.token;
@@ -1622,13 +1622,13 @@ function parse($TEXT, options) {
var ret = cont(); var ret = cont();
--S.in_loop; --S.in_loop;
return ret; return ret;
}; }
if (options.expression) { if (options.expression) {
return expression(true); return expression(true);
} }
return (function(){ return function() {
var start = S.token; var start = S.token;
var body = []; var body = [];
S.input.push_directives_stack(); S.input.push_directives_stack();
@@ -1644,6 +1644,5 @@ function parse($TEXT, options) {
toplevel = new AST_Toplevel({ start: start, body: body, end: end }); toplevel = new AST_Toplevel({ start: start, body: body, end: end });
} }
return toplevel; return toplevel;
})(); }();
}
};

View File

@@ -56,7 +56,7 @@ function find_builtins(reserved) {
[ Object, Array, Function, Number, [ Object, Array, Function, Number,
String, Boolean, Error, Math, String, Boolean, Error, Math,
Date, RegExp Date, RegExp
].forEach(function(ctor){ ].forEach(function(ctor) {
Object.getOwnPropertyNames(ctor).map(add); Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) { if (ctor.prototype) {
Object.getOwnPropertyNames(ctor.prototype).map(add); Object.getOwnPropertyNames(ctor.prototype).map(add);
@@ -136,7 +136,7 @@ function mangle_properties(ast, options) {
var unmangleable = []; var unmangleable = [];
// 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);
} }
@@ -157,7 +157,7 @@ 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);
} }
@@ -234,7 +234,7 @@ 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]);

View File

@@ -91,7 +91,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,
@@ -101,7 +101,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
var self = this; var self = this;
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);
@@ -132,10 +132,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
node.thedef = node; node.thedef = node;
node.references = []; node.references = [];
} }
if (node instanceof AST_SymbolLambda) { if (node instanceof AST_SymbolDefun || options.ie8 && node instanceof AST_SymbolLambda) {
defun.def_function(node, node.name == "arguments" ? undefined : defun);
}
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
@@ -143,6 +140,9 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
// 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_SymbolLambda) {
defun.def_function(node, node.name == "arguments" ? undefined : 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) {
@@ -162,7 +162,7 @@ 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;
@@ -217,7 +217,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,7 +230,7 @@ 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
@@ -240,7 +240,7 @@ 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({
@@ -270,20 +270,20 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
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);
@@ -349,9 +349,6 @@ 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) {
names_in_use(scope.parent_scope, options)[name] = true;
}
return name; return name;
} }
@@ -390,7 +387,7 @@ 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
@@ -407,7 +404,7 @@ 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;
@@ -520,7 +517,7 @@ 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 {

View File

@@ -46,16 +46,15 @@
// 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, {
file : null, file: null,
root : null, root: null,
orig : null, orig: null,
orig_line_diff: 0,
orig_line_diff : 0, dest_line_diff: 0,
dest_line_diff : 0, }, true);
});
var generator = new MOZ_SourceMap.SourceMapGenerator({ var generator = new MOZ_SourceMap.SourceMapGenerator({
file : options.file, file: options.file,
sourceRoot : options.root sourceRoot: options.root
}); });
var maps = options.orig && Object.create(null); var maps = options.orig && Object.create(null);
if (maps) for (var source in options.orig) { if (maps) for (var source in options.orig) {
@@ -68,8 +67,8 @@ function SourceMap(options) {
} }
maps[source] = map; maps[source] = map;
} }
return {
function add(source, gen_line, gen_col, orig_line, orig_col, name) { add: function(source, gen_line, gen_col, orig_line, orig_col, name) {
var map = maps && maps[source]; var map = maps && maps[source];
if (map) { if (map) {
var info = map.originalPositionFor({ var info = map.originalPositionFor({
@@ -83,15 +82,23 @@ function SourceMap(options) {
name = info.name || name; name = info.name || name;
} }
generator.addMapping({ generator.addMapping({
generated : { line: gen_line + options.dest_line_diff, column: gen_col }, name: name,
original : { line: orig_line + options.orig_line_diff, column: orig_col }, source: source,
source : source, generated: {
name : name line: gen_line + options.dest_line_diff,
column: gen_col
},
original: {
line: orig_line + options.orig_line_diff,
column: orig_col
}
}); });
},
get: function() {
return generator;
},
toString: function() {
return JSON.stringify(generator.toJSON());
}
}; };
return { }
add : add,
get : function() { return generator },
toString : function() { return JSON.stringify(generator.toJSON()); }
};
};

View File

@@ -43,8 +43,6 @@
"use strict"; "use strict";
// Tree transformer helpers.
function TreeTransformer(before, after) { function TreeTransformer(before, after) {
TreeWalker.call(this); TreeWalker.call(this);
this.before = before; this.before = before;
@@ -52,168 +50,136 @@ function TreeTransformer(before, after) {
} }
TreeTransformer.prototype = new TreeWalker; TreeTransformer.prototype = new TreeWalker;
(function(undefined){ (function(DEF) {
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 (x === undefined) {
x = this;
descend(x, tw);
if (tw.after) {
y = tw.after(x, in_list);
if (y !== undefined) x = y;
}
}
tw.pop();
return x;
});
};
function do_list(list, tw) { function do_list(list, tw) {
return MAP(list, function(node){ return MAP(list, function(node) {
return node.transform(tw, true); return node.transform(tw, true);
}); });
}; }
_(AST_Node, noop); DEF(AST_Node, noop);
DEF(AST_LabeledStatement, function(self, tw) {
_(AST_LabeledStatement, function(self, tw){
self.label = self.label.transform(tw); self.label = self.label.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_SimpleStatement, function(self, tw) {
_(AST_SimpleStatement, function(self, tw){
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_Block, function(self, tw) {
_(AST_Block, function(self, tw){
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Do, function(self, tw) {
_(AST_Do, function(self, tw){
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
}); });
DEF(AST_While, function(self, tw) {
_(AST_While, function(self, tw){
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_For, function(self, tw) {
_(AST_For, function(self, tw){
if (self.init) self.init = self.init.transform(tw); if (self.init) self.init = self.init.transform(tw);
if (self.condition) self.condition = self.condition.transform(tw); if (self.condition) self.condition = self.condition.transform(tw);
if (self.step) self.step = self.step.transform(tw); if (self.step) self.step = self.step.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_ForIn, function(self, tw) {
_(AST_ForIn, function(self, tw){
self.init = self.init.transform(tw); self.init = self.init.transform(tw);
self.object = self.object.transform(tw); self.object = self.object.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_With, function(self, tw) {
_(AST_With, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_Exit, function(self, tw) {
_(AST_Exit, function(self, tw){
if (self.value) self.value = self.value.transform(tw); if (self.value) self.value = self.value.transform(tw);
}); });
DEF(AST_LoopControl, function(self, tw) {
_(AST_LoopControl, function(self, tw){
if (self.label) self.label = self.label.transform(tw); if (self.label) self.label = self.label.transform(tw);
}); });
DEF(AST_If, function(self, tw) {
_(AST_If, function(self, tw){
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
if (self.alternative) self.alternative = self.alternative.transform(tw); if (self.alternative) self.alternative = self.alternative.transform(tw);
}); });
DEF(AST_Switch, function(self, tw) {
_(AST_Switch, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Case, function(self, tw) {
_(AST_Case, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Try, function(self, tw) {
_(AST_Try, function(self, tw){
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
if (self.bcatch) self.bcatch = self.bcatch.transform(tw); if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
if (self.bfinally) self.bfinally = self.bfinally.transform(tw); if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
}); });
DEF(AST_Catch, function(self, tw) {
_(AST_Catch, function(self, tw){
self.argname = self.argname.transform(tw); self.argname = self.argname.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Definitions, function(self, tw) {
_(AST_Definitions, function(self, tw){
self.definitions = do_list(self.definitions, tw); self.definitions = do_list(self.definitions, tw);
}); });
DEF(AST_VarDef, function(self, tw) {
_(AST_VarDef, function(self, tw){
self.name = self.name.transform(tw); self.name = self.name.transform(tw);
if (self.value) self.value = self.value.transform(tw); if (self.value) self.value = self.value.transform(tw);
}); });
DEF(AST_Lambda, function(self, tw) {
_(AST_Lambda, function(self, tw){
if (self.name) self.name = self.name.transform(tw); if (self.name) self.name = self.name.transform(tw);
self.argnames = do_list(self.argnames, tw); self.argnames = do_list(self.argnames, tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Call, function(self, tw) {
_(AST_Call, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.args = do_list(self.args, tw); self.args = do_list(self.args, tw);
}); });
DEF(AST_Sequence, function(self, tw) {
_(AST_Sequence, function(self, tw){
self.expressions = do_list(self.expressions, tw); self.expressions = do_list(self.expressions, tw);
}); });
DEF(AST_Dot, function(self, tw) {
_(AST_Dot, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
}); });
DEF(AST_Sub, function(self, tw) {
_(AST_Sub, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.property = self.property.transform(tw); self.property = self.property.transform(tw);
}); });
DEF(AST_Unary, function(self, tw) {
_(AST_Unary, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
}); });
DEF(AST_Binary, function(self, tw) {
_(AST_Binary, function(self, tw){
self.left = self.left.transform(tw); self.left = self.left.transform(tw);
self.right = self.right.transform(tw); self.right = self.right.transform(tw);
}); });
DEF(AST_Conditional, function(self, tw) {
_(AST_Conditional, function(self, tw){
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.consequent = self.consequent.transform(tw); self.consequent = self.consequent.transform(tw);
self.alternative = self.alternative.transform(tw); self.alternative = self.alternative.transform(tw);
}); });
DEF(AST_Array, function(self, tw) {
_(AST_Array, function(self, tw){
self.elements = do_list(self.elements, tw); self.elements = do_list(self.elements, tw);
}); });
DEF(AST_Object, function(self, tw) {
_(AST_Object, function(self, tw){
self.properties = do_list(self.properties, tw); self.properties = do_list(self.properties, tw);
}); });
DEF(AST_ObjectProperty, function(self, tw) {
_(AST_ObjectProperty, function(self, tw){
self.value = self.value.transform(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;
});
});

View File

@@ -52,9 +52,7 @@ function member(name, array) {
} }
function find_if(func, array) { function find_if(func, array) {
for (var i = 0, n = array.length; i < n; ++i) { for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
if (func(array[i])) return array[i];
}
} }
function repeat_string(str, i) { function repeat_string(str, i) {
@@ -115,7 +113,7 @@ function return_true() { return true; }
function return_this() { return this; } function return_this() { return this; }
function return_null() { return null; } function return_null() { return null; }
var MAP = (function(){ var MAP = (function() {
function MAP(a, f, backwards) { function MAP(a, f, backwards) {
var ret = [], top = [], i; var ret = [], top = [], i;
function doit() { function doit() {
@@ -138,7 +136,7 @@ var MAP = (function(){
} }
} }
return is_last; return is_last;
}; }
if (Array.isArray(a)) { if (Array.isArray(a)) {
if (backwards) { if (backwards) {
for (i = a.length; --i >= 0;) if (doit()) break; for (i = a.length; --i >= 0;) if (doit()) break;
@@ -152,14 +150,14 @@ var MAP = (function(){
for (i in a) if (HOP(a, i)) if (doit()) break; for (i in a) if (HOP(a, i)) if (doit()) break;
} }
return top.concat(ret); return top.concat(ret);
}; }
MAP.at_top = function(val) { return new AtTop(val) }; MAP.at_top = function(val) { return new AtTop(val) };
MAP.splice = function(val) { return new Splice(val) }; MAP.splice = function(val) { return new Splice(val) };
MAP.last = function(val) { return new Last(val) }; MAP.last = function(val) { return new Last(val) };
var skip = MAP.skip = {}; var skip = MAP.skip = {};
function AtTop(val) { this.v = val }; function AtTop(val) { this.v = val }
function Splice(val) { this.v = val }; function Splice(val) { this.v = val }
function Last(val) { this.v = val }; function Last(val) { this.v = val }
return MAP; return MAP;
})(); })();
@@ -169,7 +167,7 @@ function push_uniq(array, el) {
} }
function string_template(text, props) { function string_template(text, props) {
return text.replace(/\{(.+?)\}/g, function(str, p){ return text.replace(/\{(.+?)\}/g, function(str, p) {
return props && props[p]; return props && props[p];
}); });
} }

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)", "author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"version": "3.4.0", "version": "3.4.2",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },

View File

@@ -5,7 +5,8 @@ replace_index: {
properties: true, properties: true,
} }
input: { input: {
console.log(arguments && arguments[0]); var arguments = [];
console.log(arguments[0]);
(function() { (function() {
console.log(arguments[1], arguments["1"], arguments["foo"]); console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42); })("bar", 42);
@@ -21,7 +22,8 @@ replace_index: {
})("bar", 42); })("bar", 42);
} }
expect: { expect: {
console.log(arguments && arguments[0]); var arguments = [];
console.log(arguments[0]);
(function() { (function() {
console.log(arguments[1], arguments[1], arguments.foo); console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42); })("bar", 42);
@@ -45,6 +47,37 @@ replace_index: {
] ]
} }
replace_index_strict: {
options = {
arguments: true,
evaluate: true,
properties: true,
reduce_vars: true,
}
input: {
"use strict";
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
"use strict";
(function() {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
}
expect_stdout: [
"42 42 undefined",
"42 42 undefined",
]
}
replace_index_keep_fargs: { replace_index_keep_fargs: {
options = { options = {
arguments: true, arguments: true,
@@ -53,7 +86,8 @@ replace_index_keep_fargs: {
properties: true, properties: true,
} }
input: { input: {
console.log(arguments && arguments[0]); var arguments = [];
console.log(arguments[0]);
(function() { (function() {
console.log(arguments[1], arguments["1"], arguments["foo"]); console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42); })("bar", 42);
@@ -69,7 +103,8 @@ replace_index_keep_fargs: {
})("bar", 42); })("bar", 42);
} }
expect: { expect: {
console.log(arguments && arguments[0]); var arguments = [];
console.log(arguments[0]);
(function(argument_0, argument_1) { (function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo); console.log(argument_1, argument_1, arguments.foo);
})("bar", 42); })("bar", 42);
@@ -93,6 +128,38 @@ replace_index_keep_fargs: {
] ]
} }
replace_index_keep_fargs_strict: {
options = {
arguments: true,
evaluate: true,
keep_fargs: false,
properties: true,
reduce_vars: true,
}
input: {
"use strict";
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
"use strict";
(function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
}
expect_stdout: [
"42 42 undefined",
"42 42 undefined",
]
}
modified: { modified: {
options = { options = {
arguments: true, arguments: true,
@@ -101,8 +168,10 @@ modified: {
(function(a, b) { (function(a, b) {
var c = arguments[0]; var c = arguments[0];
var d = arguments[1]; var d = arguments[1];
a = "foo"; var a = "foo";
b++; b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]); console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42); })("bar", 42);
} }
@@ -110,10 +179,61 @@ modified: {
(function(a, b) { (function(a, b) {
var c = a; var c = a;
var d = b; var d = b;
a = "foo"; var a = "foo";
b++; b++;
a = "moo";
b *= 2;
console.log(a, b, c, d, a, b); console.log(a, b, c, d, a, b);
})("bar", 42); })("bar", 42);
} }
expect_stdout: "foo 43 bar 42 foo 43" expect_stdout: "moo 86 bar 42 moo 86"
}
modified_strict: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect: {
"use strict";
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect_stdout: "foo 43 bar 42 moo 84"
}
duplicate_argname: {
options = {
arguments: true,
}
input: {
(function(a, b, a) {
console.log(a, b, arguments[0], arguments[1], arguments[2]);
})("foo", 42, "bar");
}
expect: {
(function(a, b, a) {
console.log(a, b, arguments[0], b, a);
})("foo", 42, "bar");
}
expect_stdout: "bar 42 foo 42 bar"
} }

View File

@@ -150,36 +150,36 @@ collapse_vars_issue_721: {
reduce_funcs: true, reduce_vars:true, passes:2 reduce_funcs: true, reduce_vars:true, passes:2
} }
input: { input: {
define(["require", "exports", 'handlebars'], function (require, exports, hb) { define(["require", "exports", 'handlebars'], function(require, exports, hb) {
var win = window; var win = window;
var _hb = win.Handlebars = hb; var _hb = win.Handlebars = hb;
return _hb; return _hb;
}); });
def(function (hb) { def(function(hb) {
var win = window; var win = window;
var prop = 'Handlebars'; var prop = 'Handlebars';
var _hb = win[prop] = hb; var _hb = win[prop] = hb;
return _hb; return _hb;
}); });
def(function (hb) { def(function(hb) {
var prop = 'Handlebars'; var prop = 'Handlebars';
var win = window; var win = window;
var _hb = win[prop] = hb; var _hb = win[prop] = hb;
return _hb; return _hb;
}); });
def(function (hb) { def(function(hb) {
var prop = 'Handlebars'; var prop = 'Handlebars';
var win = g(); var win = g();
var _hb = win[prop] = hb; var _hb = win[prop] = hb;
return _hb; return _hb;
}); });
def(function (hb) { def(function(hb) {
var prop = g1(); var prop = g1();
var win = g2(); var win = g2();
var _hb = win[prop] = hb; var _hb = win[prop] = hb;
return _hb; return _hb;
}); });
def(function (hb) { def(function(hb) {
var win = g2(); var win = g2();
var prop = g1(); var prop = g1();
var _hb = win[prop] = hb; var _hb = win[prop] = hb;
@@ -196,14 +196,14 @@ collapse_vars_issue_721: {
def(function(hb) { def(function(hb) {
return window.Handlebars = hb; return window.Handlebars = hb;
}), }),
def(function (hb) { def(function(hb) {
return g().Handlebars = hb; return g().Handlebars = hb;
}), }),
def(function (hb) { def(function(hb) {
var prop = g1(); var prop = g1();
return g2()[prop] = hb; return g2()[prop] = hb;
}), }),
def(function (hb) { def(function(hb) {
return g2()[g1()] = hb; return g2()[g1()] = hb;
}); });
} }
@@ -3150,7 +3150,7 @@ issue_2437_1: {
return result; return result;
} else { } else {
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
var detectFunc = function () {}; var detectFunc = function(){};
req.onreadystatechange = detectFunc; req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc; var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null; req.onreadystatechange = null;
@@ -3166,7 +3166,7 @@ issue_2437_1: {
return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}), return Object.defineProperty(XMLHttpRequest.prototype, "onreadystatechange", xhrDesc || {}),
result; result;
} }
var req, detectFunc = function() {}; var req, detectFunc = function(){};
(req = new XMLHttpRequest()).onreadystatechange = detectFunc; (req = new XMLHttpRequest()).onreadystatechange = detectFunc;
result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc; result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
return req.onreadystatechange = null, result; return req.onreadystatechange = null, result;
@@ -3200,7 +3200,7 @@ issue_2437_2: {
return result; return result;
} else { } else {
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
var detectFunc = function () {}; var detectFunc = function(){};
req.onreadystatechange = detectFunc; req.onreadystatechange = detectFunc;
var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc; var result = req[SYMBOL_FAKE_ONREADYSTATECHANGE_1] === detectFunc;
req.onreadystatechange = null; req.onreadystatechange = null;
@@ -4513,7 +4513,7 @@ issue_2878: {
} }
input: { input: {
var c = 0; var c = 0;
(function (a, b) { (function(a, b) {
function f2() { function f2() {
if (a) c++; if (a) c++;
} }
@@ -4526,7 +4526,7 @@ issue_2878: {
} }
expect: { expect: {
var c = 0; var c = 0;
(function (a, b) { (function(a, b) {
function f2() { function f2() {
if (a) c++; if (a) c++;
} }

View File

@@ -1926,3 +1926,31 @@ issue_3146_4: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_3192: {
options = {
unused: true,
}
input: {
(function(a) {
console.log(a = "foo", arguments[0]);
})("bar");
(function(a) {
"use strict";
console.log(a = "foo", arguments[0]);
})("bar");
}
expect: {
(function(a) {
console.log(a = "foo", arguments[0]);
})("bar");
(function(a) {
"use strict";
console.log("foo", arguments[0]);
})("bar");
}
expect_stdout: [
"foo foo",
"foo bar",
]
}

View File

@@ -1533,7 +1533,7 @@ issue_2663_3: {
unused: true, unused: true,
} }
input: { input: {
(function () { (function() {
var outputs = [ var outputs = [
{ type: 0, target: null, eventName: "ngSubmit", propName: null }, { type: 0, target: null, eventName: "ngSubmit", propName: null },
{ type: 0, target: null, eventName: "submit", propName: null }, { type: 0, target: null, eventName: "submit", propName: null },
@@ -1550,11 +1550,11 @@ issue_2663_3: {
return handlers; return handlers;
} }
function renderEventHandlerClosure(eventName) { function renderEventHandlerClosure(eventName) {
return function () { return function() {
return console.log(eventName); return console.log(eventName);
}; };
} }
listenToElementOutputs(outputs).forEach(function (handler) { listenToElementOutputs(outputs).forEach(function(handler) {
return handler() return handler()
}); });
})(); })();
@@ -1634,7 +1634,7 @@ loop_init_arg: {
} }
input: { input: {
var a = "PASS"; var a = "PASS";
for (var k in "12") (function (b) { for (var k in "12") (function(b) {
(b >>= 1) && (a = "FAIL"), b = 2; (b >>= 1) && (a = "FAIL"), b = 2;
})(); })();
console.log(a); console.log(a);

View File

@@ -420,8 +420,8 @@ issue_24_2: {
})(); })();
} }
expect: { expect: {
(function(n) { (function(o) {
console.log(typeof function o(){} === typeof n ? "FAIL" : "PASS"); console.log(typeof function n(){} === typeof o ? "FAIL" : "PASS");
})(); })();
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -457,9 +457,29 @@ issue_2976_2: {
}()); }());
} }
expect: { expect: {
console.log(function n() { console.log(function f() {
var o; var n;
return o === n ? "FAIL" : "PASS"; return n === f ? "FAIL" : "PASS";
}());
}
expect_stdout: "PASS"
}
issue_2976_3: {
mangle = {
ie8: true,
toplevel: true,
}
input: {
console.log(function f() {
var a;
return a === f ? "FAIL" : "PASS";
}());
}
expect: {
console.log(function o() {
var n;
return n === o ? "FAIL" : "PASS";
}()); }());
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -538,3 +558,111 @@ issue_3035_ie8: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_3197_1: {
options = {
ie8: false,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
mangle = {
ie8: false,
}
input: {
var window = {};
!function() {
function Foo() {
console.log(this instanceof Foo);
}
window.Foo = Foo;
}();
new window.Foo();
}
expect: {
var window = {};
window.Foo = function o() {
console.log(this instanceof o);
};
new window.Foo();
}
expect_stdout: "true"
}
issue_3197_1_ie8: {
options = {
ie8: true,
inline: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
mangle = {
ie8: true,
}
input: {
var window = {};
!function() {
function Foo() {
console.log(this instanceof Foo);
}
window.Foo = Foo;
}();
new window.Foo();
}
expect: {
var window = {};
window.Foo = function Foo() {
console.log(this instanceof Foo);
};
new window.Foo();
}
expect_stdout: "true"
}
issue_3197_2: {
mangle = {
ie8: false,
}
input: {
(function(a) {
var f = function f() {
console.log(this instanceof f);
};
new f(a);
})();
}
expect: {
(function(n) {
var o = function n() {
console.log(this instanceof n);
};
new o(n);
})();
}
expect_stdout: "true"
}
issue_3197_2_ie8: {
mangle = {
ie8: true,
}
input: {
(function(a) {
var f = function f() {
console.log(this instanceof f);
};
new f(a);
})();
}
expect: {
(function(n) {
var o = function o() {
console.log(this instanceof o);
};
new o(n);
})();
}
expect_stdout: "true"
}

View File

@@ -399,7 +399,7 @@ wrap_iife_in_expression: {
wrap_iife: true, wrap_iife: true,
} }
input: { input: {
foo = (function () { foo = (function() {
return bar(); return bar();
})(); })();
} }

View File

@@ -1729,3 +1729,106 @@ issue_869_2: {
} }
expect_stdout: "PASS" expect_stdout: "PASS"
} }
issue_3188_1: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
}
input: {
(function() {
function f() {
console.log(this.p);
}
(function() {
var o = {
p: "PASS",
f: f
};
o.f();
})();
})();
}
expect: {
(function() {
function f() {
console.log(this.p);
}
({
p: "PASS",
f: f
}).f();
var o;
})();
}
expect_stdout: "PASS"
}
issue_3188_2: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(function() {
var f = function() {
console.log(this.p);
};
function g() {
var o = {
p: "PASS",
f: f
};
o.f();
}
g();
})();
}
expect: {
({
p: "PASS",
f: function() {
console.log(this.p);
}
}).f();
}
expect_stdout: "PASS"
}
issue_3188_3: {
options = {
collapse_vars: true,
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
}
input: {
(function() {
function f() {
console.log(this[0]);
}
(function() {
var o = ["PASS", f];
o[1]();
})();
})();
}
expect: {
(function() {
function f() {
console.log(this[0]);
}
["PASS", f][1]();
var o;
})();
}
expect_stdout: "PASS"
}

View File

@@ -4887,7 +4887,7 @@ inverted_var: {
}(), function(c) { }(), function(c) {
c = 4; c = 4;
return c; return c;
}(), function (c) { }(), function(c) {
c = 5; c = 5;
return c; return c;
var c; var c;

View File

@@ -23,7 +23,7 @@ wrap_iife_in_expression: {
wrap_iife: true, wrap_iife: true,
} }
input: { input: {
foo = (function () { foo = (function() {
return bar(); return bar();
})(); })();
} }

View File

@@ -1,4 +1,4 @@
var bar = (function () { var bar = (function() {
function foo (bar) { function foo (bar) {
return bar; return bar;
} }

View File

@@ -1,17 +1,14 @@
var UglifyJS = require("../node");
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../..");
describe("arguments", function() { describe("arguments", function() {
it("Should known that arguments in functions are local scoped", function() { it("Should known that arguments in functions are local scoped", function() {
var ast = UglifyJS.parse("var arguments; var f = function() {arguments.length}"); var ast = UglifyJS.parse("var arguments; var f = function() {arguments.length}");
ast.figure_out_scope(); ast.figure_out_scope();
// Test scope of `var arguments` // Test scope of `var arguments`
assert.strictEqual(ast.find_variable("arguments").global, true); assert.strictEqual(ast.find_variable("arguments").global, true);
// Select arguments symbol in function // Select arguments symbol in function
var symbol = ast.body[1].definitions[0].value.find_variable("arguments"); var symbol = ast.body[1].definitions[0].value.find_variable("arguments");
assert.strictEqual(symbol.global, false); assert.strictEqual(symbol.global, false);
assert.strictEqual(symbol.scope, ast. // From ast assert.strictEqual(symbol.scope, ast. // From ast
body[1]. // Select 2nd statement (equals to `var f ...`) body[1]. // Select 2nd statement (equals to `var f ...`)

View File

@@ -8,58 +8,46 @@ function read(path) {
describe("bin/uglifyjs", function() { describe("bin/uglifyjs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
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, 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');
var result = WrappedUglifyJS.minify("foo([true,,2+3]);"); var result = WrappedUglifyJS.minify("foo([true,,2+3]);");
assert.strictEqual(result.error, undefined); assert.strictEqual(result.error, undefined);
assert.strictEqual(result.code, "foo([!0,,5]);"); assert.strictEqual(result.code, "foo([!0,,5]);");
done(); done();
}); });
}); });
it("Should be able to filter comments correctly with `--comments all`", function (done) { it("Should be able to filter comments correctly with `--comments all`", function(done) {
var command = uglifyjscmd + ' test/input/comments/filter.js --comments all'; var command = uglifyjscmd + ' test/input/comments/filter.js --comments all';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "// foo\n/*@preserve*/\n// bar\n\n"); assert.strictEqual(stdout, "// foo\n/*@preserve*/\n// bar\n\n");
done(); done();
}); });
}); });
it("Should be able to filter comments correctly with `--comment <RegExp>`", function (done) { it("Should be able to filter comments correctly with `--comment <RegExp>`", function(done) {
var command = uglifyjscmd + ' test/input/comments/filter.js --comments /r/'; var command = uglifyjscmd + ' test/input/comments/filter.js --comments /r/';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "/*@preserve*/\n// bar\n\n"); assert.strictEqual(stdout, "/*@preserve*/\n// bar\n\n");
done(); done();
}); });
}); });
it("Should be able to filter comments correctly with just `--comment`", function (done) { it("Should be able to filter comments correctly with just `--comment`", function(done) {
var command = uglifyjscmd + ' test/input/comments/filter.js --comments'; var command = uglifyjscmd + ' test/input/comments/filter.js --comments';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "/*@preserve*/\n\n"); assert.strictEqual(stdout, "/*@preserve*/\n\n");
done(); done();
}); });
}); });
it("Should give sensible error against invalid input source map", function(done) { it("Should give sensible error against invalid input source map", function(done) {
var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline"; var command = uglifyjscmd + " test/mocha.js --source-map content=blah,url=inline";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.deepEqual(stderr.split(/\n/).slice(0, 2), [ assert.deepEqual(stderr.split(/\n/).slice(0, 2), [
"INFO: Using input source map: blah", "INFO: Using input source map: blah",
@@ -68,38 +56,35 @@ describe("bin/uglifyjs", function() {
done(); done();
}); });
}); });
it("Should append source map to output when using --source-map url=inline", function (done) { it("Should append source map to output when using --source-map url=inline", function(done) {
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map url=inline"; var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map url=inline";
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" + "var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==\n"); "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"",
].join("\n"));
done(); done();
}); });
}); });
it("should not append source map to output when not using --source-map url=inline", function (done) { it("should not append source map to output when not using --source-map url=inline", function(done) {
var command = uglifyjscmd + ' test/input/issue-1323/sample.js'; var command = uglifyjscmd + ' test/input/issue-1323/sample.js';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n"); assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n");
done(); done();
}); });
}); });
it("should not consider source map file content as source map file name (issue #2082)", function (done) { it("should not consider source map file content as source map file name (issue #2082)", function(done) {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,
"test/input/issue-2082/sample.js", "test/input/issue-2082/sample.js",
"--source-map", "content=test/input/issue-2082/sample.js.map", "--source-map", "content=test/input/issue-2082/sample.js.map",
"--source-map", "url=inline", "--source-map", "url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
if (err) throw err; if (err) throw err;
var stderrLines = stderr.split("\n"); var stderrLines = stderr.split("\n");
assert.strictEqual(stderrLines[0], "INFO: Using input source map: test/input/issue-2082/sample.js.map"); assert.strictEqual(stderrLines[0], "INFO: Using input source map: test/input/issue-2082/sample.js.map");
assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}'); assert.notStrictEqual(stderrLines[1], 'INFO: Using input source map: {"version": 3,"sources": ["index.js"],"mappings": ";"}');
@@ -136,82 +121,66 @@ describe("bin/uglifyjs", function() {
child.stdin.end(read("test/input/pr-3040/input.js")); child.stdin.end(read("test/input/pr-3040/input.js"));
}, 1000); }, 1000);
}); });
it("Should work with --keep-fnames (mangle only)", function (done) { it("Should work with --keep-fnames (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m'; var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n"); assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
done(); done();
}); });
}); });
it("Should work with --keep-fnames (mangle & compress)", function (done) { it("Should work with --keep-fnames (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false'; var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c unused=false';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n"); assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
done(); done();
}); });
}); });
it("Should work with keep_fnames under mangler options", function (done) { it("Should work with keep_fnames under mangler options", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true'; var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fnames=true';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n"); assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
done(); done();
}); });
}); });
it("Should work with --define (simple)", function (done) { it("Should work with --define (simple)", function(done) {
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c'; var command = uglifyjscmd + ' test/input/global_defs/simple.js --define D=5 -c';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "console.log(5);\n"); assert.strictEqual(stdout, "console.log(5);\n");
done(); done();
}); });
}); });
it("Should work with --define (nested)", function (done) { it("Should work with --define (nested)", function(done) {
var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c'; var command = uglifyjscmd + ' test/input/global_defs/nested.js --define C.D=5,C.V=3 -c';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "console.log(3,5);\n"); assert.strictEqual(stdout, "console.log(3,5);\n");
done(); done();
}); });
}); });
it("Should work with --define (AST_Node)", function (done) { it("Should work with --define (AST_Node)", function(done) {
var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c'; var command = uglifyjscmd + ' test/input/global_defs/simple.js --define console.log=stdout.println -c';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "stdout.println(D);\n"); assert.strictEqual(stdout, "stdout.println(D);\n");
done(); done();
}); });
}); });
it("Should work with `--beautify`", function (done) { it("Should work with `--beautify`", function(done) {
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b'; var command = uglifyjscmd + ' test/input/issue-1482/input.js -b';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-1482/default.js")); assert.strictEqual(stdout, read("test/input/issue-1482/default.js"));
done(); done();
}); });
}); });
it("Should work with `--beautify braces`", function (done) { it("Should work with `--beautify braces`", function(done) {
var command = uglifyjscmd + ' test/input/issue-1482/input.js -b braces'; var command = uglifyjscmd + ' test/input/issue-1482/input.js -b braces';
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-1482/braces.js")); assert.strictEqual(stdout, read("test/input/issue-1482/braces.js"));
done(); done();
}); });
@@ -225,20 +194,16 @@ describe("bin/uglifyjs", function() {
"--source-map", "includeSources=true", "--source-map", "includeSources=true",
"--source-map", "url=inline", "--source-map", "url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, read("test/input/issue-520/output.js")); assert.strictEqual(stdout, read("test/input/issue-520/output.js"));
done(); done();
}); });
}); });
it("Should warn for missing inline source map", function(done) { it("Should warn for missing inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline"; var command = uglifyjscmd + " test/input/issue-1323/sample.js --source-map content=inline,url=inline";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();", "var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
@@ -256,10 +221,8 @@ describe("bin/uglifyjs", function() {
"test/input/issue-1323/sample.js", "test/input/issue-1323/sample.js",
"--source-map", "content=inline,url=inline", "--source-map", "content=inline,url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
"var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();", "var Foo=function Foo(){console.log(1+2)};new Foo;var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0ZGluIiwidGVzdC9pbnB1dC9pc3N1ZS0xMzIzL3NhbXBsZS5qcyJdLCJuYW1lcyI6WyJGb28iLCJjb25zb2xlIiwibG9nIiwiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxJQUFJLFNBQUFBLE1BQWdCQyxRQUFRQyxJQUFJLEVBQUUsSUFBTyxJQUFJRixJQ0FuRCxJQUFJRyxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
@@ -272,8 +235,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should fail with acorn and inline source map", function(done) { it("Should fail with acorn and inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p acorn"; var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p acorn";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n"); assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n");
done(); done();
@@ -281,8 +243,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should fail with SpiderMonkey and inline source map", function(done) { it("Should fail with SpiderMonkey and inline source map", function(done) {
var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p spidermonkey"; var command = uglifyjscmd + " test/input/issue-520/input.js --source-map content=inline,url=inline -p spidermonkey";
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n"); assert.strictEqual(stderr, "ERROR: inline source map only works with built-in parser\n");
done(); done();
@@ -290,8 +251,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should fail with invalid syntax", function(done) { it("Should fail with invalid syntax", function(done) {
var command = uglifyjscmd + ' test/input/invalid/simple.js'; var command = uglifyjscmd + ' test/input/invalid/simple.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/simple.js:1,12");
@@ -303,8 +263,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should fail with correct marking of tabs", function(done) { it("Should fail with correct marking of tabs", function(done) {
var command = uglifyjscmd + ' test/input/invalid/tab.js'; var command = uglifyjscmd + ' test/input/invalid/tab.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/tab.js:1,12");
@@ -316,8 +275,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should fail with correct marking at start of line", function(done) { it("Should fail with correct marking at start of line", function(done) {
var command = uglifyjscmd + ' test/input/invalid/eof.js'; var command = uglifyjscmd + ' test/input/invalid/eof.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/eof.js:2,0");
@@ -329,8 +287,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should fail with a missing loop body", function(done) { it("Should fail with a missing loop body", function(done) {
var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js'; var command = uglifyjscmd + ' test/input/invalid/loop-no-body.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
var lines = stderr.split(/\n/); var lines = stderr.split(/\n/);
assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0"); assert.strictEqual(lines[0], "Parse error at test/input/invalid/loop-no-body.js:2,0");
@@ -342,8 +299,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (5--)", function(done) { it("Should throw syntax error (5--)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_1.js'; var command = uglifyjscmd + ' test/input/invalid/assign_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -357,8 +313,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (Math.random() /= 2)", function(done) { it("Should throw syntax error (Math.random() /= 2)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_2.js'; var command = uglifyjscmd + ' test/input/invalid/assign_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -372,8 +327,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (++this)", function(done) { it("Should throw syntax error (++this)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_3.js'; var command = uglifyjscmd + ' test/input/invalid/assign_3.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -387,8 +341,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (++null)", function(done) { it("Should throw syntax error (++null)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/assign_4.js'; var command = uglifyjscmd + ' test/input/invalid/assign_4.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -402,8 +355,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (a.=)", function(done) { it("Should throw syntax error (a.=)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/dot_1.js'; var command = uglifyjscmd + ' test/input/invalid/dot_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -417,8 +369,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (%.a)", function(done) { it("Should throw syntax error (%.a)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/dot_2.js'; var command = uglifyjscmd + ' test/input/invalid/dot_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -432,8 +383,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (a./();)", function(done) { it("Should throw syntax error (a./();)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/dot_3.js'; var command = uglifyjscmd + ' test/input/invalid/dot_3.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -447,8 +397,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error ({%: 1})", function(done) { it("Should throw syntax error ({%: 1})", function(done) {
var command = uglifyjscmd + ' test/input/invalid/object.js'; var command = uglifyjscmd + ' test/input/invalid/object.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -462,8 +411,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (delete x)", function(done) { it("Should throw syntax error (delete x)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/delete.js'; var command = uglifyjscmd + ' test/input/invalid/delete.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -477,8 +425,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (function g(arguments))", function(done) { it("Should throw syntax error (function g(arguments))", function(done) {
var command = uglifyjscmd + ' test/input/invalid/function_1.js'; var command = uglifyjscmd + ' test/input/invalid/function_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -492,8 +439,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (function eval())", function(done) { it("Should throw syntax error (function eval())", function(done) {
var command = uglifyjscmd + ' test/input/invalid/function_2.js'; var command = uglifyjscmd + ' test/input/invalid/function_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -507,8 +453,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (iife arguments())", function(done) { it("Should throw syntax error (iife arguments())", function(done) {
var command = uglifyjscmd + ' test/input/invalid/function_3.js'; var command = uglifyjscmd + ' test/input/invalid/function_3.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -522,8 +467,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (catch(eval))", function(done) { it("Should throw syntax error (catch(eval))", function(done) {
var command = uglifyjscmd + ' test/input/invalid/try.js'; var command = uglifyjscmd + ' test/input/invalid/try.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -537,8 +481,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (var eval)", function(done) { it("Should throw syntax error (var eval)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/var.js'; var command = uglifyjscmd + ' test/input/invalid/var.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -552,8 +495,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (else)", function(done) { it("Should throw syntax error (else)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/else.js'; var command = uglifyjscmd + ' test/input/invalid/else.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -567,8 +509,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (return)", function(done) { it("Should throw syntax error (return)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/return.js'; var command = uglifyjscmd + ' test/input/invalid/return.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -582,8 +523,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (for-in init)", function(done) { it("Should throw syntax error (for-in init)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_1.js'; var command = uglifyjscmd + ' test/input/invalid/for-in_1.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -597,8 +537,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should throw syntax error (for-in var)", function(done) { it("Should throw syntax error (for-in var)", function(done) {
var command = uglifyjscmd + ' test/input/invalid/for-in_2.js'; var command = uglifyjscmd + ' test/input/invalid/for-in_2.js';
exec(command, function(err, stdout, stderr) {
exec(command, function (err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [ assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
@@ -617,10 +556,8 @@ describe("bin/uglifyjs", function() {
"--source-map", "--source-map",
'content="' + read_map() + '",url=inline' 'content="' + read_map() + '",url=inline'
].join(" "); ].join(" ");
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
'"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));', '"use strict";var foo=function foo(x){return"foo "+x};console.log(foo("bar"));',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LmpzIl0sIm5hbWVzIjpbImZvbyIsIngiLCJjb25zb2xlIiwibG9nIl0sIm1hcHBpbmdzIjoiYUFBQSxJQUFJQSxJQUFNLFNBQU5BLElBQU1DLEdBQUEsTUFBSyxPQUFTQSxHQUN4QkMsUUFBUUMsSUFBSUgsSUFBSSJ9",
@@ -642,10 +579,8 @@ describe("bin/uglifyjs", function() {
"-c", "-c",
"--source-map", "url=inline", "--source-map", "url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, [
'function foo(){return function(){console.log("PASS")}}foo()();', 'function foo(){return function(){console.log("PASS")}}foo()();',
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==", "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMjMxMC9pbnB1dC5qcyJdLCJuYW1lcyI6WyJmb28iLCJjb25zb2xlIiwibG9nIiwiZiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBU0EsTUFDTCxPQUFPLFdBQ0hDLFFBQVFDLElBQUksU0FLUkYsS0FDUkcifQ==",
@@ -656,9 +591,8 @@ describe("bin/uglifyjs", function() {
}); });
it("Should dump AST as JSON", function(done) { it("Should dump AST as JSON", function(done) {
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast"; var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
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));
@@ -667,7 +601,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should print supported options on invalid option syntax", function(done) { it("Should print supported options on invalid option syntax", function(done) {
var command = uglifyjscmd + " test/input/comments/filter.js -b ascii-only"; var command = uglifyjscmd + " test/input/comments/filter.js -b ascii-only";
exec(command, function (err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr); assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `ascii-only` is not a supported option/.test(stderr), stderr);
@@ -676,27 +610,23 @@ describe("bin/uglifyjs", function() {
}); });
it("Should work with --mangle reserved=[]", function(done) { it("Should work with --mangle reserved=[]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]"; var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]";
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n'); assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n');
done(); done();
}); });
}); });
it("Should work with --mangle reserved=false", function(done) { it("Should work with --mangle reserved=false", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false"; var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false";
exec(command, function(err, stdout) {
exec(command, function (err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n'); assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n');
done(); done();
}); });
}); });
it("Should fail with --mangle-props reserved=[in]", function(done) { it("Should fail with --mangle-props reserved=[in]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]"; var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]";
exec(command, function (err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr); assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr);
@@ -705,7 +635,7 @@ describe("bin/uglifyjs", function() {
}); });
it("Should fail with --define a-b", function(done) { it("Should fail with --define a-b", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b"; var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
exec(command, function (err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n"); assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");

View File

@@ -1,89 +0,0 @@
var UglifyJS = require("../node");
var assert = require("assert");
describe("comment filters", function() {
it("Should be able to filter comments by passing regexp", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: /^!/}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
});
it("Should be able to filter comments with the 'all' option", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
});
it("Should be able to filter commments with the 'some' option", function() {
var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/");
});
it("Should be able to filter comments by passing a function", function() {
var ast = UglifyJS.parse("/*TEST 123*/\n//An other comment\n//8 chars.");
var f = function(node, comment) {
return comment.value.length === 8;
};
assert.strictEqual(ast.print_to_string({comments: f}), "/*TEST 123*/\n//8 chars.\n");
});
it("Should be able to filter comments by passing regex in string format", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: "/^!/"}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
});
it("Should be able to get the comment and comment type when using a function", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
var f = function(node, comment) {
return comment.type == "comment1" || comment.type == "comment3";
};
assert.strictEqual(ast.print_to_string({comments: f}), "//!test3\n//test4\n//test5\n//!test6\n");
});
it("Should be able to filter comments by passing a boolean", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: true}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
assert.strictEqual(ast.print_to_string({comments: false}), "");
});
it("Should never be able to filter comment5 (shebangs)", function() {
var ast = UglifyJS.parse("#!Random comment\n//test1\n/*test2*/");
var f = function(node, comment) {
assert.strictEqual(comment.type === "comment5", false);
return true;
};
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/");
});
it("Should never be able to filter comment5 when using 'some' as filter", function() {
var ast = UglifyJS.parse("#!foo\n//foo\n/*@preserve*/\n/* please hide me */");
assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/");
});
it("Should have no problem on multiple calls", function() {
const options = {
comments: /ok/
};
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
});
it("Should handle shebang and preamble correctly", function() {
var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", {
output: { preamble: "/* Build */" }
}).code;
assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;");
});
it("Should handle preamble without shebang correctly", function() {
var code = UglifyJS.minify("var x = 10;", {
output: { preamble: "/* Build */" }
}).code;
assert.strictEqual(code, "/* Build */\nvar x=10;");
});
});

View File

@@ -1,262 +0,0 @@
var assert = require("assert");
var uglify = require("../node");
describe("Comment", function() {
it("Should recognize eol of single line comments", function() {
var tests = [
"//Some comment 1\n>",
"//Some comment 2\r>",
"//Some comment 3\r\n>",
"//Some comment 4\u2028>",
"//Some comment 5\u2029>"
];
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === "Unexpected token: operator (>)" &&
e.line === 2 &&
e.col === 0;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(function() {
uglify.parse(tests[i]);
}, fail, tests[i]);
}
});
it("Should update the position of a multiline comment correctly", function() {
var tests = [
"/*Some comment 1\n\n\n*/\n>\n\n\n\n\n\n",
"/*Some comment 2\r\n\r\n\r\n*/\r\n>\n\n\n\n\n\n",
"/*Some comment 3\r\r\r*/\r>\n\n\n\n\n\n",
"/*Some comment 4\u2028\u2028\u2028*/\u2028>\n\n\n\n\n\n",
"/*Some comment 5\u2029\u2029\u2029*/\u2029>\n\n\n\n\n\n"
];
var fail = function(e) {
return e instanceof uglify.JS_Parse_Error &&
e.message === "Unexpected token: operator (>)" &&
e.line === 5 &&
e.col === 0;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(function() {
uglify.parse(tests[i]);
}, fail, tests[i]);
}
});
it("Should handle comment within return correctly", function() {
var result = uglify.minify([
"function unequal(x, y) {",
" return (",
" // Either one",
" x < y",
" ||",
" y < x",
" );",
"}",
].join("\n"), {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function unequal(x, y) {",
" // Either one",
" return x < y || y < x;",
"}",
].join("\n"));
});
it("Should handle comment folded into return correctly", function() {
var result = uglify.minify([
"function f() {",
" /* boo */ x();",
" return y();",
"}",
].join("\n"), {
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function f() {",
" /* boo */",
" return x(), y();",
"}",
].join("\n"));
});
it("Should not drop comments after first OutputStream", function() {
var code = "/* boo */\nx();";
var ast = uglify.parse(code);
var out1 = uglify.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out1);
var out2 = uglify.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out2);
assert.strictEqual(out1.get(), code);
assert.strictEqual(out2.get(), out1.get());
});
it("Should retain trailing comments", function() {
var code = [
"if (foo /* lost comment */ && bar /* lost comment */) {",
" // this one is kept",
" {/* lost comment */}",
" !function() {",
" // lost comment",
" }();",
" function baz() {/* lost comment */}",
" // lost comment",
"}",
"// comments right before EOF are lost as well",
].join("\n");
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should retain comments within braces", function() {
var code = [
"{/* foo */}",
"a({/* foo */});",
"while (a) {/* foo */}",
"switch (a) {/* foo */}",
"if (a) {/* foo */} else {/* bar */}",
].join("\n\n");
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should correctly preserve new lines around comments", function() {
var tests = [
[
"// foo",
"// bar",
"x();",
].join("\n"),
[
"// foo",
"/* bar */",
"x();",
].join("\n"),
[
"// foo",
"/* bar */ x();",
].join("\n"),
[
"/* foo */",
"// bar",
"x();",
].join("\n"),
[
"/* foo */ // bar",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */ x();",
].join("\n"),
[
"/* foo */ /* bar */",
"x();",
].join("\n"),
"/* foo */ /* bar */ x();",
].forEach(function(code) {
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
});
it("Should preserve new line before comment without beautify", function() {
var code = [
"function f(){",
"/* foo */bar()}",
].join("\n");
var result = uglify.minify(code, {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should preserve comments around IIFE", function() {
var result = uglify.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, "/*a*/ /*b*/(function(){/*c*/}/*d*/ /*e*/)();");
});
it("Should output line comments after statements", function() {
var result = uglify.minify([
"x()//foo",
"{y()//bar",
"}",
].join("\n"), {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"x();//foo",
"{y();//bar",
"}",
].join("\n"));
});
});

View File

@@ -1,22 +0,0 @@
var Uglify = require('../../');
var assert = require("assert");
describe("comment before constant", function() {
var js = 'function f() { /*c1*/ var /*c2*/ foo = /*c3*/ false; return foo; }';
it("Should test comment before constant is retained and output after mangle.", function() {
var result = Uglify.minify(js, {
compress: { collapse_vars: false, reduce_vars: false },
output: { comments: true },
});
assert.strictEqual(result.code, 'function f(){/*c1*/var/*c2*/n=/*c3*/!1;return n}');
});
it("Should test code works when comments disabled.", function() {
var result = Uglify.minify(js, {
compress: { collapse_vars: false, reduce_vars: false },
output: { comments: false },
});
assert.strictEqual(result.code, 'function f(){var n=!1;return n}');
});
});

380
test/mocha/comments.js Normal file
View File

@@ -0,0 +1,380 @@
var assert = require("assert");
var UglifyJS = require("../node");
describe("comments", function() {
it("Should recognize eol of single line comments", function() {
var tests = [
"//Some comment 1\n>",
"//Some comment 2\r>",
"//Some comment 3\r\n>",
"//Some comment 4\u2028>",
"//Some comment 5\u2029>"
];
var fail = function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (>)"
&& e.line === 2
&& e.col === 0;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(function() {
UglifyJS.parse(tests[i]);
}, fail, tests[i]);
}
});
it("Should update the position of a multiline comment correctly", function() {
var tests = [
"/*Some comment 1\n\n\n*/\n>\n\n\n\n\n\n",
"/*Some comment 2\r\n\r\n\r\n*/\r\n>\n\n\n\n\n\n",
"/*Some comment 3\r\r\r*/\r>\n\n\n\n\n\n",
"/*Some comment 4\u2028\u2028\u2028*/\u2028>\n\n\n\n\n\n",
"/*Some comment 5\u2029\u2029\u2029*/\u2029>\n\n\n\n\n\n"
];
var fail = function(e) {
return e instanceof UglifyJS.JS_Parse_Error
&& e.message === "Unexpected token: operator (>)"
&& e.line === 5
&& e.col === 0;
}
for (var i = 0; i < tests.length; i++) {
assert.throws(function() {
UglifyJS.parse(tests[i]);
}, fail, tests[i]);
}
});
it("Should handle comment within return correctly", function() {
var result = UglifyJS.minify([
"function unequal(x, y) {",
" return (",
" // Either one",
" x < y",
" ||",
" y < x",
" );",
"}",
].join("\n"), {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function unequal(x, y) {",
" // Either one",
" return x < y || y < x;",
"}",
].join("\n"));
});
it("Should handle comment folded into return correctly", function() {
var result = UglifyJS.minify([
"function f() {",
" /* boo */ x();",
" return y();",
"}",
].join("\n"), {
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"function f() {",
" /* boo */",
" return x(), y();",
"}",
].join("\n"));
});
it("Should not drop comments after first OutputStream", function() {
var code = "/* boo */\nx();";
var ast = UglifyJS.parse(code);
var out1 = UglifyJS.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out1);
var out2 = UglifyJS.OutputStream({
beautify: true,
comments: "all",
});
ast.print(out2);
assert.strictEqual(out1.get(), code);
assert.strictEqual(out2.get(), out1.get());
});
it("Should retain trailing comments", function() {
var code = [
"if (foo /* lost comment */ && bar /* lost comment */) {",
" // this one is kept",
" {/* lost comment */}",
" !function() {",
" // lost comment",
" }();",
" function baz() {/* lost comment */}",
" // lost comment",
"}",
"// comments right before EOF are lost as well",
].join("\n");
var result = UglifyJS.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should retain comments within braces", function() {
var code = [
"{/* foo */}",
"a({/* foo */});",
"while (a) {/* foo */}",
"switch (a) {/* foo */}",
"if (a) {/* foo */} else {/* bar */}",
].join("\n\n");
var result = UglifyJS.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should correctly preserve new lines around comments", function() {
var tests = [
[
"// foo",
"// bar",
"x();",
].join("\n"),
[
"// foo",
"/* bar */",
"x();",
].join("\n"),
[
"// foo",
"/* bar */ x();",
].join("\n"),
[
"/* foo */",
"// bar",
"x();",
].join("\n"),
[
"/* foo */ // bar",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */",
"x();",
].join("\n"),
[
"/* foo */",
"/* bar */ x();",
].join("\n"),
[
"/* foo */ /* bar */",
"x();",
].join("\n"),
"/* foo */ /* bar */ x();",
].forEach(function(code) {
var result = UglifyJS.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
});
it("Should preserve new line before comment without beautify", function() {
var code = [
"function f(){",
"/* foo */bar()}",
].join("\n");
var result = UglifyJS.minify(code, {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
});
it("Should preserve comments around IIFE", function() {
var result = UglifyJS.minify("/*a*/(/*b*/function(){/*c*/}/*d*/)/*e*/();", {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, "/*a*/ /*b*/(function(){/*c*/}/*d*/ /*e*/)();");
});
it("Should output line comments after statements", function() {
var result = UglifyJS.minify([
"x()//foo",
"{y()//bar",
"}",
].join("\n"), {
compress: false,
mangle: false,
output: {
comments: "all",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
"x();//foo",
"{y();//bar",
"}",
].join("\n"));
});
describe("comment before constant", function() {
var js = 'function f() { /*c1*/ var /*c2*/ foo = /*c3*/ false; return foo; }';
it("Should test comment before constant is retained and output after mangle.", function() {
var result = UglifyJS.minify(js, {
compress: { collapse_vars: false, reduce_vars: false },
output: { comments: true },
});
assert.strictEqual(result.code, 'function f(){/*c1*/var/*c2*/n=/*c3*/!1;return n}');
});
it("Should test code works when comments disabled.", function() {
var result = UglifyJS.minify(js, {
compress: { collapse_vars: false, reduce_vars: false },
output: { comments: false },
});
assert.strictEqual(result.code, 'function f(){var n=!1;return n}');
});
});
describe("comment filters", function() {
it("Should be able to filter comments by passing regexp", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: /^!/}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
});
it("Should be able to filter comments with the 'all' option", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: "all"}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
});
it("Should be able to filter commments with the 'some' option", function() {
var ast = UglifyJS.parse("// foo\n/*@preserve*/\n// bar\n/*@license*/\n//@license with the wrong comment type\n/*@cc_on something*/");
assert.strictEqual(ast.print_to_string({comments: "some"}), "/*@preserve*/\n/*@license*/\n/*@cc_on something*/");
});
it("Should be able to filter comments by passing a function", function() {
var ast = UglifyJS.parse("/*TEST 123*/\n//An other comment\n//8 chars.");
var f = function(node, comment) {
return comment.value.length === 8;
};
assert.strictEqual(ast.print_to_string({comments: f}), "/*TEST 123*/\n//8 chars.\n");
});
it("Should be able to filter comments by passing regex in string format", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: "/^!/"}), "/*!test1*/\n//!test3\n//!test6\n//!test8\n");
});
it("Should be able to get the comment and comment type when using a function", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
var f = function(node, comment) {
return comment.type == "comment1" || comment.type == "comment3";
};
assert.strictEqual(ast.print_to_string({comments: f}), "//!test3\n//test4\n//test5\n//!test6\n");
});
it("Should be able to filter comments by passing a boolean", function() {
var ast = UglifyJS.parse("/*!test1*/\n/*test2*/\n//!test3\n//test4\n<!--test5\n<!--!test6\n-->test7\n-->!test8");
assert.strictEqual(ast.print_to_string({comments: true}), "/*!test1*/\n/*test2*/\n//!test3\n//test4\n//test5\n//!test6\n//test7\n//!test8\n");
assert.strictEqual(ast.print_to_string({comments: false}), "");
});
it("Should never be able to filter comment5 (shebangs)", function() {
var ast = UglifyJS.parse("#!Random comment\n//test1\n/*test2*/");
var f = function(node, comment) {
assert.strictEqual(comment.type === "comment5", false);
return true;
};
assert.strictEqual(ast.print_to_string({comments: f}), "#!Random comment\n//test1\n/*test2*/");
});
it("Should never be able to filter comment5 when using 'some' as filter", function() {
var ast = UglifyJS.parse("#!foo\n//foo\n/*@preserve*/\n/* please hide me */");
assert.strictEqual(ast.print_to_string({comments: "some"}), "#!foo\n/*@preserve*/");
});
it("Should have no problem on multiple calls", function() {
const options = {
comments: /ok/
};
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
assert.strictEqual(UglifyJS.parse("/* ok */ function a(){}").print_to_string(options), "/* ok */function a(){}");
});
it("Should handle shebang and preamble correctly", function() {
var code = UglifyJS.minify("#!/usr/bin/node\nvar x = 10;", {
output: { preamble: "/* Build */" }
}).code;
assert.strictEqual(code, "#!/usr/bin/node\n/* Build */\nvar x=10;");
});
it("Should handle preamble without shebang correctly", function() {
var code = UglifyJS.minify("var x = 10;", {
output: { preamble: "/* Build */" }
}).code;
assert.strictEqual(code, "/* Build */\nvar x=10;");
});
});
describe("Huge number of comments.", function() {
it("Should parse and compress code with thousands of consecutive comments", function() {
var js = "function lots_of_comments(x) { return 7 -";
for (var i = 1; i <= 5000; ++i) js += "// " + i + "\n";
for (; i <= 10000; ++i) js += "/* " + i + " */ /**/";
js += "x; }";
var result = UglifyJS.minify(js, { mangle: false });
assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
});
});
});

View File

@@ -1,9 +1,9 @@
var assert = require("assert"); var assert = require("assert");
var uglify = require("../node"); var UglifyJS = require("../node");
describe("Directives", function() { describe("Directives", function() {
it ("Should allow tokenizer to store directives state", function() { it ("Should allow tokenizer to store directives state", function() {
var tokenizer = uglify.tokenizer("", "foo.js"); var tokenizer = UglifyJS.tokenizer("", "foo.js");
// Stack level 0 // Stack level 0
assert.strictEqual(tokenizer.has_directive("use strict"), false); assert.strictEqual(tokenizer.has_directive("use strict"), false);
@@ -161,13 +161,13 @@ describe("Directives", function() {
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
// Fail parser deliberately to get state at failure // Fail parser deliberately to get state at failure
var tokenizer = uglify.tokenizer(tests[i].input + "]", "foo.js"); var tokenizer = UglifyJS.tokenizer(tests[i].input + "]", "foo.js");
try { try {
var parser = uglify.parse(tokenizer); var parser = UglifyJS.parse(tokenizer);
throw new Error("Expected parser to fail"); throw new Error("Expected parser to fail");
} catch (e) { } catch (e) {
assert.strictEqual(e instanceof uglify.JS_Parse_Error, true); assert.strictEqual(e instanceof UglifyJS.JS_Parse_Error, true);
assert.strictEqual(e.message, "Unexpected token: punc (])"); assert.strictEqual(e.message, "Unexpected token: punc (])");
} }
@@ -186,7 +186,7 @@ describe("Directives", function() {
["'tests';\n\n", true], ["'tests';\n\n", true],
["\n\n\"use strict\";\n\n", true] ["\n\n\"use strict\";\n\n", true]
].forEach(function(test) { ].forEach(function(test) {
var out = uglify.OutputStream(); var out = UglifyJS.OutputStream();
out.print(test[0]); out.print(test[0]);
out.print_string("", null, true); out.print_string("", null, true);
assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]); assert.strictEqual(out.get() === test[0] + ';""', test[1], test[0]);
@@ -195,7 +195,7 @@ describe("Directives", function() {
it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() { it("Should only print 2 semicolons spread over 2 lines in beautify mode", function() {
assert.strictEqual( assert.strictEqual(
uglify.minify( UglifyJS.minify(
'"use strict";\'use strict\';"use strict";"use strict";;\'use strict\';console.log(\'use strict\');', '"use strict";\'use strict\';"use strict";"use strict";;\'use strict\';console.log(\'use strict\');',
{output: {beautify: true, quote_style: 3}, compress: false} {output: {beautify: true, quote_style: 3}, compress: false}
).code, ).code,
@@ -225,7 +225,7 @@ describe("Directives", function() {
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
assert.strictEqual( assert.strictEqual(
uglify.minify(tests[i][0], {compress: false, mangle: false}).code, UglifyJS.minify(tests[i][0], {compress: false, mangle: false}).code,
tests[i][1], tests[i][1],
tests[i][0] tests[i][0]
); );
@@ -233,7 +233,7 @@ describe("Directives", function() {
}); });
it("Should add double semicolon when relying on automatic semicolon insertion", function() { it("Should add double semicolon when relying on automatic semicolon insertion", function() {
var code = uglify.minify('"use strict";"use\\x20strict";', var code = UglifyJS.minify('"use strict";"use\\x20strict";',
{output: {semicolons: false}, compress: false} {output: {semicolons: false}, compress: false}
).code; ).code;
assert.strictEqual(code, '"use strict";;"use strict"\n'); assert.strictEqual(code, '"use strict";;"use strict"\n');
@@ -340,7 +340,7 @@ describe("Directives", function() {
]; ];
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
assert.strictEqual( assert.strictEqual(
uglify.minify(tests[i][0], {output:{quote_style: tests[i][1]}, compress: false}).code, UglifyJS.minify(tests[i][0], {output:{quote_style: tests[i][1]}, compress: false}).code,
tests[i][2], tests[i][2],
tests[i][0] + " using mode " + tests[i][1] tests[i][0] + " using mode " + tests[i][1]
); );
@@ -372,7 +372,7 @@ describe("Directives", function() {
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
assert.strictEqual( assert.strictEqual(
uglify.minify(tests[i][0]).code, UglifyJS.minify(tests[i][0]).code,
tests[i][1], tests[i][1],
tests[i][0] tests[i][0]
); );

View File

@@ -1,5 +1,5 @@
var UglifyJS = require("../node");
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../node");
describe("Getters and setters", function() { describe("Getters and setters", function() {
it("Should not accept operator symbols as getter/setter name", function() { it("Should not accept operator symbols as getter/setter name", function() {
@@ -61,29 +61,24 @@ describe("Getters and setters", function() {
return results; return results;
}; };
var testCase = function(data) { var testCase = function(data) {
return function() { return function() {
UglifyJS.parse(data.code); UglifyJS.parse(data.code);
}; };
}; };
var fail = function(data) { var fail = function(data) {
return function (e) { return function(e) {
return e instanceof UglifyJS.JS_Parse_Error && return e instanceof UglifyJS.JS_Parse_Error
e.message === "Unexpected token: operator (" + data.operator + ")"; && e.message === "Unexpected token: operator (" + data.operator + ")";
}; };
}; };
var errorMessage = function(data) { var errorMessage = function(data) {
return "Expected but didn't get a syntax error while parsing following line:\n" + data.code; return "Expected but didn't get a syntax error while parsing following line:\n" + data.code;
}; };
var tests = generator(); var tests = generator();
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
var test = tests[i]; var test = tests[i];
assert.throws(testCase(test), fail(test), errorMessage(test)); assert.throws(testCase(test), fail(test), errorMessage(test));
} }
}); });
}); });

View File

@@ -1,14 +0,0 @@
var Uglify = require('../../');
var assert = require("assert");
describe("Huge number of comments.", function() {
it("Should parse and compress code with thousands of consecutive comments", function() {
var js = 'function lots_of_comments(x) { return 7 -';
var i;
for (i = 1; i <= 5000; ++i) { js += "// " + i + "\n"; }
for (; i <= 10000; ++i) { js += "/* " + i + " */ /**/"; }
js += "x; }";
var result = Uglify.minify(js, { mangle: false });
assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
});
});

21
test/mocha/ie8.js Normal file
View File

@@ -0,0 +1,21 @@
var assert = require("assert");
var UglifyJS = require("../..");
describe("ie8", function() {
it("Should be able to minify() with undefined as catch parameter in a try...catch statement", function() {
assert.strictEqual(
UglifyJS.minify([
"function a(b){",
" try {",
" throw 'Stuff';",
" } catch (undefined) {",
" console.log('caught: ' + undefined);",
" }",
" console.log('undefined is ' + undefined);",
" return b === undefined;",
"};",
].join("\n")).code,
'function a(o){try{throw"Stuff"}catch(o){console.log("caught: "+o)}return console.log("undefined is "+void 0),void 0===o}'
);
});
});

View File

@@ -1,68 +0,0 @@
var assert = require("assert");
var Uglify = require("../../");
var SourceMapConsumer = require("source-map").SourceMapConsumer;
function getMap() {
return {
"version": 3,
"sources": ["index.js"],
"names": [],
"mappings": ";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ",
"file": "bundle.js",
"sourcesContent": ["let foo = x => \"foo \" + x;\nconsole.log(foo(\"bar\"));"]
};
}
function prepareMap(sourceMap) {
var code = [
'"use strict";',
"",
"var foo = function foo(x) {",
' return "foo " + x;',
"};",
'console.log(foo("bar"));',
"",
"//# sourceMappingURL=bundle.js.map",
].join("\n");
var result = Uglify.minify(code, {
sourceMap: {
content: sourceMap,
includeSources: true,
}
});
if (result.error) throw result.error;
return new SourceMapConsumer(result.map);
}
describe("input sourcemaps", function() {
it("Should copy over original sourcesContent", function() {
var orig = getMap();
var map = prepareMap(orig);
assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]);
});
it("Should copy sourcesContent if sources are relative", function() {
var relativeMap = getMap();
relativeMap.sources = ['./index.js'];
var map = prepareMap(relativeMap);
assert.notEqual(map.sourcesContent, null);
assert.equal(map.sourcesContent.length, 1);
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
});
it("Should not have invalid mappings from inputSourceMap (issue #882)", function() {
var map = prepareMap(getMap());
// The original source has only 2 lines, check that mappings don't have more lines
var msg = "Mapping should not have higher line number than the original file had";
map.eachMapping(function(mapping) {
assert.ok(mapping.originalLine <= 2, msg);
});
map.allGeneratedPositionsFor({
source: "index.js",
line: 1,
column: 1
}).forEach(function(pos) {
assert.ok(pos.line <= 2, msg);
});
});
});

View File

@@ -1,5 +1,5 @@
var Uglify = require('../../');
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../..");
describe("let", function() { describe("let", function() {
this.timeout(30000); this.timeout(30000);
@@ -10,7 +10,7 @@ describe("let", function() {
s += "var v" + i + "=0;"; s += "var v" + i + "=0;";
} }
s += '}'; s += '}';
var result = Uglify.minify(s, { var result = UglifyJS.minify(s, {
compress: false compress: false
}).code; }).code;
@@ -39,7 +39,7 @@ describe("let", function() {
for (var i = 0; i < 18000; i++) { for (var i = 0; i < 18000; i++) {
s += "v.b" + i + ";"; s += "v.b" + i + ";";
} }
var result = Uglify.minify(s, { var result = UglifyJS.minify(s, {
compress: false, compress: false,
ie8: true, ie8: true,
mangle: { mangle: {

View File

@@ -1,5 +1,5 @@
var Uglify = require("../node");
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../node");
describe("line-endings", function() { describe("line-endings", function() {
var options = { var options = {
@@ -14,19 +14,19 @@ describe("line-endings", function() {
it("Should parse LF line endings", function() { it("Should parse LF line endings", function() {
var js = '/*!one\n2\n3*///comment\nfunction f(x) {\n if (x)\n//comment\n return 3;\n}\n'; var js = '/*!one\n2\n3*///comment\nfunction f(x) {\n if (x)\n//comment\n return 3;\n}\n';
var result = Uglify.minify(js, options); var result = UglifyJS.minify(js, options);
assert.strictEqual(result.code, expected_code); assert.strictEqual(result.code, expected_code);
}); });
it("Should parse CR/LF line endings", function() { it("Should parse CR/LF line endings", function() {
var js = '/*!one\r\n2\r\n3*///comment\r\nfunction f(x) {\r\n if (x)\r\n//comment\r\n return 3;\r\n}\r\n'; var js = '/*!one\r\n2\r\n3*///comment\r\nfunction f(x) {\r\n if (x)\r\n//comment\r\n return 3;\r\n}\r\n';
var result = Uglify.minify(js, options); var result = UglifyJS.minify(js, options);
assert.strictEqual(result.code, expected_code); assert.strictEqual(result.code, expected_code);
}); });
it("Should parse CR line endings", function() { it("Should parse CR line endings", function() {
var js = '/*!one\r2\r3*///comment\rfunction f(x) {\r if (x)\r//comment\r return 3;\r}\r'; var js = '/*!one\r2\r3*///comment\rfunction f(x) {\r if (x)\r//comment\r return 3;\r}\r';
var result = Uglify.minify(js, options); var result = UglifyJS.minify(js, options);
assert.strictEqual(result.code, expected_code); assert.strictEqual(result.code, expected_code);
}); });
@@ -44,16 +44,15 @@ describe("line-endings", function() {
] ]
var test = function(input) { var test = function(input) {
return function() { return function() {
Uglify.parse(input); UglifyJS.parse(input);
} }
} }
var fail = function(e) { var fail = function(e) {
return e instanceof Uglify.JS_Parse_Error && return e instanceof UglifyJS.JS_Parse_Error
e.message === "Unexpected line terminator"; && e.message === "Unexpected line terminator";
} }
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
assert.throws(test(inputs[i]), fail); assert.throws(test(inputs[i]), fail);
} }
}); });
}); });

View File

@@ -1,22 +1,22 @@
var Uglify = require('../../');
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../..");
describe("Input file as map", function() { describe("Input file as map", function() {
it("Should accept object", function() { it("Should accept object", function() {
var jsMap = { var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};' '/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
}; };
var result = Uglify.minify(jsMap, {sourceMap: true}); var result = UglifyJS.minify(jsMap, {sourceMap: true});
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
assert.deepEqual(map.sources, ['/scripts/foo.js']); assert.deepEqual(map.sources, ['/scripts/foo.js']);
assert.strictEqual(map.file, undefined); assert.strictEqual(map.file, undefined);
result = Uglify.minify(jsMap); result = UglifyJS.minify(jsMap);
assert.strictEqual(result.map, undefined); assert.strictEqual(result.map, undefined);
result = Uglify.minify(jsMap, {sourceMap: {filename: 'out.js'}}); result = UglifyJS.minify(jsMap, {sourceMap: {filename: 'out.js'}});
map = JSON.parse(result.map); map = JSON.parse(result.map);
assert.strictEqual(map.file, 'out.js'); assert.strictEqual(map.file, 'out.js');
}); });
@@ -26,7 +26,7 @@ describe("Input file as map", function() {
'var foo = {"x": 1, y: 2, \'z\': 3};', 'var foo = {"x": 1, y: 2, \'z\': 3};',
'var bar = 15;' 'var bar = 15;'
]; ];
var result = Uglify.minify(jsSeq, {sourceMap: true}); var result = UglifyJS.minify(jsSeq, {sourceMap: true});
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;');
@@ -37,7 +37,7 @@ describe("Input file as map", function() {
var jsMap = { var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};' '/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
}; };
var result = Uglify.minify(jsMap, {sourceMap: {includeSources: true}}); var result = UglifyJS.minify(jsMap, {sourceMap: {includeSources: true}});
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');

View File

@@ -1,7 +1,7 @@
var Uglify = require('../../');
var assert = require("assert"); var assert = require("assert");
var readFileSync = require("fs").readFileSync; var readFileSync = require("fs").readFileSync;
var run_code = require("../sandbox").run_code; var run_code = require("../sandbox").run_code;
var UglifyJS = require("../../");
function read(path) { function read(path) {
return readFileSync(path, "utf8"); return readFileSync(path, "utf8");
@@ -10,14 +10,14 @@ function read(path) {
describe("minify", function() { describe("minify", function() {
it("Should test basic sanity of minify with default options", function() { it("Should test basic sanity of minify with default options", function() {
var js = 'function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }'; var js = 'function foo(bar) { if (bar) return 3; else return 7; var u = not_called(); }';
var result = Uglify.minify(js); var result = UglifyJS.minify(js);
assert.strictEqual(result.code, 'function foo(n){return n?3:7}'); assert.strictEqual(result.code, 'function foo(n){return n?3:7}');
}); });
it("Should skip inherited keys from `files`", function() { it("Should skip inherited keys from `files`", function() {
var files = Object.create({ skip: this }); var files = Object.create({ skip: this });
files[0] = "alert(1 + 1)"; files[0] = "alert(1 + 1)";
var result = Uglify.minify(files); var result = UglifyJS.minify(files);
assert.strictEqual(result.code, "alert(2);"); assert.strictEqual(result.code, "alert(2);");
}); });
@@ -32,7 +32,7 @@ describe("minify", function() {
"qux.js", "qux.js",
].forEach(function(file) { ].forEach(function(file) {
var code = read("test/input/issue-1242/" + file); var code = read("test/input/issue-1242/" + file);
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
mangle: { mangle: {
cache: cache, cache: cache,
toplevel: true toplevel: true
@@ -65,7 +65,7 @@ describe("minify", function() {
"qux.js", "qux.js",
].forEach(function(file) { ].forEach(function(file) {
var code = read("test/input/issue-1242/" + file); var code = read("test/input/issue-1242/" + file);
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
mangle: { mangle: {
toplevel: true toplevel: true
}, },
@@ -96,7 +96,7 @@ describe("minify", function() {
'"xxyyy";var j={t:2,u:3},k=4;', '"xxyyy";var j={t:2,u:3},k=4;',
'console.log(i.s,j.t,j.u,k);', 'console.log(i.s,j.t,j.u,k);',
].forEach(function(code) { ].forEach(function(code) {
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
mangle: { mangle: {
properties: true, properties: true,
@@ -117,15 +117,15 @@ describe("minify", function() {
}); });
it("Should not parse invalid use of reserved words", function() { it("Should not parse invalid use of reserved words", function() {
assert.strictEqual(Uglify.minify("function enum(){}").error, undefined); assert.strictEqual(UglifyJS.minify("function enum(){}").error, undefined);
assert.strictEqual(Uglify.minify("function static(){}").error, undefined); assert.strictEqual(UglifyJS.minify("function static(){}").error, undefined);
assert.strictEqual(Uglify.minify("function this(){}").error.message, "Unexpected token: name (this)"); assert.strictEqual(UglifyJS.minify("function this(){}").error.message, "Unexpected token: name (this)");
}); });
describe("keep_quoted_props", function() { describe("keep_quoted_props", function() {
it("Should preserve quotes in object literals", function() { it("Should preserve quotes in object literals", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};'; var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = Uglify.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: true keep_quoted_props: true
}}); }});
@@ -134,7 +134,7 @@ describe("minify", function() {
it("Should preserve quote styles when quote_style is 3", function() { it("Should preserve quote styles when quote_style is 3", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};'; var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = Uglify.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: true, keep_quoted_props: true,
quote_style: 3 quote_style: 3
@@ -144,7 +144,7 @@ describe("minify", function() {
it("Should not preserve quotes in object literals when disabled", function() { it("Should not preserve quotes in object literals when disabled", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};'; var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = Uglify.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: false, keep_quoted_props: false,
quote_style: 3 quote_style: 3
@@ -156,7 +156,7 @@ describe("minify", function() {
describe("mangleProperties", function() { describe("mangleProperties", function() {
it("Shouldn't mangle quoted properties", function() { it("Shouldn't mangle quoted properties", function() {
var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};'; var js = 'a["foo"] = "bar"; a.color = "red"; x = {"bar": 10};';
var result = Uglify.minify(js, { var result = UglifyJS.minify(js, {
compress: { compress: {
properties: false properties: false
}, },
@@ -174,7 +174,7 @@ describe("minify", function() {
'a["foo"]="bar",a.a="red",x={"bar":10};'); 'a["foo"]="bar",a.a="red",x={"bar":10};');
}); });
it("Should not mangle quoted property within dead code", function() { it("Should not mangle quoted property within dead code", function() {
var result = Uglify.minify('({ "keep": 1 }); g.keep = g.change;', { var result = UglifyJS.minify('({ "keep": 1 }); g.keep = g.change;', {
mangle: { mangle: {
properties: { properties: {
keep_quoted: true keep_quoted: true
@@ -188,7 +188,7 @@ describe("minify", function() {
describe("#__PURE__", function() { describe("#__PURE__", function() {
it("should drop #__PURE__ hint after use", function() { it("should drop #__PURE__ hint after use", function() {
var result = Uglify.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', { var result = UglifyJS.minify('//@__PURE__ comment1 #__PURE__ comment2\n foo(), bar();', {
output: { output: {
comments: "all", comments: "all",
beautify: false, beautify: false,
@@ -198,7 +198,7 @@ describe("minify", function() {
assert.strictEqual(code, "// comment1 comment2\nbar();"); assert.strictEqual(code, "// comment1 comment2\nbar();");
}); });
it("should drop #__PURE__ hint if function is retained", function() { it("should drop #__PURE__ hint if function is retained", function() {
var result = Uglify.minify("var a = /*#__PURE__*/(function(){ foo(); })();", { var result = UglifyJS.minify("var a = /*#__PURE__*/(function(){ foo(); })();", {
output: { output: {
comments: "all", comments: "all",
beautify: false, beautify: false,
@@ -211,7 +211,7 @@ describe("minify", function() {
describe("JS_Parse_Error", function() { describe("JS_Parse_Error", function() {
it("should return syntax error", function() { it("should return syntax error", function() {
var result = Uglify.minify("function f(a{}"); var result = UglifyJS.minify("function f(a{}");
var err = result.error; var err = result.error;
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»"); assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»");
@@ -220,7 +220,7 @@ describe("minify", function() {
assert.strictEqual(err.col, 12); assert.strictEqual(err.col, 12);
}); });
it("should reject duplicated label name", function() { it("should reject duplicated label name", function() {
var result = Uglify.minify("L:{L:{}}"); var result = UglifyJS.minify("L:{L:{}}");
var err = result.error; var err = result.error;
assert.ok(err instanceof Error); assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Label L defined twice"); assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Label L defined twice");
@@ -232,7 +232,7 @@ describe("minify", function() {
describe("global_defs", function() { describe("global_defs", function() {
it("should throw for non-trivial expressions", function() { it("should throw for non-trivial expressions", function() {
var result = Uglify.minify("alert(42);", { var result = UglifyJS.minify("alert(42);", {
compress: { compress: {
global_defs: { global_defs: {
"@alert": "debugger" "@alert": "debugger"
@@ -246,7 +246,7 @@ describe("minify", function() {
it("should skip inherited properties", function() { it("should skip inherited properties", function() {
var foo = Object.create({ skip: this }); var foo = Object.create({ skip: this });
foo.bar = 42; foo.bar = 42;
var result = Uglify.minify("alert(FOO);", { var result = UglifyJS.minify("alert(FOO);", {
compress: { compress: {
global_defs: { global_defs: {
FOO: foo FOO: foo
@@ -266,7 +266,7 @@ describe("minify", function() {
"}", "}",
"f();", "f();",
].join("\n"); ].join("\n");
var ast = Uglify.minify(code, { var ast = UglifyJS.minify(code, {
compress: false, compress: false,
mangle: false, mangle: false,
output: { output: {
@@ -279,7 +279,7 @@ describe("minify", function() {
assert.strictEqual(ast.body[0].body.length, 2); assert.strictEqual(ast.body[0].body.length, 2);
assert.strictEqual(ast.body[0].body[0].TYPE, "SimpleStatement"); assert.strictEqual(ast.body[0].body[0].TYPE, "SimpleStatement");
var stat = ast.body[0].body[0]; var stat = ast.body[0].body[0];
Uglify.minify(ast, { UglifyJS.minify(ast, {
compress: { compress: {
sequences: false sequences: false
}, },
@@ -294,7 +294,7 @@ describe("minify", function() {
it("Should be repeatable", function() { it("Should be repeatable", function() {
var code = "!function(x){return x(x)}(y);"; var code = "!function(x){return x(x)}(y);";
for (var i = 0; i < 2; i++) { for (var i = 0; i < 2; i++) {
assert.strictEqual(Uglify.minify(code, { assert.strictEqual(UglifyJS.minify(code, {
compress: { compress: {
toplevel: true, toplevel: true,
}, },
@@ -307,7 +307,7 @@ describe("minify", function() {
describe("enclose", function() { describe("enclose", function() {
var code = read("test/input/enclose/input.js"); var code = read("test/input/enclose/input.js");
it("Should work with true", function() { it("Should work with true", function() {
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
enclose: true, enclose: true,
mangle: false, mangle: false,
@@ -316,7 +316,7 @@ describe("minify", function() {
assert.strictEqual(result.code, '(function(){function enclose(){console.log("test enclose")}enclose()})();'); assert.strictEqual(result.code, '(function(){function enclose(){console.log("test enclose")}enclose()})();');
}); });
it("Should work with arg", function() { it("Should work with arg", function() {
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
enclose: 'undefined', enclose: 'undefined',
mangle: false, mangle: false,
@@ -325,7 +325,7 @@ describe("minify", function() {
assert.strictEqual(result.code, '(function(undefined){function enclose(){console.log("test enclose")}enclose()})();'); assert.strictEqual(result.code, '(function(undefined){function enclose(){console.log("test enclose")}enclose()})();');
}); });
it("Should work with arg:value", function() { it("Should work with arg:value", function() {
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
enclose: 'window,undefined:window', enclose: 'window,undefined:window',
mangle: false, mangle: false,
@@ -334,7 +334,7 @@ describe("minify", function() {
assert.strictEqual(result.code, '(function(window,undefined){function enclose(){console.log("test enclose")}enclose()})(window);'); assert.strictEqual(result.code, '(function(window,undefined){function enclose(){console.log("test enclose")}enclose()})(window);');
}); });
it("Should work alongside wrap", function() { it("Should work alongside wrap", function() {
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
enclose: 'window,undefined:window', enclose: 'window,undefined:window',
mangle: false, mangle: false,

View File

@@ -1,22 +1,21 @@
var assert = require("assert"); var assert = require("assert");
var uglify = require("../node"); var UglifyJS = require("../node");
describe("Number literals", function () { describe("Number literals", function() {
it("Should not allow legacy octal literals in strict mode", function() { it("Should not allow legacy octal literals in strict mode", function() {
var inputs = [ var inputs = [
'"use strict";00;', '"use strict";00;',
'"use strict"; var foo = 00;' '"use strict"; var foo = 00;'
]; ];
var test = function(input) { var test = function(input) {
return function() { return function() {
uglify.parse(input); UglifyJS.parse(input);
}
} }
};
var error = function(e) { var error = function(e) {
return e instanceof uglify.JS_Parse_Error && return e instanceof UglifyJS.JS_Parse_Error
e.message === "Legacy octal literals are not allowed in strict mode"; && e.message === "Legacy octal literals are not allowed in strict mode";
} };
for (var i = 0; i < inputs.length; i++) { for (var i = 0; i < inputs.length; i++) {
assert.throws(test(inputs[i]), error, inputs[i]); assert.throws(test(inputs[i]), error, inputs[i]);
} }

View File

@@ -1,5 +1,5 @@
var UglifyJS = require("../node");
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../..");
describe("operator", function() { describe("operator", function() {
it("Should handle mixing of ++/+/--/- correctly", function() { it("Should handle mixing of ++/+/--/- correctly", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert"); var assert = require("assert");
var uglify = require("../../"); var UglifyJS = require("../..");
describe("parentheses", function() { describe("parentheses", function() {
it("Should add trailing parentheses for new expressions with zero arguments in beautify mode", function() { it("Should add trailing parentheses for new expressions with zero arguments in beautify mode", function() {
@@ -33,7 +33,7 @@ describe("parentheses", function() {
]; ];
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
assert.strictEqual( assert.strictEqual(
uglify.minify(tests[i], { UglifyJS.minify(tests[i], {
output: {beautify: true}, output: {beautify: true},
compress: false, compress: false,
mangle: false mangle: false
@@ -74,7 +74,7 @@ describe("parentheses", function() {
]; ];
for (var i = 0; i < tests.length; i++) { for (var i = 0; i < tests.length; i++) {
assert.strictEqual( assert.strictEqual(
uglify.minify(tests[i], { UglifyJS.minify(tests[i], {
output: {beautify: false}, output: {beautify: false},
compress: false, compress: false,
mangle: false mangle: false
@@ -94,7 +94,7 @@ describe("parentheses", function() {
code = code.concat(code); code = code.concat(code);
} }
code = code.join(""); code = code.join("");
var result = uglify.minify(code, { var result = UglifyJS.minify(code, {
compress: false, compress: false,
mangle: false, mangle: false,
}); });

View File

@@ -1,21 +0,0 @@
var assert = require("assert");
var uglify = require("../../");
describe("screw-ie8", function () {
it("Should be able to minify() with undefined as catch parameter in a try...catch statement", function () {
assert.strictEqual(
uglify.minify(
"function a(b){\
try {\
throw 'Stuff';\
} catch (undefined) {\
console.log('caught: ' + undefined);\
}\
console.log('undefined is ' + undefined);\
return b === undefined;\
};"
).code,
'function a(o){try{throw"Stuff"}catch(o){console.log("caught: "+o)}return console.log("undefined is "+void 0),void 0===o}'
);
});
});

View File

@@ -1,19 +1,52 @@
var assert = require("assert"); var assert = require("assert");
var readFileSync = require("fs").readFileSync; var readFileSync = require("fs").readFileSync;
var Uglify = require("../../"); var SourceMapConsumer = require("source-map").SourceMapConsumer;
var UglifyJS = require("../..");
function read(path) { function read(path) {
return readFileSync(path, "utf8"); return readFileSync(path, "utf8");
} }
function source_map(code) { function source_map(code) {
return JSON.parse(Uglify.minify(code, { return JSON.parse(UglifyJS.minify(code, {
compress: false, compress: false,
mangle: false, mangle: false,
sourceMap: true, sourceMap: true,
}).map); }).map);
} }
function get_map() {
return {
"version": 3,
"sources": ["index.js"],
"names": [],
"mappings": ";;AAAA,IAAI,MAAM,SAAN,GAAM;AAAA,SAAK,SAAS,CAAd;AAAA,CAAV;AACA,QAAQ,GAAR,CAAY,IAAI,KAAJ,CAAZ",
"file": "bundle.js",
"sourcesContent": ["let foo = x => \"foo \" + x;\nconsole.log(foo(\"bar\"));"]
};
}
function prepare_map(sourceMap) {
var code = [
'"use strict";',
"",
"var foo = function foo(x) {",
' return "foo " + x;',
"};",
'console.log(foo("bar"));',
"",
"//# sourceMappingURL=bundle.js.map",
].join("\n");
var result = UglifyJS.minify(code, {
sourceMap: {
content: sourceMap,
includeSources: true,
}
});
if (result.error) throw result.error;
return new SourceMapConsumer(result.map);
}
describe("sourcemaps", function() { describe("sourcemaps", function() {
it("Should give correct version", function() { it("Should give correct version", function() {
var map = source_map("var x = 1 + 1;"); var map = source_map("var x = 1 + 1;");
@@ -36,7 +69,7 @@ describe("sourcemaps", function() {
}); });
it("Should mark array/object literals", function() { it("Should mark array/object literals", function() {
var result = Uglify.minify([ var result = UglifyJS.minify([
"var obj = {};", "var obj = {};",
"obj.wat([]);", "obj.wat([]);",
].join("\n"), { ].join("\n"), {
@@ -48,9 +81,21 @@ describe("sourcemaps", function() {
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}'); assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["wat"],"mappings":"CAAU,IACNA,IAAI"}');
}); });
it("Should give correct sourceRoot", function() {
var code = "console.log(42);";
var result = UglifyJS.minify(code, {
sourceMap: {
root: "//foo.bar/",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, code);
assert.strictEqual(result.map, '{"version":3,"sources":["0"],"names":["console","log"],"mappings":"AAAAA,QAAQC,IAAI","sourceRoot":"//foo.bar/"}');
});
describe("inSourceMap", function() { describe("inSourceMap", function() {
it("Should read the given string filename correctly when sourceMapIncludeSources is enabled (#1236)", function() { it("Should read the given string filename correctly when sourceMapIncludeSources is enabled", function() {
var result = Uglify.minify(read("./test/input/issue-1236/simple.js"), { var result = UglifyJS.minify(read("./test/input/issue-1236/simple.js"), {
sourceMap: { sourceMap: {
content: read("./test/input/issue-1236/simple.js.map"), content: read("./test/input/issue-1236/simple.js.map"),
filename: "simple.min.js", filename: "simple.min.js",
@@ -64,7 +109,7 @@ describe("sourcemaps", function() {
assert.equal(map.sourcesContent[0], 'let foo = x => "foo " + x;\nconsole.log(foo("bar"));'); assert.equal(map.sourcesContent[0], 'let foo = x => "foo " + x;\nconsole.log(foo("bar"));');
}); });
it("Should process inline source map", function() { it("Should process inline source map", function() {
var result = Uglify.minify(read("./test/input/issue-520/input.js"), { var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
compress: { toplevel: true }, compress: { toplevel: true },
sourceMap: { sourceMap: {
content: "inline", content: "inline",
@@ -76,13 +121,13 @@ describe("sourcemaps", function() {
assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-520/output.js", "utf8")); assert.strictEqual(result.code + "\n", readFileSync("test/input/issue-520/output.js", "utf8"));
}); });
it("Should warn for missing inline source map", function() { it("Should warn for missing inline source map", function() {
var warn_function = Uglify.AST_Node.warn_function; var warn_function = UglifyJS.AST_Node.warn_function;
var warnings = []; var warnings = [];
Uglify.AST_Node.warn_function = function(txt) { UglifyJS.AST_Node.warn_function = function(txt) {
warnings.push(txt); warnings.push(txt);
}; };
try { try {
var result = Uglify.minify(read("./test/input/issue-1323/sample.js"), { var result = UglifyJS.minify(read("./test/input/issue-1323/sample.js"), {
mangle: false, mangle: false,
sourceMap: { sourceMap: {
content: "inline" content: "inline"
@@ -92,17 +137,17 @@ describe("sourcemaps", function() {
assert.strictEqual(warnings.length, 1); assert.strictEqual(warnings.length, 1);
assert.strictEqual(warnings[0], "inline source map not found: 0"); assert.strictEqual(warnings[0], "inline source map not found: 0");
} finally { } finally {
Uglify.AST_Node.warn_function = warn_function; UglifyJS.AST_Node.warn_function = warn_function;
} }
}); });
it("Should handle multiple input and inline source map", function() { it("Should handle multiple input and inline source map", function() {
var warn_function = Uglify.AST_Node.warn_function; var warn_function = UglifyJS.AST_Node.warn_function;
var warnings = []; var warnings = [];
Uglify.AST_Node.warn_function = function(txt) { UglifyJS.AST_Node.warn_function = function(txt) {
warnings.push(txt); warnings.push(txt);
}; };
try { try {
var result = Uglify.minify([ var result = UglifyJS.minify([
read("./test/input/issue-520/input.js"), read("./test/input/issue-520/input.js"),
read("./test/input/issue-1323/sample.js"), read("./test/input/issue-1323/sample.js"),
], { ], {
@@ -119,11 +164,11 @@ describe("sourcemaps", function() {
assert.strictEqual(warnings.length, 1); assert.strictEqual(warnings.length, 1);
assert.strictEqual(warnings[0], "inline source map not found: 1"); assert.strictEqual(warnings[0], "inline source map not found: 1");
} finally { } finally {
Uglify.AST_Node.warn_function = warn_function; UglifyJS.AST_Node.warn_function = warn_function;
} }
}); });
it("Should drop source contents for includeSources=false", function() { it("Should drop source contents for includeSources=false", function() {
var result = Uglify.minify(read("./test/input/issue-520/input.js"), { var result = UglifyJS.minify(read("./test/input/issue-520/input.js"), {
compress: false, compress: false,
mangle: false, mangle: false,
sourceMap: { sourceMap: {
@@ -134,7 +179,7 @@ describe("sourcemaps", function() {
if (result.error) throw result.error; if (result.error) throw result.error;
var map = JSON.parse(result.map); var map = JSON.parse(result.map);
assert.strictEqual(map.sourcesContent.length, 1); assert.strictEqual(map.sourcesContent.length, 1);
result = Uglify.minify(result.code, { result = UglifyJS.minify(result.code, {
compress: false, compress: false,
mangle: false, mangle: false,
sourceMap: { sourceMap: {
@@ -149,7 +194,7 @@ describe("sourcemaps", function() {
describe("sourceMapInline", function() { describe("sourceMapInline", function() {
it("Should append source map to output js when sourceMapInline is enabled", function() { it("Should append source map to output js when sourceMapInline is enabled", function() {
var result = Uglify.minify('var a = function(foo) { return foo; };', { var result = UglifyJS.minify('var a = function(foo) { return foo; };', {
sourceMap: { sourceMap: {
url: "inline" url: "inline"
} }
@@ -160,13 +205,13 @@ describe("sourcemaps", function() {
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0="); "//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BIn0=");
}); });
it("Should not append source map to output js when sourceMapInline is not enabled", function() { it("Should not append source map to output js when sourceMapInline is not enabled", function() {
var result = Uglify.minify('var a = function(foo) { return foo; };'); var result = UglifyJS.minify('var a = function(foo) { return foo; };');
if (result.error) throw result.error; if (result.error) throw result.error;
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=function(n){return n};"); assert.strictEqual(code, "var a=function(n){return n};");
}); });
it("Should work with max_line_len", function() { it("Should work with max_line_len", function() {
var result = Uglify.minify(read("./test/input/issue-505/input.js"), { var result = UglifyJS.minify(read("./test/input/issue-505/input.js"), {
output: { output: {
max_line_len: 20 max_line_len: 20
}, },
@@ -182,7 +227,7 @@ describe("sourcemaps", function() {
"var tëst = '→unicøde←';", "var tëst = '→unicøde←';",
"alert(tëst);", "alert(tëst);",
].join("\n"); ].join("\n");
var result = Uglify.minify(code, { var result = UglifyJS.minify(code, {
sourceMap: { sourceMap: {
includeSources: true, includeSources: true,
url: "inline", url: "inline",
@@ -196,7 +241,7 @@ describe("sourcemaps", function() {
map = JSON.parse(new Buffer(encoded, "base64").toString()); map = JSON.parse(new Buffer(encoded, "base64").toString());
assert.strictEqual(map.sourcesContent.length, 1); assert.strictEqual(map.sourcesContent.length, 1);
assert.strictEqual(map.sourcesContent[0], code); assert.strictEqual(map.sourcesContent[0], code);
result = Uglify.minify(result.code, { result = UglifyJS.minify(result.code, {
sourceMap: { sourceMap: {
content: "inline", content: "inline",
includeSources: true, includeSources: true,
@@ -209,4 +254,37 @@ describe("sourcemaps", function() {
assert.strictEqual(map.names[1], "alert"); assert.strictEqual(map.names[1], "alert");
}); });
}); });
describe("input sourcemaps", function() {
it("Should copy over original sourcesContent", function() {
var orig = get_map();
var map = prepare_map(orig);
assert.equal(map.sourceContentFor("index.js"), orig.sourcesContent[0]);
});
it("Should copy sourcesContent if sources are relative", function() {
var relativeMap = get_map();
relativeMap.sources = ['./index.js'];
var map = prepare_map(relativeMap);
assert.notEqual(map.sourcesContent, null);
assert.equal(map.sourcesContent.length, 1);
assert.equal(map.sourceContentFor("index.js"), relativeMap.sourcesContent[0]);
});
it("Should not have invalid mappings from inputSourceMap", function() {
var map = prepare_map(get_map());
// The original source has only 2 lines, check that mappings don't have more lines
var msg = "Mapping should not have higher line number than the original file had";
map.eachMapping(function(mapping) {
assert.ok(mapping.originalLine <= 2, msg);
});
map.allGeneratedPositionsFor({
source: "index.js",
line: 1,
column: 1
}).forEach(function(pos) {
assert.ok(pos.line <= 2, msg);
});
});
});
}); });

View File

@@ -1,6 +1,6 @@
var assert = require("assert"); var assert = require("assert");
var exec = require("child_process").exec; var exec = require("child_process").exec;
var uglify = require("../node"); var UglifyJS = require("../..");
describe("spidermonkey export/import sanity test", function() { describe("spidermonkey export/import sanity test", function() {
it("should produce a functional build when using --self with spidermonkey", function(done) { it("should produce a functional build when using --self with spidermonkey", function(done) {
@@ -25,9 +25,9 @@ describe("spidermonkey export/import sanity test", function() {
it("should not add unnecessary escape slashes to regexps", function() { it("should not add unnecessary escape slashes to regexps", function() {
var input = "/[\\\\/]/;"; var input = "/[\\\\/]/;";
var ast = uglify.parse(input).to_mozilla_ast(); var ast = UglifyJS.parse(input).to_mozilla_ast();
assert.equal( assert.equal(
uglify.AST_Node.from_mozilla_ast(ast).print_to_string(), UglifyJS.AST_Node.from_mozilla_ast(ast).print_to_string(),
input input
); );
}); });
@@ -99,10 +99,10 @@ describe("spidermonkey export/import sanity test", function() {
var counter_directives; var counter_directives;
var counter_strings; var counter_strings;
var checkWalker = new uglify.TreeWalker(function(node, descend) { var checkWalker = new UglifyJS.TreeWalker(function(node, descend) {
if (node instanceof uglify.AST_String) { if (node instanceof UglifyJS.AST_String) {
counter_strings++; counter_strings++;
} else if (node instanceof uglify.AST_Directive) { } else if (node instanceof UglifyJS.AST_Directive) {
counter_directives++; counter_directives++;
} }
}); });
@@ -111,9 +111,9 @@ describe("spidermonkey export/import sanity test", function() {
counter_directives = 0; counter_directives = 0;
counter_strings = 0; counter_strings = 0;
var ast = uglify.parse(tests[i].input); var ast = UglifyJS.parse(tests[i].input);
var moz_ast = ast.to_mozilla_ast(); var moz_ast = ast.to_mozilla_ast();
var from_moz_ast = uglify.AST_Node.from_mozilla_ast(moz_ast); var from_moz_ast = UglifyJS.AST_Node.from_mozilla_ast(moz_ast);
from_moz_ast.walk(checkWalker); from_moz_ast.walk(checkWalker);

View File

@@ -1,5 +1,5 @@
var UglifyJS = require("../node");
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../node");
describe("String literals", function() { describe("String literals", function() {
it("Should throw syntax error if a string literal contains a newline", function() { it("Should throw syntax error if a string literal contains a newline", function() {
@@ -18,8 +18,8 @@ describe("String literals", function() {
}; };
var error = function(e) { var error = function(e) {
return e instanceof UglifyJS.JS_Parse_Error && return e instanceof UglifyJS.JS_Parse_Error
e.message === "Unterminated string constant"; && e.message === "Unterminated string constant";
}; };
for (var input in inputs) { for (var input in inputs) {
@@ -48,8 +48,8 @@ describe("String literals", function() {
}; };
var error = function(e) { var error = function(e) {
return e instanceof UglifyJS.JS_Parse_Error && return e instanceof UglifyJS.JS_Parse_Error
e.message === "Legacy octal escape sequences are not allowed in strict mode"; && e.message === "Legacy octal escape sequences are not allowed in strict mode";
} }
for (var input in inputs) { for (var input in inputs) {

View File

@@ -1,32 +1,26 @@
var UglifyJS = require("../node");
var assert = require("assert"); var assert = require("assert");
var UglifyJS = require("../..");
describe("Accessor tokens", function() { describe("tokens", function() {
it("Should fill the token information for accessors (issue #1492)", function() { it("Should give correct positions for accessors", function() {
// location 0 1 2 3 4 // location 0 1 2 3 4
// 01234567890123456789012345678901234567890123456789 // 01234567890123456789012345678901234567890123456789
var ast = UglifyJS.parse("var obj = { get latest() { return undefined; } }"); var ast = UglifyJS.parse("var obj = { get latest() { return undefined; } }");
// test all AST_ObjectProperty tokens are set as expected // test all AST_ObjectProperty tokens are set as expected
var checkedAST_ObjectProperty = false; var found = false;
var checkWalker = new UglifyJS.TreeWalker(function(node, descend) { ast.walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.AST_ObjectProperty) { if (node instanceof UglifyJS.AST_ObjectProperty) {
checkedAST_ObjectProperty = true; found = true;
assert.equal(node.start.pos, 12); assert.equal(node.start.pos, 12);
assert.equal(node.end.endpos, 46); assert.equal(node.end.endpos, 46);
assert(node.key instanceof UglifyJS.AST_SymbolAccessor); assert(node.key instanceof UglifyJS.AST_SymbolAccessor);
assert.equal(node.key.start.pos, 16); assert.equal(node.key.start.pos, 16);
assert.equal(node.key.end.endpos, 22); assert.equal(node.key.end.endpos, 22);
assert(node.value instanceof UglifyJS.AST_Accessor); assert(node.value instanceof UglifyJS.AST_Accessor);
assert.equal(node.value.start.pos, 22); assert.equal(node.value.start.pos, 22);
assert.equal(node.value.end.endpos, 46); assert.equal(node.value.end.endpos, 46);
} }
}); }));
ast.walk(checkWalker); assert(found, "AST_ObjectProperty not found");
assert(checkedAST_ObjectProperty, "AST_ObjectProperty not found");
}); });
}); });

View File

@@ -1,20 +1,20 @@
var assert = require("assert"); var assert = require("assert");
var uglify = require("../node"); var UglifyJS = require("../node");
describe("With", function() { describe("With", function() {
it("Should throw syntaxError when using with statement in strict mode", function() { it("Should throw syntaxError when using with statement in strict mode", function() {
var code = '"use strict";\nthrow NotEarlyError;\nwith ({}) { }'; var code = '"use strict";\nthrow NotEarlyError;\nwith ({}) { }';
var test = function() { var test = function() {
uglify.parse(code); UglifyJS.parse(code);
} }
var error = function(e) { var error = function(e) {
return e instanceof uglify.JS_Parse_Error && return e instanceof UglifyJS.JS_Parse_Error
e.message === "Strict mode may not include a with statement"; && e.message === "Strict mode may not include a with statement";
} }
assert.throws(test, error); assert.throws(test, error);
}); });
it("Should set uses_with for scopes involving With statements", function() { it("Should set uses_with for scopes involving With statements", function() {
var ast = uglify.parse("with(e) {f(1, 2)}"); var ast = UglifyJS.parse("with(e) {f(1, 2)}");
ast.figure_out_scope(); ast.figure_out_scope();
assert.equal(ast.uses_with, true); assert.equal(ast.uses_with, true);
assert.equal(ast.body[0].expression.scope.uses_with, true); assert.equal(ast.body[0].expression.scope.uses_with, true);

View File

@@ -210,7 +210,7 @@ function run_compress_tests() {
} }
} }
} }
files.forEach(function(file){ files.forEach(function(file) {
test_file(file); test_file(file);
}); });
} }
@@ -228,7 +228,7 @@ function parse_test(file) {
throw e; throw e;
} }
var tests = {}; var tests = {};
var tw = new U.TreeWalker(function(node, descend){ var tw = new U.TreeWalker(function(node, descend) {
if (node instanceof U.AST_LabeledStatement if (node instanceof U.AST_LabeledStatement
&& tw.parent() instanceof U.AST_Toplevel) { && tw.parent() instanceof U.AST_Toplevel) {
var name = node.label.name; var name = node.label.name;
@@ -271,7 +271,7 @@ function parse_test(file) {
function get_one_test(name, block) { function get_one_test(name, block) {
var test = { name: name, options: {} }; var test = { name: name, options: {} };
var tw = new U.TreeWalker(function(node, descend){ var tw = new U.TreeWalker(function(node, descend) {
if (node instanceof U.AST_Assign) { if (node instanceof U.AST_Assign) {
if (!(node.left instanceof U.AST_SymbolRef)) { if (!(node.left instanceof U.AST_SymbolRef)) {
croak(node); croak(node);

View File

@@ -14,7 +14,7 @@ var FILES = UglifyJS.FILES = [
"../lib/propmangle.js", "../lib/propmangle.js",
"../lib/minify.js", "../lib/minify.js",
"./exports.js", "./exports.js",
].map(function(file){ ].map(function(file) {
return require.resolve(file); return require.resolve(file);
}); });
@@ -33,13 +33,13 @@ 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);
}); });
if (props.length > 0) { if (props.length > 0) {
out.space(); out.space();
out.with_parens(function(){ out.with_parens(function() {
props.forEach(function(prop, i){ props.forEach(function(prop, i) {
if (i) out.space(); if (i) out.space();
out.print(prop); out.print(prop);
}); });
@@ -51,8 +51,8 @@ function describe_ast() {
} }
if (ctor.SUBCLASSES.length > 0) { if (ctor.SUBCLASSES.length > 0) {
out.space(); out.space();
out.with_block(function(){ out.with_block(function() {
ctor.SUBCLASSES.forEach(function(ctor, i){ ctor.SUBCLASSES.forEach(function(ctor, i) {
out.indent(); out.indent();
doitem(ctor); doitem(ctor);
out.newline(); out.newline();