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
@@ -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: {
|
||||
options = {
|
||||
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;"
|
||||
}
|
||||
|
||||
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: {
|
||||
input: {
|
||||
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: {
|
||||
input: {
|
||||
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");
|
||||
|
||||
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;}}";
|
||||
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 parse = function() {
|
||||
Uglify.parse(code);
|
||||
@@ -17,4 +17,111 @@ describe("Object", function() {
|
||||
}
|
||||
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