augment evaluate to extract within objects (#1425)
- gated by `unsafe` - replaces previous optimisation specific to String.length - "123"[0] => 1 - [1, 2, 3][0] => 1 - [1, 2, 3].length => 3 - does not apply to objects with overridden prototype functions
This commit is contained in:
committed by
Richard van Velzen
parent
48284844a4
commit
0d7d4918eb
@@ -152,6 +152,12 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
AST_Node.DEFMETHOD("clear_opt_flags", function(){
|
AST_Node.DEFMETHOD("clear_opt_flags", function(){
|
||||||
this.walk(new TreeWalker(function(node){
|
this.walk(new TreeWalker(function(node){
|
||||||
|
if (node instanceof AST_SymbolRef) {
|
||||||
|
var d = node.definition();
|
||||||
|
if (d && d.init) {
|
||||||
|
delete d.init._evaluated;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
if (!(node instanceof AST_Directive || node instanceof AST_Constant)) {
|
||||||
node._squeezed = false;
|
node._squeezed = false;
|
||||||
node._optimized = false;
|
node._optimized = false;
|
||||||
@@ -992,13 +998,20 @@ merge(Compressor.prototype, {
|
|||||||
// constant; otherwise it's the original or a replacement node.
|
// constant; otherwise it's the original or a replacement node.
|
||||||
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
AST_Node.DEFMETHOD("evaluate", function(compressor){
|
||||||
if (!compressor.option("evaluate")) return [ this ];
|
if (!compressor.option("evaluate")) return [ this ];
|
||||||
|
var val;
|
||||||
try {
|
try {
|
||||||
var val = this._eval(compressor);
|
val = this._eval(compressor);
|
||||||
return [ best_of(make_node_from_constant(compressor, val, this), this), val ];
|
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
if (ex !== def) throw ex;
|
if (ex !== def) throw ex;
|
||||||
return [ this ];
|
return [ this ];
|
||||||
}
|
}
|
||||||
|
var node;
|
||||||
|
try {
|
||||||
|
node = make_node_from_constant(compressor, val, this);
|
||||||
|
} catch(ex) {
|
||||||
|
return [ this ];
|
||||||
|
}
|
||||||
|
return [ best_of(node, this), val ];
|
||||||
});
|
});
|
||||||
AST_Node.DEFMETHOD("is_constant", function(compressor){
|
AST_Node.DEFMETHOD("is_constant", function(compressor){
|
||||||
// Accomodate when compress option evaluate=false
|
// Accomodate when compress option evaluate=false
|
||||||
@@ -1047,6 +1060,32 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Constant, function(){
|
def(AST_Constant, function(){
|
||||||
return this.getValue();
|
return this.getValue();
|
||||||
});
|
});
|
||||||
|
def(AST_Array, function(compressor){
|
||||||
|
if (compressor.option("unsafe")) {
|
||||||
|
return this.elements.map(function(element) {
|
||||||
|
return ev(element, compressor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw def;
|
||||||
|
});
|
||||||
|
def(AST_Object, function(compressor){
|
||||||
|
if (compressor.option("unsafe")) {
|
||||||
|
var val = {};
|
||||||
|
for (var i = 0, len = this.properties.length; i < len; i++) {
|
||||||
|
var prop = this.properties[i];
|
||||||
|
var key = prop.key;
|
||||||
|
if (key instanceof AST_Node) {
|
||||||
|
key = ev(key, compressor);
|
||||||
|
}
|
||||||
|
if (typeof Object.prototype[key] === 'function') {
|
||||||
|
throw def;
|
||||||
|
}
|
||||||
|
val[key] = ev(prop.value, compressor);
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
throw def;
|
||||||
|
});
|
||||||
def(AST_UnaryPrefix, function(compressor){
|
def(AST_UnaryPrefix, function(compressor){
|
||||||
var e = this.expression;
|
var e = this.expression;
|
||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
@@ -1114,6 +1153,12 @@ merge(Compressor.prototype, {
|
|||||||
try {
|
try {
|
||||||
var d = this.definition();
|
var d = this.definition();
|
||||||
if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) {
|
if (d && (d.constant || compressor.option("reduce_vars") && !d.modified) && d.init) {
|
||||||
|
if (compressor.option("unsafe")) {
|
||||||
|
if (!HOP(d.init, '_evaluated')) {
|
||||||
|
d.init._evaluated = ev(d.init, compressor);
|
||||||
|
}
|
||||||
|
return d.init._evaluated;
|
||||||
|
}
|
||||||
return ev(d.init, compressor);
|
return ev(d.init, compressor);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1121,11 +1166,16 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
throw def;
|
throw def;
|
||||||
});
|
});
|
||||||
def(AST_Dot, function(compressor){
|
def(AST_PropAccess, function(compressor){
|
||||||
if (compressor.option("unsafe") && this.property == "length") {
|
if (compressor.option("unsafe")) {
|
||||||
var str = ev(this.expression, compressor);
|
var key = this.property;
|
||||||
if (typeof str == "string")
|
if (key instanceof AST_Node) {
|
||||||
return str.length;
|
key = ev(key, compressor);
|
||||||
|
}
|
||||||
|
var val = ev(this.expression, compressor);
|
||||||
|
if (val && HOP(val, key)) {
|
||||||
|
return val[key];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw def;
|
throw def;
|
||||||
});
|
});
|
||||||
@@ -2890,7 +2940,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self;
|
return self.evaluate(compressor)[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_Dot, function(self, compressor){
|
OPT(AST_Dot, function(self, compressor){
|
||||||
|
|||||||
17
lib/scope.js
17
lib/scope.js
@@ -184,6 +184,17 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
var func = null;
|
var func = null;
|
||||||
var globals = self.globals = new Dictionary();
|
var globals = self.globals = new Dictionary();
|
||||||
var tw = new TreeWalker(function(node, descend){
|
var tw = new TreeWalker(function(node, descend){
|
||||||
|
function isModified(node, level) {
|
||||||
|
var parent = tw.parent(level);
|
||||||
|
if (parent instanceof AST_Unary && (parent.operator === "++" || parent.operator === "--")
|
||||||
|
|| parent instanceof AST_Assign && parent.left === node
|
||||||
|
|| parent instanceof AST_Call && parent.expression === node) {
|
||||||
|
return true;
|
||||||
|
} else if (parent instanceof AST_PropAccess && parent.expression === node) {
|
||||||
|
return isModified(parent, level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (node instanceof AST_Lambda) {
|
if (node instanceof AST_Lambda) {
|
||||||
var prev_func = func;
|
var prev_func = func;
|
||||||
func = node;
|
func = node;
|
||||||
@@ -197,8 +208,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
}
|
}
|
||||||
if (node instanceof AST_SymbolRef) {
|
if (node instanceof AST_SymbolRef) {
|
||||||
var name = node.name;
|
var name = node.name;
|
||||||
var parent = tw.parent();
|
if (name == "eval" && tw.parent() instanceof AST_Call) {
|
||||||
if (name == "eval" && parent instanceof AST_Call) {
|
|
||||||
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
|
||||||
s.uses_eval = true;
|
s.uses_eval = true;
|
||||||
}
|
}
|
||||||
@@ -220,8 +230,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
sym = g;
|
sym = g;
|
||||||
}
|
}
|
||||||
node.thedef = sym;
|
node.thedef = sym;
|
||||||
if (parent instanceof AST_Unary && (parent.operator === "++" || parent.operator === "--")
|
if (isModified(node, 0)) {
|
||||||
|| parent instanceof AST_Assign && parent.left === node) {
|
|
||||||
sym.modified = true;
|
sym.modified = true;
|
||||||
}
|
}
|
||||||
node.reference();
|
node.reference();
|
||||||
|
|||||||
@@ -72,3 +72,52 @@ constant_join_2: {
|
|||||||
var f = "strstr" + variable + "foobarmoo" + foo;
|
var f = "strstr" + variable + "foobarmoo" + foo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for_loop: {
|
||||||
|
options = {
|
||||||
|
unsafe : true,
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f0() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0, len = a.length; i < len; i++) {
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++) {
|
||||||
|
a[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < 3; i++)
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0, len = 3; i < len; i++)
|
||||||
|
console.log(a[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2() {
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
for (var i = 0; i < a.length; i++)
|
||||||
|
a[i]++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,3 +37,380 @@ positive_zero: {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_constant: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
true.a,
|
||||||
|
false.a,
|
||||||
|
null.a,
|
||||||
|
undefined.a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
true.a,
|
||||||
|
false.a,
|
||||||
|
null.a,
|
||||||
|
(void 0).a
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:1}) + 1,
|
||||||
|
({a:1}).a + 1,
|
||||||
|
({a:1}).b + 1,
|
||||||
|
({a:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:1}) + 1,
|
||||||
|
2,
|
||||||
|
({a:1}).b + 1,
|
||||||
|
1..b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_nested: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1}}) + 1,
|
||||||
|
({a:{b:1}}).a + 1,
|
||||||
|
({a:{b:1}}).b + 1,
|
||||||
|
({a:{b:1}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1}}) + 1,
|
||||||
|
({a:{b:1}}).a + 1,
|
||||||
|
({a:{b:1}}).b + 1,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:1}) + 1,
|
||||||
|
({a:{b:1},b:1}).a + 1,
|
||||||
|
({a:{b:1},b:1}).b + 1,
|
||||||
|
({a:{b:1},b:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:1}) + 1,
|
||||||
|
({a:{b:1},b:1}).a + 1,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_object_repeated: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},a:1}) + 1,
|
||||||
|
({a:{b:1},a:1}).a + 1,
|
||||||
|
({a:{b:1},a:1}).b + 1,
|
||||||
|
({a:{b:1},a:1}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},a:1}) + 1,
|
||||||
|
2,
|
||||||
|
({a:{b:1},a:1}).b + 1,
|
||||||
|
1..b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_function: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:function(){}}) + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a + 1,
|
||||||
|
({a:{b:1},b:function(){}}).b + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({a:{b:1},b:function(){}}) + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a + 1,
|
||||||
|
({a:{b:1},b:function(){}}).b + 1,
|
||||||
|
({a:{b:1},b:function(){}}).a.b + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_integer_key: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({0:1}) + 1,
|
||||||
|
({0:1})[0] + 1,
|
||||||
|
({0:1})["0"] + 1,
|
||||||
|
({0:1})[1] + 1,
|
||||||
|
({0:1})[0][1] + 1,
|
||||||
|
({0:1})[0]["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({0:1}) + 1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
({0:1})[1] + 1,
|
||||||
|
1[1] + 1,
|
||||||
|
1["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_integer_key_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({0:{1:1},1:1}) + 1,
|
||||||
|
({0:{1:1},1:1})[0] + 1,
|
||||||
|
({0:{1:1},1:1})["0"] + 1,
|
||||||
|
({0:{1:1},1:1})[1] + 1,
|
||||||
|
({0:{1:1},1:1})[0][1] + 1,
|
||||||
|
({0:{1:1},1:1})[0]["1"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({0:{1:1},1:1}) + 1,
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_float_key: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({2.72:1}) + 1,
|
||||||
|
({2.72:1})[2.72] + 1,
|
||||||
|
({2.72:1})["2.72"] + 1,
|
||||||
|
({2.72:1})[3.14] + 1,
|
||||||
|
({2.72:1})[2.72][3.14] + 1,
|
||||||
|
({2.72:1})[2.72]["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
({2.72:1}) + 1,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
({2.72:1})[3.14] + 1,
|
||||||
|
1[3.14] + 1,
|
||||||
|
1["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_float_key_complex: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
({2.72:{3.14:1},3.14:1}) + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})["2.72"] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[3.14] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72][3.14] + 1,
|
||||||
|
({2.72:{3.14:1},3.14:1})[2.72]["3.14"] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
"[object Object]1",
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_array: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
[1, , 3][1],
|
||||||
|
[1, 2, 3, a] + 1,
|
||||||
|
[1, 2, 3, 4] + 1,
|
||||||
|
[1, 2, 3, a][0] + 1,
|
||||||
|
[1, 2, 3, 4][0] + 1,
|
||||||
|
[1, 2, 3, 4][6 - 5] + 1,
|
||||||
|
[1, , 3, 4][6 - 5] + 1,
|
||||||
|
[[1, 2], [3, 4]][0] + 1,
|
||||||
|
[[1, 2], [3, 4]][6 - 5][1] + 1,
|
||||||
|
[[1, 2], , [3, 4]][6 - 5][1] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
void 0,
|
||||||
|
[1, 2, 3, a] + 1,
|
||||||
|
"1,2,3,41",
|
||||||
|
[1, 2, 3, a][0] + 1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
NaN,
|
||||||
|
"1,21",
|
||||||
|
5,
|
||||||
|
(void 0)[1] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234" + 1,
|
||||||
|
"1234"[0] + 1,
|
||||||
|
"1234"[6 - 5] + 1,
|
||||||
|
("12" + "34")[0] + 1,
|
||||||
|
("12" + "34")[6 - 5] + 1,
|
||||||
|
[1, 2, 3, 4].join("")[0] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"12341",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11",
|
||||||
|
"21",
|
||||||
|
"11"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_array_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
[1, 2, 3, 4].a + 1,
|
||||||
|
[1, 2, 3, 4]["a"] + 1,
|
||||||
|
[1, 2, 3, 4][3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
[1, 2, 3, 4].a + 1,
|
||||||
|
[1, 2, 3, 4]["a"] + 1,
|
||||||
|
[1, 2, 3, 4][3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_string_bad_index: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(
|
||||||
|
"1234".a + 1,
|
||||||
|
"1234"["a"] + 1,
|
||||||
|
"1234"[3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(
|
||||||
|
"1234".a + 1,
|
||||||
|
"1234"["a"] + 1,
|
||||||
|
"1234"[3.14] + 1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_prototype_function: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = ({valueOf: 0}) < 1;
|
||||||
|
var b = ({toString: 0}) < 1;
|
||||||
|
var c = ({valueOf: 0}) + "";
|
||||||
|
var d = ({toString: 0}) + "";
|
||||||
|
var e = (({valueOf: 0}) + "")[2];
|
||||||
|
var f = (({toString: 0}) + "")[2];
|
||||||
|
var g = ({valueOf: 0}).valueOf();
|
||||||
|
var h = ({toString: 0}).toString();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = ({valueOf: 0}) < 1;
|
||||||
|
var b = ({toString: 0}) < 1;
|
||||||
|
var c = ({valueOf: 0}) + "";
|
||||||
|
var d = ({toString: 0}) + "";
|
||||||
|
var e = (({valueOf: 0}) + "")[2];
|
||||||
|
var f = (({toString: 0}) + "")[2];
|
||||||
|
var g = ({valueOf: 0}).valueOf();
|
||||||
|
var h = "" + ({toString: 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -54,7 +54,56 @@ dot_properties_es5: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluate_length: {
|
sub_properties: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
properties: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a[0] = 0;
|
||||||
|
a["0"] = 1;
|
||||||
|
a[3.14] = 2;
|
||||||
|
a["3" + ".14"] = 3;
|
||||||
|
a["i" + "f"] = 4;
|
||||||
|
a["foo" + " bar"] = 5;
|
||||||
|
a[0 / 0] = 6;
|
||||||
|
a[null] = 7;
|
||||||
|
a[undefined] = 8;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a[0] = 0;
|
||||||
|
a[0] = 1;
|
||||||
|
a[3.14] = 2;
|
||||||
|
a[3.14] = 3;
|
||||||
|
a.if = 4;
|
||||||
|
a["foo bar"] = 5;
|
||||||
|
a[NaN] = 6;
|
||||||
|
a[null] = 7;
|
||||||
|
a[void 0] = 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_array_length: {
|
||||||
|
options = {
|
||||||
|
properties: true,
|
||||||
|
unsafe: true,
|
||||||
|
evaluate: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a = [1, 2, 3].length;
|
||||||
|
a = [1, 2, 3].join()["len" + "gth"];
|
||||||
|
a = [1, 2, b].length;
|
||||||
|
a = [1, 2, 3].join(b).length;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a = 3;
|
||||||
|
a = 5;
|
||||||
|
a = [1, 2, b].length;
|
||||||
|
a = [1, 2, 3].join(b).length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
evaluate_string_length: {
|
||||||
options = {
|
options = {
|
||||||
properties: true,
|
properties: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
|
|||||||
@@ -168,4 +168,185 @@ modified: {
|
|||||||
console.log(B ? 'yes' : 'no');
|
console.log(B ? 'yes' : 'no');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true,
|
||||||
|
unused : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = {
|
||||||
|
b:1
|
||||||
|
};
|
||||||
|
console.log(a.b + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:{
|
||||||
|
c:1
|
||||||
|
},
|
||||||
|
d:2
|
||||||
|
};
|
||||||
|
console.log(a.b + 3, a.d + 4, a.b.c + 5, a.d.c + 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
console.log(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:{
|
||||||
|
c:1
|
||||||
|
},
|
||||||
|
d:2
|
||||||
|
};
|
||||||
|
console.log(a.b + 3, 6, 6, 2..c + 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate_object: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = {};
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(a + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:1
|
||||||
|
};
|
||||||
|
a.b = 2;
|
||||||
|
console.log(a.b + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = {};
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = {
|
||||||
|
b:1
|
||||||
|
};
|
||||||
|
a.b = 2;
|
||||||
|
console.log(a.b + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate_array: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = [];
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(a + 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = [1];
|
||||||
|
a[2] = 3;
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
var a = [1];
|
||||||
|
a.push(2);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
var a = 1;
|
||||||
|
var b = [];
|
||||||
|
b[a] = 2;
|
||||||
|
console.log(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = [1];
|
||||||
|
a[2] = 3;
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
var a = [1];
|
||||||
|
a.push(2);
|
||||||
|
console.log(a.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_evaluate_equality: {
|
||||||
|
options = {
|
||||||
|
evaluate : true,
|
||||||
|
reduce_vars : true,
|
||||||
|
unsafe : true,
|
||||||
|
unused : true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f0(){
|
||||||
|
var a = {};
|
||||||
|
console.log(a === a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
var a = [];
|
||||||
|
console.log(a === a);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
var a = {a:1, b:2};
|
||||||
|
var b = a;
|
||||||
|
var c = a;
|
||||||
|
console.log(b === c);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f3(){
|
||||||
|
var a = [1, 2, 3];
|
||||||
|
var b = a;
|
||||||
|
var c = a;
|
||||||
|
console.log(b === c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f0(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f1(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f2(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function f3(){
|
||||||
|
console.log(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user