if (self.args.length != 1) {
return make_node(AST_Array, self, {
elements: self.args
- }).transform(compressor);
+ }).optimize(compressor);
}
break;
case "Object":
left: self.args[0],
operator: "+",
right: make_node(AST_String, self, { value: "" })
- }).transform(compressor);
+ }).optimize(compressor);
break;
case "Number":
if (self.args.length == 0) return make_node(AST_Number, self, {
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
expression: self.args[0],
operator: "+"
- }).transform(compressor);
+ }).optimize(compressor);
case "Boolean":
if (self.args.length == 0) return make_node(AST_False, self);
if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
operator: "!"
}),
operator: "!"
- }).transform(compressor);
+ }).optimize(compressor);
break;
case "Function":
// new Function() => function(){}
left: make_node(AST_String, self, { value: "" }),
operator: "+",
right: exp.expression
- }).transform(compressor);
+ }).optimize(compressor);
}
else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
var separator;
left : prev,
right : el
});
- }, first).transform(compressor);
+ }, first).optimize(compressor);
}
// need this awkward cloning to not affect original element
// best_of will decide which one to get through.
node.expression.expression.elements = elements;
return best_of(compressor, self, node);
}
+ else if (exp instanceof AST_Dot && exp.expression.is_string(compressor) && exp.property == "charAt") {
+ var arg = self.args[0];
+ var index = arg ? arg.evaluate(compressor) : 0;
+ if (index !== arg) {
+ return make_node(AST_Sub, exp, {
+ expression: exp.expression,
+ property: make_node_from_constant(index | 0, arg || exp)
+ }).optimize(compressor);
+ }
+ }
}
if (exp instanceof AST_Function) {
if (exp.body[0] instanceof AST_Return) {
1 / (-0)
);
}
+ expect_stdout: true
}
positive_zero: {
1 / (0)
);
}
+ expect_stdout: true
}
unsafe_constant: {
1["1"] + 1
);
}
+ expect_stdout: true
}
unsafe_integer_key_complex: {
2
);
}
+ expect_stdout: true
}
unsafe_float_key: {
1["3.14"] + 1
);
}
+ expect_stdout: true
}
unsafe_float_key_complex: {
2
);
}
+ expect_stdout: true
}
unsafe_array: {
"11"
);
}
+ expect_stdout: true
}
unsafe_array_bad_index: {
[1, 2, 3, 4][3.14] + 1
);
}
+ expect_stdout: true
}
unsafe_string_bad_index: {
"1234"[3.14] + 1
);
}
+ expect_stdout: true
}
unsafe_prototype_function: {
);
}
}
+
+unsafe_charAt: {
+ options = {
+ evaluate : true,
+ unsafe : true
+ }
+ input: {
+ console.log(
+ "1234" + 1,
+ "1234".charAt(0) + 1,
+ "1234".charAt(6 - 5) + 1,
+ ("12" + "34").charAt(0) + 1,
+ ("12" + "34").charAt(6 - 5) + 1,
+ [1, 2, 3, 4].join("").charAt(0) + 1
+ );
+ }
+ expect: {
+ console.log(
+ "12341",
+ "11",
+ "21",
+ "11",
+ "21",
+ "11"
+ );
+ }
+ expect_stdout: true
+}
+
+unsafe_charAt_bad_index: {
+ options = {
+ evaluate : true,
+ unsafe : true
+ }
+ input: {
+ console.log(
+ "1234".charAt() + 1,
+ "1234".charAt("a") + 1,
+ "1234".charAt(3.14) + 1
+ );
+ }
+ expect: {
+ console.log(
+ "11",
+ "11",
+ "41"
+ );
+ }
+ expect_stdout: true
+}
+
+unsafe_charAt_noop: {
+ options = {
+ evaluate : true,
+ unsafe : true
+ }
+ input: {
+ console.log(
+ s.charAt(0),
+ "string".charAt(x)
+ );
+ }
+ expect: {
+ console.log(
+ s.charAt(0),
+ "string".charAt(x)
+ );
+ }
+}