Various property fixes
* Implement getter/setter with computed value * Fix parsing getter/setter after static or generator token * Allow storing expressions for computed expression in AST_SymbolMethod * Allow get and set in shorthand properties in object literals Fixes #1094, #1146 and #1221
This commit is contained in:
committed by
Richard van Velzen
parent
766fafda8b
commit
72a9d799b6
@@ -887,8 +887,12 @@ function OutputStream(options) {
|
|||||||
output.space();
|
output.space();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (self.name) {
|
if (self.name instanceof AST_Symbol) {
|
||||||
self.name.print(output);
|
self.name.print(output);
|
||||||
|
} else if (nokeyword && self.name instanceof AST_Node) {
|
||||||
|
output.with_square(function() {
|
||||||
|
self.name.print(output); // Computed method name
|
||||||
|
});
|
||||||
}
|
}
|
||||||
output.with_parens(function(){
|
output.with_parens(function(){
|
||||||
self.argnames.forEach(function(arg, i){
|
self.argnames.forEach(function(arg, i){
|
||||||
@@ -1489,6 +1493,15 @@ function OutputStream(options) {
|
|||||||
self.default.print(output)
|
self.default.print(output)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
DEFPRINT(AST_SymbolMethod, function(self, output) {
|
||||||
|
if (self.name instanceof AST_Node) {
|
||||||
|
output.with_square(function() {
|
||||||
|
self.name.print(output);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self._do_print(output);
|
||||||
|
}
|
||||||
|
});
|
||||||
DEFPRINT(AST_Undefined, function(self, output){
|
DEFPRINT(AST_Undefined, function(self, output){
|
||||||
output.print("void 0");
|
output.print("void 0");
|
||||||
});
|
});
|
||||||
|
|||||||
76
lib/parse.js
76
lib/parse.js
@@ -1738,7 +1738,7 @@ function parse($TEXT, options) {
|
|||||||
if (!options.strict && is("punc", "}"))
|
if (!options.strict && is("punc", "}"))
|
||||||
// allow trailing comma
|
// allow trailing comma
|
||||||
break;
|
break;
|
||||||
var start = S.token;
|
start = S.token;
|
||||||
var type = start.type;
|
var type = start.type;
|
||||||
var name = as_property_name();
|
var name = as_property_name();
|
||||||
if (type != "string" && type != "num" && !is("punc", ":")) {
|
if (type != "string" && type != "num" && !is("punc", ":")) {
|
||||||
@@ -1747,6 +1747,8 @@ function parse($TEXT, options) {
|
|||||||
a.push(concise);
|
a.push(concise);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
} else if (start.value === "*") {
|
||||||
|
unexpected(prev());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == "punc" && start.value == "[") {
|
if (type == "punc" && start.value == "[") {
|
||||||
@@ -1802,7 +1804,7 @@ function parse($TEXT, options) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function class_(KindOfClass) {
|
function class_(KindOfClass) {
|
||||||
var start, method, class_name, name, extends_, a = [];
|
var start, method, class_name, extends_, a = [];
|
||||||
|
|
||||||
if (S.token.type == "name" && S.token.value != "extends") {
|
if (S.token.type == "name" && S.token.value != "extends") {
|
||||||
class_name = as_symbol(KindOfClass === AST_DefClass ? AST_SymbolDefClass : AST_SymbolClass);
|
class_name = as_symbol(KindOfClass === AST_DefClass ? AST_SymbolDefClass : AST_SymbolClass);
|
||||||
@@ -1822,8 +1824,7 @@ function parse($TEXT, options) {
|
|||||||
if (is("punc", ";")) { next(); } // Leading semicolons are okay in class bodies.
|
if (is("punc", ";")) { next(); } // Leading semicolons are okay in class bodies.
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
start = S.token;
|
start = S.token;
|
||||||
name = as_property_name();
|
method = concise_method_or_getset(as_property_name(), start, true);
|
||||||
method = concise_method_or_getset(name, start, true);
|
|
||||||
if (!method) { unexpected(); }
|
if (!method) { unexpected(); }
|
||||||
a.push(method);
|
a.push(method);
|
||||||
if (is("punc", ";")) { next(); }
|
if (is("punc", ";")) { next(); }
|
||||||
@@ -1841,46 +1842,64 @@ function parse($TEXT, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function concise_method_or_getset(name, start, is_class) {
|
function concise_method_or_getset(name, start, is_class) {
|
||||||
|
var get_ast = function(name, token) {
|
||||||
|
if (typeof name === "string" || typeof name === "number") {
|
||||||
|
if (name === "*") {
|
||||||
|
unexpected(token);
|
||||||
|
}
|
||||||
|
return new AST_SymbolMethod({
|
||||||
|
start: token,
|
||||||
|
name: name,
|
||||||
|
end: prev()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
var is_static = false;
|
var is_static = false;
|
||||||
var is_generator = false;
|
var is_generator = false;
|
||||||
if (is_class && name === "static" && !is("punc", "(")) {
|
if (is_class && name === "static" && !is("punc", "(")) {
|
||||||
is_static = true;
|
is_static = true;
|
||||||
name = S.token.value;
|
name = as_property_name();
|
||||||
next();
|
|
||||||
}
|
}
|
||||||
if (name === "*") {
|
if (name === "*") {
|
||||||
is_generator = true;
|
is_generator = true;
|
||||||
name = S.token.value;
|
name = as_property_name();
|
||||||
next();
|
|
||||||
}
|
}
|
||||||
if (is("punc", "(")) {
|
if (is("punc", "(")) {
|
||||||
|
name = get_ast(name, start);
|
||||||
return new AST_ConciseMethod({
|
return new AST_ConciseMethod({
|
||||||
is_generator: is_generator,
|
is_generator: is_generator,
|
||||||
start : start,
|
start : start,
|
||||||
static : is_static,
|
static : is_static,
|
||||||
name : new AST_SymbolMethod({ name: name }),
|
name : name,
|
||||||
argnames : params_or_seq_().as_params(croak),
|
argnames : params_or_seq_().as_params(croak),
|
||||||
body : _function_body(true, is_generator),
|
body : _function_body(true, is_generator),
|
||||||
end : prev()
|
end : prev()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (name == "get") {
|
if (name == "get") {
|
||||||
return new AST_ObjectGetter({
|
if (!is("punc") || is("punc", "[")) {
|
||||||
start : start,
|
name = get_ast(as_property_name(), prev());
|
||||||
static: is_static,
|
return new AST_ObjectGetter({
|
||||||
key : as_atom_node(),
|
start : start,
|
||||||
value : function_(AST_Accessor),
|
static: is_static,
|
||||||
end : prev()
|
key : name,
|
||||||
});
|
value : function_(AST_Accessor),
|
||||||
|
end : prev()
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (name == "set") {
|
else if (name == "set") {
|
||||||
return new AST_ObjectSetter({
|
if (!is("punc") || is("punc", "[")) {
|
||||||
start : start,
|
name = get_ast(as_property_name(), prev());
|
||||||
static: is_static,
|
return new AST_ObjectSetter({
|
||||||
key : as_atom_node(),
|
start : start,
|
||||||
value : function_(AST_Accessor),
|
static: is_static,
|
||||||
end : prev()
|
key : name,
|
||||||
});
|
value : function_(AST_Accessor),
|
||||||
|
end : prev()
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1996,19 +2015,22 @@ function parse($TEXT, options) {
|
|||||||
var ex = expression(false);
|
var ex = expression(false);
|
||||||
expect("]");
|
expect("]");
|
||||||
return ex;
|
return ex;
|
||||||
} else unexpected();
|
} else unexpected(tmp);
|
||||||
|
case "operator":
|
||||||
|
if (["*", "delete", "in", "instanceof", "new", "typeof", "void"].indexOf(tmp.value) === -1) {
|
||||||
|
unexpected(tmp);
|
||||||
|
}
|
||||||
case "name":
|
case "name":
|
||||||
if (tmp.value === "yield" && S.input.has_directive("use strict") && !is_in_generator()) {
|
if (tmp.value === "yield" && S.input.has_directive("use strict") && !is_in_generator()) {
|
||||||
token_error(tmp, "SyntaxError: Unexpected yield identifier inside strict mode");
|
token_error(tmp, "SyntaxError: Unexpected yield identifier inside strict mode");
|
||||||
}
|
}
|
||||||
case "string":
|
case "string":
|
||||||
case "num":
|
case "num":
|
||||||
case "operator":
|
|
||||||
case "keyword":
|
case "keyword":
|
||||||
case "atom":
|
case "atom":
|
||||||
return tmp.value;
|
return tmp.value;
|
||||||
default:
|
default:
|
||||||
unexpected();
|
unexpected(tmp);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,27 +47,6 @@ regression_assign_arrow_functions: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
computed_property_names: {
|
|
||||||
input: {
|
|
||||||
obj({ ["x" + "x"]: 6 });
|
|
||||||
}
|
|
||||||
expect_exact: 'obj({["x"+"x"]:6});'
|
|
||||||
}
|
|
||||||
|
|
||||||
shorthand_properties: {
|
|
||||||
mangle = true;
|
|
||||||
input: (function() {
|
|
||||||
var prop = 1;
|
|
||||||
const value = {prop};
|
|
||||||
return value;
|
|
||||||
})();
|
|
||||||
expect: (function() {
|
|
||||||
var n = 1;
|
|
||||||
const r = {prop:n};
|
|
||||||
return r;
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
|
|
||||||
typeof_arrow_functions: {
|
typeof_arrow_functions: {
|
||||||
options = {
|
options = {
|
||||||
evaluate: true
|
evaluate: true
|
||||||
@@ -158,72 +137,6 @@ default_values_in_destructurings: {
|
|||||||
expect_exact: "function x({a=4,b}){}function x([b,c=12]){}var{x=6,y}=x;var[x,y=6]=x;"
|
expect_exact: "function x({a=4,b}){}function x([b,c=12]){}var{x=6,y}=x;var[x,y=6]=x;"
|
||||||
}
|
}
|
||||||
|
|
||||||
concise_methods: {
|
|
||||||
input: {
|
|
||||||
x = {
|
|
||||||
foo(a, b) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
y = {
|
|
||||||
foo([{a}]) {
|
|
||||||
return a;
|
|
||||||
},
|
|
||||||
bar(){}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect_exact: "x={foo(a,b){return x}};y={foo([{a}]){return a},bar(){}};"
|
|
||||||
}
|
|
||||||
|
|
||||||
concise_methods_and_mangle_props: {
|
|
||||||
mangle_props = {
|
|
||||||
regex: /_/
|
|
||||||
};
|
|
||||||
input: {
|
|
||||||
function x() {
|
|
||||||
obj = {
|
|
||||||
_foo() { return 1; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
function x() {
|
|
||||||
obj = {
|
|
||||||
a() { return 1; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
concise_generators: {
|
|
||||||
input: {
|
|
||||||
x = {
|
|
||||||
*foo(a, b) {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
y = {
|
|
||||||
*foo([{a}]) {
|
|
||||||
yield a;
|
|
||||||
},
|
|
||||||
bar(){}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect_exact: "x={*foo(a,b){return x}};y={*foo([{a}]){yield a},bar(){}};"
|
|
||||||
}
|
|
||||||
|
|
||||||
concise_methods_and_keyword_names: {
|
|
||||||
input: {
|
|
||||||
x = {
|
|
||||||
catch() {},
|
|
||||||
throw() {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
x={catch(){},throw(){}};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
classes: {
|
classes: {
|
||||||
input: {
|
input: {
|
||||||
class SomeClass {
|
class SomeClass {
|
||||||
@@ -309,6 +222,32 @@ classes_can_have_generators: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
classes_can_have_computed_generators: {
|
||||||
|
input: {
|
||||||
|
class C4 {
|
||||||
|
*['constructor']() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
class C4 {
|
||||||
|
*['constructor']() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
classes_can_have_computed_static: {
|
||||||
|
input: {
|
||||||
|
class C4 {
|
||||||
|
static ['constructor']() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
class C4 {
|
||||||
|
static ['constructor']() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
new_target: {
|
new_target: {
|
||||||
input: {
|
input: {
|
||||||
new.target;
|
new.target;
|
||||||
|
|||||||
263
test/compress/object.js
Normal file
263
test/compress/object.js
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
getter_setter: {
|
||||||
|
input: {
|
||||||
|
var get = "bar";
|
||||||
|
var a = {
|
||||||
|
get,
|
||||||
|
set: "foo",
|
||||||
|
get bar() {
|
||||||
|
return this.get;
|
||||||
|
},
|
||||||
|
get 5() {
|
||||||
|
return "five";
|
||||||
|
},
|
||||||
|
get 0xf55() {
|
||||||
|
return "f five five";
|
||||||
|
},
|
||||||
|
get "five"() {
|
||||||
|
return 5;
|
||||||
|
},
|
||||||
|
set one(value) {
|
||||||
|
this._one = value;
|
||||||
|
},
|
||||||
|
set 9(value) {
|
||||||
|
this._nine = value;
|
||||||
|
},
|
||||||
|
set 0b1010(value) {
|
||||||
|
this._ten = value;
|
||||||
|
},
|
||||||
|
set "eleven"(value) {
|
||||||
|
this._eleven = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var b = {
|
||||||
|
get() { return "gift"; },
|
||||||
|
set: function(code) { return "Storing code " + code; }
|
||||||
|
};
|
||||||
|
var c = {
|
||||||
|
["get"]: "foo",
|
||||||
|
["set"]: "bar"
|
||||||
|
};
|
||||||
|
var d = {
|
||||||
|
get: "foo",
|
||||||
|
set: "bar"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var get = "bar";
|
||||||
|
var a = {
|
||||||
|
get,
|
||||||
|
set: "foo",
|
||||||
|
get bar() {
|
||||||
|
return this.get;
|
||||||
|
},
|
||||||
|
get 5() {
|
||||||
|
return "five";
|
||||||
|
},
|
||||||
|
get 0xf55() {
|
||||||
|
return "f five five";
|
||||||
|
},
|
||||||
|
get "five"() {
|
||||||
|
return 5;
|
||||||
|
},
|
||||||
|
set one(value) {
|
||||||
|
this._one = value;
|
||||||
|
},
|
||||||
|
set 9(value) {
|
||||||
|
this._nine = value;
|
||||||
|
},
|
||||||
|
set 0b1010(value) {
|
||||||
|
this._ten = value;
|
||||||
|
},
|
||||||
|
set "eleven"(value) {
|
||||||
|
this._eleven = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var b = {
|
||||||
|
get() { return "gift"; },
|
||||||
|
set: function(code) { return "Storing code " + code; }
|
||||||
|
};
|
||||||
|
var c = {
|
||||||
|
["get"]: "foo",
|
||||||
|
["set"]: "bar"
|
||||||
|
};
|
||||||
|
var d = {
|
||||||
|
get: "foo",
|
||||||
|
set: "bar"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getter_setter_mangler: {
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
function f(get,set) {
|
||||||
|
return {
|
||||||
|
get,
|
||||||
|
set,
|
||||||
|
get g(){},
|
||||||
|
set s(n){},
|
||||||
|
c,
|
||||||
|
a:1,
|
||||||
|
m(){}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "function f(t,e){return{get:t,set:e,get g(){},set s(t){},c,a:1,m(){}}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
computed_property_names: {
|
||||||
|
input: {
|
||||||
|
obj({ ["x" + "x"]: 6 });
|
||||||
|
}
|
||||||
|
expect_exact: 'obj({["x"+"x"]:6});'
|
||||||
|
}
|
||||||
|
|
||||||
|
shorthand_properties: {
|
||||||
|
mangle = true;
|
||||||
|
input: (function() {
|
||||||
|
var prop = 1;
|
||||||
|
const value = {prop};
|
||||||
|
return value;
|
||||||
|
})();
|
||||||
|
expect: (function() {
|
||||||
|
var n = 1;
|
||||||
|
const r = {prop:n};
|
||||||
|
return r;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
concise_methods: {
|
||||||
|
input: {
|
||||||
|
x = {
|
||||||
|
foo(a, b) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y = {
|
||||||
|
foo([{a}]) {
|
||||||
|
return a;
|
||||||
|
},
|
||||||
|
bar(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "x={foo(a,b){return x}};y={foo([{a}]){return a},bar(){}};"
|
||||||
|
}
|
||||||
|
|
||||||
|
concise_methods_with_computed_property: {
|
||||||
|
options = {
|
||||||
|
evaluate: true
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var foo = {
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return { /* stuff */ }
|
||||||
|
},
|
||||||
|
[1 + 2]() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var foo = {
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return { /* stuff */ }
|
||||||
|
},
|
||||||
|
[3]() {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
concise_methods_and_mangle_props: {
|
||||||
|
mangle_props = {
|
||||||
|
regex: /_/
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function x() {
|
||||||
|
obj = {
|
||||||
|
_foo() { return 1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function x() {
|
||||||
|
obj = {
|
||||||
|
a() { return 1; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
concise_generators: {
|
||||||
|
input: {
|
||||||
|
x = {
|
||||||
|
*foo(a, b) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
y = {
|
||||||
|
*foo([{a}]) {
|
||||||
|
yield a;
|
||||||
|
},
|
||||||
|
bar(){}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "x={*foo(a,b){return x}};y={*foo([{a}]){yield a},bar(){}};"
|
||||||
|
}
|
||||||
|
|
||||||
|
concise_methods_and_keyword_names: {
|
||||||
|
input: {
|
||||||
|
x = {
|
||||||
|
catch() {},
|
||||||
|
throw() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x={catch(){},throw(){}};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getter_setter_with_computed_value: {
|
||||||
|
input: {
|
||||||
|
class C {
|
||||||
|
get ['a']() {
|
||||||
|
return 'A';
|
||||||
|
}
|
||||||
|
set ['a'](value) {
|
||||||
|
do_something(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var x = {
|
||||||
|
get [a.b]() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class MyArray extends Array {
|
||||||
|
get [Symbol.species]() {
|
||||||
|
return Array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
class C {
|
||||||
|
get ['a']() {
|
||||||
|
return 'A';
|
||||||
|
}
|
||||||
|
set ['a'](value) {
|
||||||
|
do_something(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var x = {
|
||||||
|
get [a.b]() {
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class MyArray extends Array {
|
||||||
|
get [Symbol.species]() {
|
||||||
|
return Array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
var UglifyJS = require('../../');
|
|
||||||
var assert = require("assert");
|
|
||||||
|
|
||||||
describe("Getters and setters", function() {
|
|
||||||
it("Should not accept operator symbols as getter/setter name", function() {
|
|
||||||
var illegalOperators = [
|
|
||||||
"++",
|
|
||||||
"--",
|
|
||||||
"+",
|
|
||||||
"-",
|
|
||||||
"!",
|
|
||||||
"~",
|
|
||||||
"&",
|
|
||||||
"|",
|
|
||||||
"^",
|
|
||||||
"*",
|
|
||||||
"/",
|
|
||||||
"%",
|
|
||||||
">>",
|
|
||||||
"<<",
|
|
||||||
">>>",
|
|
||||||
"<",
|
|
||||||
">",
|
|
||||||
"<=",
|
|
||||||
">=",
|
|
||||||
"==",
|
|
||||||
"===",
|
|
||||||
"!=",
|
|
||||||
"!==",
|
|
||||||
"?",
|
|
||||||
"=",
|
|
||||||
"+=",
|
|
||||||
"-=",
|
|
||||||
"/=",
|
|
||||||
"*=",
|
|
||||||
"%=",
|
|
||||||
">>=",
|
|
||||||
"<<=",
|
|
||||||
">>>=",
|
|
||||||
"|=",
|
|
||||||
"^=",
|
|
||||||
"&=",
|
|
||||||
"&&",
|
|
||||||
"||"
|
|
||||||
];
|
|
||||||
var generator = function() {
|
|
||||||
var results = [];
|
|
||||||
|
|
||||||
for (var i in illegalOperators) {
|
|
||||||
results.push({
|
|
||||||
code: "var obj = { get " + illegalOperators[i] + "() { return test; }};",
|
|
||||||
operator: illegalOperators[i],
|
|
||||||
method: "get"
|
|
||||||
});
|
|
||||||
results.push({
|
|
||||||
code: "var obj = { set " + illegalOperators[i] + "(value) { test = value}};",
|
|
||||||
operator: illegalOperators[i],
|
|
||||||
method: "set"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
};
|
|
||||||
|
|
||||||
var testCase = function(data) {
|
|
||||||
return function() {
|
|
||||||
UglifyJS.parse(data.code);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var fail = function(data) {
|
|
||||||
return function (e) {
|
|
||||||
return e instanceof UglifyJS.JS_Parse_Error &&
|
|
||||||
e.message === "SyntaxError: Invalid getter/setter name: " + data.operator;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
var errorMessage = function(data) {
|
|
||||||
return "Expected but didn't get a syntax error while parsing following line:\n" + data.code;
|
|
||||||
};
|
|
||||||
|
|
||||||
var tests = generator();
|
|
||||||
for (var i = 0; i < tests.length; i++) {
|
|
||||||
var test = tests[i];
|
|
||||||
assert.throws(testCase(test), fail(test), errorMessage(test));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
@@ -2,12 +2,12 @@ var Uglify = require("../../");
|
|||||||
var assert = require("assert");
|
var assert = require("assert");
|
||||||
|
|
||||||
describe("Object", function() {
|
describe("Object", function() {
|
||||||
it ("Should allow objects to have a methodDefinition as property", function() {
|
it("Should allow objects to have a methodDefinition as property", function() {
|
||||||
var code = "var a = {test() {return true;}}";
|
var code = "var a = {test() {return true;}}";
|
||||||
assert.equal(Uglify.minify(code, {fromString: true}).code, "var a={test(){return!0}};");
|
assert.equal(Uglify.minify(code, {fromString: true}).code, "var a={test(){return!0}};");
|
||||||
});
|
});
|
||||||
|
|
||||||
it ("Should not allow objects to use static keywords like in classes", function() {
|
it("Should not allow objects to use static keywords like in classes", function() {
|
||||||
var code = "{static test() {}}";
|
var code = "{static test() {}}";
|
||||||
var parse = function() {
|
var parse = function() {
|
||||||
Uglify.parse(code);
|
Uglify.parse(code);
|
||||||
@@ -17,4 +17,111 @@ describe("Object", function() {
|
|||||||
}
|
}
|
||||||
assert.throws(parse, expect);
|
assert.throws(parse, expect);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it("Should not allow objects to have static computed properties like in classes", function() {
|
||||||
|
var code = "var foo = {static [123](){}}";
|
||||||
|
var parse = function() {
|
||||||
|
console.log(Uglify.parse(code).body[0].body[0]);
|
||||||
|
}
|
||||||
|
var expect = function(e) {
|
||||||
|
return e instanceof Uglify.JS_Parse_Error;
|
||||||
|
}
|
||||||
|
assert.throws(parse, expect);
|
||||||
|
});
|
||||||
|
it("Should not accept operator tokens as property/getter/setter name", function() {
|
||||||
|
var illegalOperators = [
|
||||||
|
"++",
|
||||||
|
"--",
|
||||||
|
"+",
|
||||||
|
"-",
|
||||||
|
"!",
|
||||||
|
"~",
|
||||||
|
"&",
|
||||||
|
"|",
|
||||||
|
"^",
|
||||||
|
"*",
|
||||||
|
"/",
|
||||||
|
"%",
|
||||||
|
">>",
|
||||||
|
"<<",
|
||||||
|
">>>",
|
||||||
|
"<",
|
||||||
|
">",
|
||||||
|
"<=",
|
||||||
|
">=",
|
||||||
|
"==",
|
||||||
|
"===",
|
||||||
|
"!=",
|
||||||
|
"!==",
|
||||||
|
"?",
|
||||||
|
"=",
|
||||||
|
"+=",
|
||||||
|
"-=",
|
||||||
|
"/=",
|
||||||
|
"*=",
|
||||||
|
"%=",
|
||||||
|
">>=",
|
||||||
|
"<<=",
|
||||||
|
">>>=",
|
||||||
|
"|=",
|
||||||
|
"^=",
|
||||||
|
"&=",
|
||||||
|
"&&",
|
||||||
|
"||"
|
||||||
|
];
|
||||||
|
var generator = function() {
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
for (var i in illegalOperators) {
|
||||||
|
results.push({
|
||||||
|
code: "var obj = { get " + illegalOperators[i] + "() { return test; }};",
|
||||||
|
operator: illegalOperators[i],
|
||||||
|
method: "get"
|
||||||
|
});
|
||||||
|
results.push({
|
||||||
|
code: "var obj = { set " + illegalOperators[i] + "(value) { test = value}};",
|
||||||
|
operator: illegalOperators[i],
|
||||||
|
method: "set"
|
||||||
|
});
|
||||||
|
results.push({
|
||||||
|
code: "var obj = { " + illegalOperators[i] + ': "123"};',
|
||||||
|
operator: illegalOperators[i],
|
||||||
|
method: "key"
|
||||||
|
});
|
||||||
|
results.push({
|
||||||
|
code: "var obj = { " + illegalOperators[i] + "(){ return test; }};",
|
||||||
|
operator: illegalOperators[i],
|
||||||
|
method: "method"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
var testCase = function(data) {
|
||||||
|
return function() {
|
||||||
|
Uglify.parse(data.code);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var fail = function(data) {
|
||||||
|
return function (e) {
|
||||||
|
return e instanceof Uglify.JS_Parse_Error && (
|
||||||
|
e.message === "SyntaxError: Unexpected token: operator (" + data.operator + ")" ||
|
||||||
|
(e.message === "SyntaxError: Unterminated regular expression" && data.operator[0] === "/") ||
|
||||||
|
(e.message === "SyntaxError: Unexpected token: punc (()" && data.operator === "*")
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var errorMessage = function(data) {
|
||||||
|
return "Expected but didn't get a syntax error while parsing following line:\n" + data.code;
|
||||||
|
};
|
||||||
|
|
||||||
|
var tests = generator();
|
||||||
|
for (var i = 0; i < tests.length; i++) {
|
||||||
|
var test = tests[i];
|
||||||
|
assert.throws(testCase(test), fail(test), errorMessage(test));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user