Experimenting with array destructuring in each-blocks

pull/2658/head
Michael Braun 5 years ago
parent 85b1850b77
commit c477f50b9a

@ -9,14 +9,18 @@ import { Node as INode } from '../../interfaces';
function unpack_destructuring(contexts: Array<{ name: string, tail: string }>, node: INode, tail: string) { function unpack_destructuring(contexts: Array<{ name: string, tail: string }>, node: INode, tail: string) {
if (!node) return; if (!node) return;
if (node.type === 'Identifier') { if (node.type === 'Identifier' || node.type === 'RestIdentifier') {
contexts.push({ contexts.push({
key: node, key: node,
tail tail
}); });
} else if (node.type === 'ArrayPattern') { } else if (node.type === 'ArrayPattern') {
node.elements.forEach((element, i) => { node.elements.forEach((element, i) => {
unpack_destructuring(contexts, element, `${tail}[${i}]`); if (element.type === 'RestIdentifier') {
unpack_destructuring(contexts, element, `${tail}.slice(${i})`)
} else {
unpack_destructuring(contexts, element, `${tail}[${i}]`);
}
}); });
} else if (node.type === 'ObjectPattern') { } else if (node.type === 'ObjectPattern') {
node.properties.forEach((property) => { node.properties.forEach((property) => {

@ -20,7 +20,7 @@ type Property = {
type Context = { type Context = {
start: number; start: number;
end: number; end: number;
type: 'Identifier' | 'ArrayPattern' | 'ObjectPattern'; type: 'Identifier' | 'ArrayPattern' | 'ObjectPattern' | 'RestIdentifier';
name?: string; name?: string;
elements?: Context[]; elements?: Context[];
properties?: Property[]; properties?: Property[];
@ -35,6 +35,13 @@ function error_on_assignment_pattern(parser: Parser) {
} }
} }
function error_on_rest_pattern_not_last(parser: Parser) {
parser.error({
code: 'rest-pattern-not-last',
message: 'Rest destructuring expected to be last'
}, parser.index);
}
export default function read_context(parser: Parser) { export default function read_context(parser: Parser) {
const context: Context = { const context: Context = {
start: parser.index, start: parser.index,
@ -49,6 +56,11 @@ export default function read_context(parser: Parser) {
do { do {
parser.allow_whitespace(); parser.allow_whitespace();
const lastContext = context.elements[context.elements.length - 1];
if (lastContext && lastContext.type === 'RestIdentifier') {
error_on_rest_pattern_not_last(parser);
}
if (parser.template[parser.index] === ',') { if (parser.template[parser.index] === ',') {
context.elements.push(null); context.elements.push(null);
} else { } else {
@ -103,6 +115,22 @@ export default function read_context(parser: Parser) {
context.end = parser.index; context.end = parser.index;
} }
else if (parser.eat('...')) {
const name = parser.read_identifier();
if (name) {
context.type = 'RestIdentifier';
context.end = parser.index;
context.name = name;
}
else {
parser.error({
code: 'invalid-context',
message: 'Expected a rest pattern'
});
}
}
else { else {
const name = parser.read_identifier(); const name = parser.read_identifier();
if (name) { if (name) {
@ -122,4 +150,4 @@ export default function read_context(parser: Parser) {
} }
return context; return context;
} }

@ -1,3 +1,3 @@
{#each animals as [key, value]} {#each animals as [key, value, ...rest]}
<p>{key}: {value}</p> <p>{key}: {value}</p>
{/each} {/each}

@ -1,12 +1,12 @@
{ {
"html": { "html": {
"start": 0, "start": 0,
"end": 62, "end": 71,
"type": "Fragment", "type": "Fragment",
"children": [ "children": [
{ {
"start": 0, "start": 0,
"end": 62, "end": 71,
"type": "EachBlock", "type": "EachBlock",
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -16,37 +16,37 @@
}, },
"children": [ "children": [
{ {
"start": 33, "start": 42,
"end": 54, "end": 63,
"type": "Element", "type": "Element",
"name": "p", "name": "p",
"attributes": [], "attributes": [],
"children": [ "children": [
{ {
"start": 36, "start": 45,
"end": 41, "end": 50,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 37, "start": 46,
"end": 40, "end": 49,
"name": "key" "name": "key"
} }
}, },
{ {
"start": 41, "start": 50,
"end": 43, "end": 52,
"type": "Text", "type": "Text",
"data": ": " "data": ": "
}, },
{ {
"start": 43, "start": 52,
"end": 50, "end": 59,
"type": "MustacheTag", "type": "MustacheTag",
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 44, "start": 53,
"end": 49, "end": 58,
"name": "value" "name": "value"
} }
} }
@ -55,7 +55,7 @@
], ],
"context": { "context": {
"start": 18, "start": 18,
"end": 30, "end": 39,
"type": "ArrayPattern", "type": "ArrayPattern",
"elements": [ "elements": [
{ {
@ -69,6 +69,12 @@
"end": 29, "end": 29,
"type": "Identifier", "type": "Identifier",
"name": "value" "name": "value"
},
{
"start": 31,
"end": 38,
"type": "RestIdentifier",
"name": "rest"
} }
] ]
} }
@ -78,4 +84,4 @@
"css": null, "css": null,
"instance": null, "instance": null,
"module": null "module": null
} }

Loading…
Cancel
Save