Skip to content

Commit

Permalink
cell destructuring
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Dec 24, 2021
1 parent 09901d0 commit c3145db
Show file tree
Hide file tree
Showing 13 changed files with 518 additions and 17 deletions.
51 changes: 34 additions & 17 deletions src/parse.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getLineInfo, TokContext, tokTypes as tt, Parser} from "acorn";
import {getLineInfo, TokContext, Token, tokTypes as tt, Parser} from "acorn";
import defaultGlobals from "./globals.js";
import findReferences from "./references.js";
import findFeatures from "./features.js";
Expand Down Expand Up @@ -106,6 +106,7 @@ export class CellParser extends Parser {
this.O_function = 0;
this.O_async = false;
this.O_generator = false;
this.O_destructuring = null;
this.strict = true;
this.enterScope(SCOPE_FUNCTION | SCOPE_ASYNC | SCOPE_GENERATOR);
}
Expand Down Expand Up @@ -133,8 +134,22 @@ export class CellParser extends Parser {

// A non-empty cell?
else if (token.type !== tt.eof && token.type !== tt.semi) {
// A named cell?
if (token.type === tt.name) {

// A destructuring cell, maybe?
// (But not an object expression or arrow function!)
if (token.type === tt.parenL) {
id = this.parseParenAndDistinguishExpression(true);
if (id.type !== "ArrowFunctionExpression" && this.eat(tt.eq)) {
id = this.toAssignable(id, true, this.O_destructuring);
} else {
body = id;
id = null;
}
token = new Token(this);
}

// A simple named cell?
else if (token.type === tt.name) {
if (token.value === "viewof" || token.value === "mutable") {
token = lookahead.getToken();
if (token.type !== tt.name) {
Expand All @@ -152,22 +167,20 @@ export class CellParser extends Parser {
}
}

// A block?
if (token.type === tt.braceL) {
body = this.parseBlock();
// A block or an expression?
if (body === null) {
body = token.type === tt.braceL
? this.parseBlock()
: this.parseExpression();
}

// An expression?
// Possibly a function or class declaration?
else {
body = this.parseExpression();
if (
id === null &&
(body.type === "FunctionExpression" ||
body.type === "ClassExpression")
) {
id = body.id;
}
// Promote the name of a function or class declaration?
if (
id === null &&
(body.type === "FunctionExpression" ||
body.type === "ClassExpression")
) {
id = body.id;
}
}

Expand All @@ -190,6 +203,10 @@ export class CellParser extends Parser {
this.raise(node.start, `Identifier '${node.name}' is reserved`);
}
}
checkExpressionErrors(refDestructuringErrors, andThrow) {
this.O_destructuring = refDestructuringErrors;
return super.checkExpressionErrors(refDestructuringErrors, andThrow);
}
checkUnreserved(node) {
if (node.name === "viewof" || node.name === "mutable") {
this.raise(node.start, `Unexpected keyword '${node.name}'`);
Expand Down
1 change: 1 addition & 0 deletions test/input/destructure-array-literal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
([foo, ...bar]) = [1, 2, 3]
3 changes: 3 additions & 0 deletions test/input/destructure-block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
({foo, bar}) = {
return {foo: 1, bar: 2};
}
1 change: 1 addition & 0 deletions test/input/destructure-default-value-async.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
([x, y = x + await z]) = [1]
1 change: 1 addition & 0 deletions test/input/destructure-default-value.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
([x, y = 2]) = [1]
1 change: 1 addition & 0 deletions test/input/destructure-dynamic-import.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
({default: confetti}) = import("https://cdn.skypack.dev/canvas-confetti")
1 change: 1 addition & 0 deletions test/input/destructure-object-literal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
({foo, bar}) = ({foo: 1, bar: 2})
63 changes: 63 additions & 0 deletions test/output/destructure-array-literal.js.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"type": "Cell",
"start": 0,
"end": 28,
"id": {
"type": "ArrayPattern",
"start": 1,
"end": 14,
"elements": [
{
"type": "Identifier",
"start": 2,
"end": 5,
"name": "foo"
},
{
"type": "RestElement",
"start": 7,
"end": 13,
"argument": {
"type": "Identifier",
"start": 10,
"end": 13,
"name": "bar"
}
}
]
},
"body": {
"type": "ArrayExpression",
"start": 18,
"end": 27,
"elements": [
{
"type": "Literal",
"start": 19,
"end": 20,
"value": 1,
"raw": "1"
},
{
"type": "Literal",
"start": 22,
"end": 23,
"value": 2,
"raw": "2"
},
{
"type": "Literal",
"start": 25,
"end": 26,
"value": 3,
"raw": "3"
}
]
},
"async": false,
"generator": false,
"references": [],
"fileAttachments": [],
"databaseClients": [],
"secrets": []
}
123 changes: 123 additions & 0 deletions test/output/destructure-block.js.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
{
"type": "Cell",
"start": 0,
"end": 46,
"id": {
"type": "ObjectPattern",
"start": 1,
"end": 11,
"properties": [
{
"type": "Property",
"start": 2,
"end": 5,
"method": false,
"shorthand": true,
"computed": false,
"key": {
"type": "Identifier",
"start": 2,
"end": 5,
"name": "foo"
},
"kind": "init",
"value": {
"type": "Identifier",
"start": 2,
"end": 5,
"name": "foo"
}
},
{
"type": "Property",
"start": 7,
"end": 10,
"method": false,
"shorthand": true,
"computed": false,
"key": {
"type": "Identifier",
"start": 7,
"end": 10,
"name": "bar"
},
"kind": "init",
"value": {
"type": "Identifier",
"start": 7,
"end": 10,
"name": "bar"
}
}
]
},
"body": {
"type": "BlockStatement",
"start": 15,
"end": 45,
"body": [
{
"type": "ReturnStatement",
"start": 19,
"end": 43,
"argument": {
"type": "ObjectExpression",
"start": 26,
"end": 42,
"properties": [
{
"type": "Property",
"start": 27,
"end": 33,
"method": false,
"shorthand": false,
"computed": false,
"key": {
"type": "Identifier",
"start": 27,
"end": 30,
"name": "foo"
},
"value": {
"type": "Literal",
"start": 32,
"end": 33,
"value": 1,
"raw": "1"
},
"kind": "init"
},
{
"type": "Property",
"start": 35,
"end": 41,
"method": false,
"shorthand": false,
"computed": false,
"key": {
"type": "Identifier",
"start": 35,
"end": 38,
"name": "bar"
},
"value": {
"type": "Literal",
"start": 40,
"end": 41,
"value": 2,
"raw": "2"
},
"kind": "init"
}
]
}
}
]
},
"async": false,
"generator": false,
"references": [],
"fileAttachments": [],
"databaseClients": [],
"secrets": []
}
72 changes: 72 additions & 0 deletions test/output/destructure-default-value-async.js.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"type": "Cell",
"start": 0,
"end": 29,
"id": {
"type": "ArrayPattern",
"start": 1,
"end": 21,
"elements": [
{
"type": "Identifier",
"start": 2,
"end": 3,
"name": "x"
},
{
"type": "AssignmentPattern",
"start": 5,
"end": 20,
"left": {
"type": "Identifier",
"start": 5,
"end": 6,
"name": "y"
},
"right": {
"type": "BinaryExpression",
"start": 9,
"end": 20,
"left": {
"type": "Identifier",
"start": 9,
"end": 10,
"name": "x"
},
"operator": "+",
"right": {
"type": "AwaitExpression",
"start": 13,
"end": 20,
"argument": {
"type": "Identifier",
"start": 19,
"end": 20,
"name": "z"
}
}
}
}
]
},
"body": {
"type": "ArrayExpression",
"start": 25,
"end": 28,
"elements": [
{
"type": "Literal",
"start": 26,
"end": 27,
"value": 1,
"raw": "1"
}
]
},
"async": true,
"generator": false,
"references": [],
"fileAttachments": [],
"databaseClients": [],
"secrets": []
}
Loading

0 comments on commit c3145db

Please sign in to comment.