[ES9] implement object rest/spread

This commit is contained in:
kzc 2017-07-31 11:38:07 -04:00
parent f54ab16843
commit 6f52e39ad3
3 changed files with 81 additions and 16 deletions

View File

@ -1547,18 +1547,33 @@ function parse($TEXT, options) {
} else {
expect(",");
}
if (is("expand", "...")) {
is_expand = true;
expand_token = S.token;
used_parameters.mark_spread(S.token);
next();
}
if (is("name") && (is_token(peek(), "punc") || is_token(peek(), "operator")) && [",", "}", "="].indexOf(peek().value) !== -1) {
used_parameters.add_parameter(S.token);
var value = new symbol_type({
start: S.token,
name: S.token.value,
end: S.token,
});
if (is_expand) {
elements.push(new AST_Expansion({
start: expand_token,
expression: value,
end: value.end,
}));
} else {
elements.push(new AST_ObjectKeyVal({
start: prev(),
key: S.token.value,
value: new symbol_type({
start: S.token,
name: S.token.value,
end: S.token
}),
end: prev()
value: value,
end: value.end,
}));
}
next();
} else if (is("punc", "}")) {
continue; // Allow trailing hole
@ -1589,7 +1604,12 @@ function parse($TEXT, options) {
}));
}
}
if (is("operator", "=")) {
if (is_expand) {
if (!is("punc", "}")) {
unexpected(); // Must be last element
}
}
else if (is("operator", "=")) {
used_parameters.mark_default_assignment(S.token);
next();
elements[elements.length - 1].value = new AST_DefaultAssign({
@ -2143,7 +2163,18 @@ function parse($TEXT, options) {
if (!options.strict && is("punc", "}"))
// allow trailing comma
break;
start = S.token;
if (start.type == "expand") {
next();
a.push(new AST_Expansion({
start: start,
expression: expression(false),
end: prev(),
}));
continue;
}
var name = as_property_name();
var value;

View File

@ -695,3 +695,37 @@ export_default_class_decl: {
}
expect_exact: "export default class Car{};export class Cab{};"
}
object_rest_spread: {
mangle = {
toplevel: true,
}
input: {
var { w: w1, ...V } = { w: 7, x: 1, y: 2 }; console.log(w1, V);
let { w: w2, ...L } = { w: 8, x: 3, y: 4 }; console.log(w2, L);
const { w: w3, ...C } = { w: 9, x: 5, y: 6 }; console.log(w3, C);
let b;
({ b, ...V } = { a: 1, b: 2, c: 3 }); console.log(V);
({ b, ...L } = { a: 4, b: 5, c: 6 }); console.log(L);
(function({ y, ...p }){ console.log(p); })({ x: 1, y: 2, z: 3 });
(({ y, ...p }) => { console.log(p); })({ x: 4, y: 5, z: 6 });
const T = { a: 1, b: 2 }; console.log({ ...T, w: 0, ...{}, ...L, ...{K: 9} });
}
expect: {
var { w: o, ...l } = { w: 7, x: 1, y: 2 }; console.log(o, l);
let { w: c, ...n } = { w: 8, x: 3, y: 4 }; console.log(c, n);
const { w: e, ...s } = { w: 9, x: 5, y: 6 }; console.log(e, s);
let g;
({ b: g, ...l } = { a: 1, b: 2, c: 3 }); console.log(l);
({ b: g, ...n } = { a: 4, b: 5, c: 6 }); console.log(n);
(function({ y: o, ...l }) { console.log(l); })({ x: 1, y: 2, z: 3 });
(({ y: o, ...l }) => { console.log(l); })({ x: 4, y: 5, z: 6 });
const w = { a: 1, b: 2 }; console.log({ ...w, w: 0, ...{}, ...n, ...{ K: 9 } });
}
}

View File

@ -253,13 +253,13 @@ describe("Left-hand side expressions", function () {
// Multiple spreads are not allowed in destructuring array
expect("[...a, ...b] = [1, 2, 3, 4]", "Spread must the be last element in destructuring array");
// Spread in obvious object pattern
expect("({...a} = foo)", "Unexpected token: expand (...)");
// Spread in block should not be allowed
expect("{...a} = foo", "Unexpected token: expand (...)");
// Not in standard yet
expect("let foo = {bar: 42}, bar; bar = {...foo}", "Unexpected token: expand (...)");
// Object spread must be last in destructuring declaration
expect("let { ...x, a } = o;", "Unexpected token: punc (,)");
// Only one spread per destructuring declaration
expect("let { a, ...x, ...y } = o;", "Unexpected token: punc (,)");
});
});