From 7f5a259046431816b77eab7d4dc279e81cc55396 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Wed, 4 Dec 2019 11:43:42 -0800 Subject: [PATCH 01/10] cell destructuring --- src/features.js | 3 +- src/parse.js | 76 ++++++++--- src/references.js | 27 +++- src/walk.js | 8 +- test/input/destructure-array-literal.js | 1 + test/input/destructure-block.js | 3 + test/input/destructure-computed.js | 1 + test/input/destructure-default-value-async.js | 1 + .../input/destructure-default-value-secret.js | 1 + test/input/destructure-default-value.js | 1 + test/input/destructure-dynamic-import.js | 1 + test/input/destructure-keyword.js | 1 + test/input/destructure-mutable.js | 1 + .../destructure-nested-object-literal.js | 1 + test/input/destructure-object-literal.js | 1 + test/output/destructure-array-literal.js.json | 63 +++++++++ test/output/destructure-block.js.json | 123 ++++++++++++++++++ test/output/destructure-computed.js.json | 11 ++ .../destructure-default-value-async.js.json | 79 +++++++++++ .../destructure-default-value-secret.js.json | 87 +++++++++++++ test/output/destructure-default-value.js.json | 56 ++++++++ .../output/destructure-dynamic-import.js.json | 51 ++++++++ test/output/destructure-keyword.js.json | 11 ++ test/output/destructure-mutable.js.json | 11 ++ .../destructure-nested-object-literal.js.json | 89 +++++++++++++ .../output/destructure-object-literal.js.json | 111 ++++++++++++++++ 26 files changed, 794 insertions(+), 25 deletions(-) create mode 100644 test/input/destructure-array-literal.js create mode 100644 test/input/destructure-block.js create mode 100644 test/input/destructure-computed.js create mode 100644 test/input/destructure-default-value-async.js create mode 100644 test/input/destructure-default-value-secret.js create mode 100644 test/input/destructure-default-value.js create mode 100644 test/input/destructure-dynamic-import.js create mode 100644 test/input/destructure-keyword.js create mode 100644 test/input/destructure-mutable.js create mode 100644 test/input/destructure-nested-object-literal.js create mode 100644 test/input/destructure-object-literal.js create mode 100644 test/output/destructure-array-literal.js.json create mode 100644 test/output/destructure-block.js.json create mode 100644 test/output/destructure-computed.js.json create mode 100644 test/output/destructure-default-value-async.js.json create mode 100644 test/output/destructure-default-value-secret.js.json create mode 100644 test/output/destructure-default-value.js.json create mode 100644 test/output/destructure-dynamic-import.js.json create mode 100644 test/output/destructure-keyword.js.json create mode 100644 test/output/destructure-mutable.js.json create mode 100644 test/output/destructure-nested-object-literal.js.json create mode 100644 test/output/destructure-object-literal.js.json diff --git a/src/features.js b/src/features.js index e0a5580..b1cfaec 100644 --- a/src/features.js +++ b/src/features.js @@ -2,12 +2,11 @@ import {simple} from "acorn-walk"; import walk from "./walk.js"; export default function findFeatures(cell, featureName) { - const ast = {type: "Program", body: [cell.body]}; const features = new Map(); const {references} = cell; simple( - ast, + cell, { CallExpression: node => { const {callee, arguments: args} = node; diff --git a/src/parse.js b/src/parse.js index eec8f38..9a8ed27 100644 --- a/src/parse.js +++ b/src/parse.js @@ -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"; @@ -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); } @@ -133,8 +134,23 @@ 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); + this.checkCellDeclaration(id); + } 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) { @@ -152,22 +168,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; } } @@ -184,12 +198,40 @@ export class CellParser extends Parser { ? node : super.toAssignable(node, isBinding, refDestructuringErrors); } + checkCellDeclaration(node) { + switch (node.type) { + case "Identifier": + break; + case "ObjectPattern": + for (const p of node.properties) this.checkCellDeclaration(p); + break; + case "ArrayPattern": + for (const e of node.elements) e && this.checkCellDeclaration(e); + break; + case "Property": + this.checkCellDeclaration(node.value); + break; + case "RestElement": + this.checkCellDeclaration(node.argument); + break; + case "AssignmentPattern": + this.checkCellDeclaration(node.left); + break; + default: + this.unexpected(); + break; + } + } checkLocal(id) { const node = id.id || id; if (defaultGlobals.has(node.name) || node.name === "arguments") { 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}'`); diff --git a/src/references.js b/src/references.js index 308c323..e1208df 100644 --- a/src/references.js +++ b/src/references.js @@ -26,7 +26,6 @@ function declaresArguments(node) { } export default function findReferences(cell, globals) { - const ast = {type: "Program", body: [cell.body]}; const locals = new Map; const globalSet = new Set(globals); const references = []; @@ -81,11 +80,11 @@ export default function findReferences(cell, globals) { } function declareModuleSpecifier(node) { - declareLocal(ast, node.local); + declareLocal(cell.body, node.local); } ancestor( - ast, + cell.body, { VariableDeclaration: (node, parents) => { let parent = null; @@ -154,8 +153,26 @@ export default function findReferences(cell, globals) { } } + function assignmentIdentifier(node, parents) { + if (parents.length > 2 && parents[1].type === "AssignmentPattern" && parents[2] === parents[1].right) { + identifier(node, parents); + } + } + + if (cell.id && (cell.id.type === "ArrayPattern" || cell.id.type === "ObjectPattern")) { + declarePattern(cell.id, cell.id); + ancestor( + cell.id, + { + VariablePattern: assignmentIdentifier, + Identifier: assignmentIdentifier + }, + walk + ); + } + ancestor( - ast, + cell.body, { VariablePattern: identifier, Identifier: identifier @@ -210,7 +227,7 @@ export default function findReferences(cell, globals) { } ancestor( - ast, + cell.body, { AssignmentExpression: checkConstLeft, AssignmentPattern: checkConstLeft, diff --git a/src/walk.js b/src/walk.js index b4d23a3..a04c5b7 100644 --- a/src/walk.js +++ b/src/walk.js @@ -1,7 +1,13 @@ import {make} from "acorn-walk"; export default make({ - Import() {}, + Cell(node, st, c) { + if (node.id) c(node.id, st); + c(node.body, st); + }, + CellTag(node, st, c) { + c(node.body, st); + }, ViewExpression(node, st, c) { c(node.id, st, "Identifier"); }, diff --git a/test/input/destructure-array-literal.js b/test/input/destructure-array-literal.js new file mode 100644 index 0000000..f97d2ba --- /dev/null +++ b/test/input/destructure-array-literal.js @@ -0,0 +1 @@ +([foo, ...bar]) = [1, 2, 3] diff --git a/test/input/destructure-block.js b/test/input/destructure-block.js new file mode 100644 index 0000000..ff2e9fd --- /dev/null +++ b/test/input/destructure-block.js @@ -0,0 +1,3 @@ +({foo, bar}) = { + return {foo: 1, bar: 2}; +} diff --git a/test/input/destructure-computed.js b/test/input/destructure-computed.js new file mode 100644 index 0000000..7abe96e --- /dev/null +++ b/test/input/destructure-computed.js @@ -0,0 +1 @@ +({["foo"]}) = 42 diff --git a/test/input/destructure-default-value-async.js b/test/input/destructure-default-value-async.js new file mode 100644 index 0000000..c61132a --- /dev/null +++ b/test/input/destructure-default-value-async.js @@ -0,0 +1 @@ +([x, y = x + await z]) = [1] diff --git a/test/input/destructure-default-value-secret.js b/test/input/destructure-default-value-secret.js new file mode 100644 index 0000000..fddbd1f --- /dev/null +++ b/test/input/destructure-default-value-secret.js @@ -0,0 +1 @@ +([x, y = Secret("foo")]) = [1] diff --git a/test/input/destructure-default-value.js b/test/input/destructure-default-value.js new file mode 100644 index 0000000..598662c --- /dev/null +++ b/test/input/destructure-default-value.js @@ -0,0 +1 @@ +([x, y = 2]) = [1] diff --git a/test/input/destructure-dynamic-import.js b/test/input/destructure-dynamic-import.js new file mode 100644 index 0000000..e951b20 --- /dev/null +++ b/test/input/destructure-dynamic-import.js @@ -0,0 +1 @@ +({default: confetti}) = import("https://cdn.skypack.dev/canvas-confetti") diff --git a/test/input/destructure-keyword.js b/test/input/destructure-keyword.js new file mode 100644 index 0000000..a6bd1e2 --- /dev/null +++ b/test/input/destructure-keyword.js @@ -0,0 +1 @@ +([mutable]) = [42] diff --git a/test/input/destructure-mutable.js b/test/input/destructure-mutable.js new file mode 100644 index 0000000..39b8101 --- /dev/null +++ b/test/input/destructure-mutable.js @@ -0,0 +1 @@ +([mutable foo]) = [42] diff --git a/test/input/destructure-nested-object-literal.js b/test/input/destructure-nested-object-literal.js new file mode 100644 index 0000000..0efdc76 --- /dev/null +++ b/test/input/destructure-nested-object-literal.js @@ -0,0 +1 @@ +({foo: {bar: {baz: qux}}}) = ({}) diff --git a/test/input/destructure-object-literal.js b/test/input/destructure-object-literal.js new file mode 100644 index 0000000..90f1684 --- /dev/null +++ b/test/input/destructure-object-literal.js @@ -0,0 +1 @@ +({foo, bar}) = ({foo: 1, bar: 2}) diff --git a/test/output/destructure-array-literal.js.json b/test/output/destructure-array-literal.js.json new file mode 100644 index 0000000..124c648 --- /dev/null +++ b/test/output/destructure-array-literal.js.json @@ -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": [] +} \ No newline at end of file diff --git a/test/output/destructure-block.js.json b/test/output/destructure-block.js.json new file mode 100644 index 0000000..7041b19 --- /dev/null +++ b/test/output/destructure-block.js.json @@ -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": [] +} \ No newline at end of file diff --git a/test/output/destructure-computed.js.json b/test/output/destructure-computed.js.json new file mode 100644 index 0000000..0b75260 --- /dev/null +++ b/test/output/destructure-computed.js.json @@ -0,0 +1,11 @@ +{ + "error": { + "type": "SyntaxError", + "message": "Unexpected token (1:9)", + "pos": 9, + "loc": { + "line": 1, + "column": 9 + } + } +} \ No newline at end of file diff --git a/test/output/destructure-default-value-async.js.json b/test/output/destructure-default-value-async.js.json new file mode 100644 index 0000000..d76cce7 --- /dev/null +++ b/test/output/destructure-default-value-async.js.json @@ -0,0 +1,79 @@ +{ + "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": [ + { + "type": "Identifier", + "start": 19, + "end": 20, + "name": "z" + } + ], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file diff --git a/test/output/destructure-default-value-secret.js.json b/test/output/destructure-default-value-secret.js.json new file mode 100644 index 0000000..781e49d --- /dev/null +++ b/test/output/destructure-default-value-secret.js.json @@ -0,0 +1,87 @@ +{ + "type": "Cell", + "start": 0, + "end": 31, + "id": { + "type": "ArrayPattern", + "start": 1, + "end": 23, + "elements": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + { + "type": "AssignmentPattern", + "start": 5, + "end": 22, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + }, + "right": { + "type": "CallExpression", + "start": 9, + "end": 22, + "callee": { + "type": "Identifier", + "start": 9, + "end": 15, + "name": "Secret" + }, + "arguments": [ + { + "type": "Literal", + "start": 16, + "end": 21, + "value": "foo", + "raw": "\"foo\"" + } + ], + "optional": false + } + } + ] + }, + "body": { + "type": "ArrayExpression", + "start": 27, + "end": 30, + "elements": [ + { + "type": "Literal", + "start": 28, + "end": 29, + "value": 1, + "raw": "1" + } + ] + }, + "async": false, + "generator": false, + "references": [ + { + "type": "Identifier", + "start": 9, + "end": 15, + "name": "Secret" + } + ], + "fileAttachments": [], + "databaseClients": [], + "secrets": [ + [ + "foo", + [ + { + "start": 16, + "end": 21 + } + ] + ] + ] +} \ No newline at end of file diff --git a/test/output/destructure-default-value.js.json b/test/output/destructure-default-value.js.json new file mode 100644 index 0000000..8b3d039 --- /dev/null +++ b/test/output/destructure-default-value.js.json @@ -0,0 +1,56 @@ +{ + "type": "Cell", + "start": 0, + "end": 19, + "id": { + "type": "ArrayPattern", + "start": 1, + "end": 11, + "elements": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + { + "type": "AssignmentPattern", + "start": 5, + "end": 10, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + }, + "right": { + "type": "Literal", + "start": 9, + "end": 10, + "value": 2, + "raw": "2" + } + } + ] + }, + "body": { + "type": "ArrayExpression", + "start": 15, + "end": 18, + "elements": [ + { + "type": "Literal", + "start": 16, + "end": 17, + "value": 1, + "raw": "1" + } + ] + }, + "async": false, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file diff --git a/test/output/destructure-dynamic-import.js.json b/test/output/destructure-dynamic-import.js.json new file mode 100644 index 0000000..f466bf3 --- /dev/null +++ b/test/output/destructure-dynamic-import.js.json @@ -0,0 +1,51 @@ +{ + "type": "Cell", + "start": 0, + "end": 74, + "id": { + "type": "ObjectPattern", + "start": 1, + "end": 20, + "properties": [ + { + "type": "Property", + "start": 2, + "end": 19, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 2, + "end": 9, + "name": "default" + }, + "value": { + "type": "Identifier", + "start": 11, + "end": 19, + "name": "confetti" + }, + "kind": "init" + } + ] + }, + "body": { + "type": "ImportExpression", + "start": 24, + "end": 73, + "source": { + "type": "Literal", + "start": 31, + "end": 72, + "value": "https://cdn.skypack.dev/canvas-confetti", + "raw": "\"https://cdn.skypack.dev/canvas-confetti\"" + } + }, + "async": false, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file diff --git a/test/output/destructure-keyword.js.json b/test/output/destructure-keyword.js.json new file mode 100644 index 0000000..0b75260 --- /dev/null +++ b/test/output/destructure-keyword.js.json @@ -0,0 +1,11 @@ +{ + "error": { + "type": "SyntaxError", + "message": "Unexpected token (1:9)", + "pos": 9, + "loc": { + "line": 1, + "column": 9 + } + } +} \ No newline at end of file diff --git a/test/output/destructure-mutable.js.json b/test/output/destructure-mutable.js.json new file mode 100644 index 0000000..5a4ba8f --- /dev/null +++ b/test/output/destructure-mutable.js.json @@ -0,0 +1,11 @@ +{ + "error": { + "type": "SyntaxError", + "message": "Unexpected token (1:18)", + "pos": 18, + "loc": { + "line": 1, + "column": 18 + } + } +} \ No newline at end of file diff --git a/test/output/destructure-nested-object-literal.js.json b/test/output/destructure-nested-object-literal.js.json new file mode 100644 index 0000000..e6854b0 --- /dev/null +++ b/test/output/destructure-nested-object-literal.js.json @@ -0,0 +1,89 @@ +{ + "type": "Cell", + "start": 0, + "end": 34, + "id": { + "type": "ObjectPattern", + "start": 1, + "end": 25, + "properties": [ + { + "type": "Property", + "start": 2, + "end": 24, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 2, + "end": 5, + "name": "foo" + }, + "value": { + "type": "ObjectPattern", + "start": 7, + "end": 24, + "properties": [ + { + "type": "Property", + "start": 8, + "end": 23, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 8, + "end": 11, + "name": "bar" + }, + "value": { + "type": "ObjectPattern", + "start": 13, + "end": 23, + "properties": [ + { + "type": "Property", + "start": 14, + "end": 22, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 14, + "end": 17, + "name": "baz" + }, + "value": { + "type": "Identifier", + "start": 19, + "end": 22, + "name": "qux" + }, + "kind": "init" + } + ] + }, + "kind": "init" + } + ] + }, + "kind": "init" + } + ] + }, + "body": { + "type": "ObjectExpression", + "start": 30, + "end": 32, + "properties": [] + }, + "async": false, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file diff --git a/test/output/destructure-object-literal.js.json b/test/output/destructure-object-literal.js.json new file mode 100644 index 0000000..7b8ca5b --- /dev/null +++ b/test/output/destructure-object-literal.js.json @@ -0,0 +1,111 @@ +{ + "type": "Cell", + "start": 0, + "end": 34, + "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": "ObjectExpression", + "start": 16, + "end": 32, + "properties": [ + { + "type": "Property", + "start": 17, + "end": 23, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 17, + "end": 20, + "name": "foo" + }, + "value": { + "type": "Literal", + "start": 22, + "end": 23, + "value": 1, + "raw": "1" + }, + "kind": "init" + }, + { + "type": "Property", + "start": 25, + "end": 31, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 25, + "end": 28, + "name": "bar" + }, + "value": { + "type": "Literal", + "start": 30, + "end": 31, + "value": 2, + "raw": "2" + }, + "kind": "init" + } + ] + }, + "async": false, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file From e2fd78cb3cd50c07cbcf4fd74ee4d860fc3335e4 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Fri, 24 Dec 2021 16:27:05 -0800 Subject: [PATCH 02/10] add parenthesized name test --- test/input/named-with-parens.js | 1 + test/output/named-with-parens.js.json | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/input/named-with-parens.js create mode 100644 test/output/named-with-parens.js.json diff --git a/test/input/named-with-parens.js b/test/input/named-with-parens.js new file mode 100644 index 0000000..54eacbb --- /dev/null +++ b/test/input/named-with-parens.js @@ -0,0 +1 @@ +(foo) = 42 diff --git a/test/output/named-with-parens.js.json b/test/output/named-with-parens.js.json new file mode 100644 index 0000000..803c05f --- /dev/null +++ b/test/output/named-with-parens.js.json @@ -0,0 +1,24 @@ +{ + "type": "Cell", + "start": 0, + "end": 11, + "id": { + "type": "Identifier", + "start": 1, + "end": 4, + "name": "foo" + }, + "body": { + "type": "Literal", + "start": 8, + "end": 10, + "value": 42, + "raw": "42" + }, + "async": false, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file From e694234539568dded69bd487010af1ae66a675cd Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Sat, 25 Dec 2021 10:18:01 -0800 Subject: [PATCH 03/10] =?UTF-8?q?don=E2=80=99t=20allow=20await=20or=20yiel?= =?UTF-8?q?d=20in=20default=20values?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parse.js | 1 + .../destructure-default-value-reference.js | 1 + test/input/destructure-default-value-yield.js | 1 + test/input/destructure-multiple.js | 1 + .../destructure-default-value-async.js.json | 84 ++----------------- ...estructure-default-value-reference.js.json | 74 ++++++++++++++++ .../destructure-default-value-yield.js.json | 11 +++ test/output/destructure-multiple.js.json | 11 +++ 8 files changed, 108 insertions(+), 76 deletions(-) create mode 100644 test/input/destructure-default-value-reference.js create mode 100644 test/input/destructure-default-value-yield.js create mode 100644 test/input/destructure-multiple.js create mode 100644 test/output/destructure-default-value-reference.js.json create mode 100644 test/output/destructure-default-value-yield.js.json create mode 100644 test/output/destructure-multiple.js.json diff --git a/src/parse.js b/src/parse.js index 9a8ed27..90340cb 100644 --- a/src/parse.js +++ b/src/parse.js @@ -140,6 +140,7 @@ export class CellParser extends Parser { if (token.type === tt.parenL) { id = this.parseParenAndDistinguishExpression(true); if (id.type !== "ArrowFunctionExpression" && this.eat(tt.eq)) { + this.checkYieldAwaitInDefaultParams(); id = this.toAssignable(id, true, this.O_destructuring); this.checkCellDeclaration(id); } else { diff --git a/test/input/destructure-default-value-reference.js b/test/input/destructure-default-value-reference.js new file mode 100644 index 0000000..8bd8183 --- /dev/null +++ b/test/input/destructure-default-value-reference.js @@ -0,0 +1 @@ +([x, y = x + z]) = [1] diff --git a/test/input/destructure-default-value-yield.js b/test/input/destructure-default-value-yield.js new file mode 100644 index 0000000..c5bde25 --- /dev/null +++ b/test/input/destructure-default-value-yield.js @@ -0,0 +1 @@ +([x, y = x + yield z]) = [1] diff --git a/test/input/destructure-multiple.js b/test/input/destructure-multiple.js new file mode 100644 index 0000000..24bf800 --- /dev/null +++ b/test/input/destructure-multiple.js @@ -0,0 +1 @@ +([x], y) = [1] diff --git a/test/output/destructure-default-value-async.js.json b/test/output/destructure-default-value-async.js.json index d76cce7..d436b50 100644 --- a/test/output/destructure-default-value-async.js.json +++ b/test/output/destructure-default-value-async.js.json @@ -1,79 +1,11 @@ { - "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": [ - { - "type": "Identifier", - "start": 19, - "end": 20, - "name": "z" + "error": { + "type": "SyntaxError", + "message": "Await expression cannot be a default value (1:13)", + "pos": 13, + "loc": { + "line": 1, + "column": 13 } - ], - "fileAttachments": [], - "databaseClients": [], - "secrets": [] + } } \ No newline at end of file diff --git a/test/output/destructure-default-value-reference.js.json b/test/output/destructure-default-value-reference.js.json new file mode 100644 index 0000000..0bb6751 --- /dev/null +++ b/test/output/destructure-default-value-reference.js.json @@ -0,0 +1,74 @@ +{ + "type": "Cell", + "start": 0, + "end": 23, + "id": { + "type": "ArrayPattern", + "start": 1, + "end": 15, + "elements": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + { + "type": "AssignmentPattern", + "start": 5, + "end": 14, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + }, + "right": { + "type": "BinaryExpression", + "start": 9, + "end": 14, + "left": { + "type": "Identifier", + "start": 9, + "end": 10, + "name": "x" + }, + "operator": "+", + "right": { + "type": "Identifier", + "start": 13, + "end": 14, + "name": "z" + } + } + } + ] + }, + "body": { + "type": "ArrayExpression", + "start": 19, + "end": 22, + "elements": [ + { + "type": "Literal", + "start": 20, + "end": 21, + "value": 1, + "raw": "1" + } + ] + }, + "async": false, + "generator": false, + "references": [ + { + "type": "Identifier", + "start": 13, + "end": 14, + "name": "z" + } + ], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file diff --git a/test/output/destructure-default-value-yield.js.json b/test/output/destructure-default-value-yield.js.json new file mode 100644 index 0000000..22e3c7a --- /dev/null +++ b/test/output/destructure-default-value-yield.js.json @@ -0,0 +1,11 @@ +{ + "error": { + "type": "SyntaxError", + "message": "Cannot use 'yield' as identifier inside a generator (1:13)", + "pos": 13, + "loc": { + "line": 1, + "column": 13 + } + } +} \ No newline at end of file diff --git a/test/output/destructure-multiple.js.json b/test/output/destructure-multiple.js.json new file mode 100644 index 0000000..b41dee9 --- /dev/null +++ b/test/output/destructure-multiple.js.json @@ -0,0 +1,11 @@ +{ + "error": { + "type": "SyntaxError", + "message": "Assigning to rvalue (1:1)", + "pos": 1, + "loc": { + "line": 1, + "column": 1 + } + } +} \ No newline at end of file From 632daaae86bcdc8fe914c1e01c503e63231f781a Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Sat, 25 Dec 2021 10:24:24 -0800 Subject: [PATCH 04/10] simplify --- src/parse.js | 7 +------ test/input/destructure-trailing-comma.js | 1 + test/output/destructure-trailing-comma.js.json | 11 +++++++++++ 3 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 test/input/destructure-trailing-comma.js create mode 100644 test/output/destructure-trailing-comma.js.json diff --git a/src/parse.js b/src/parse.js index 90340cb..da74e2a 100644 --- a/src/parse.js +++ b/src/parse.js @@ -106,7 +106,6 @@ 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); } @@ -141,7 +140,7 @@ export class CellParser extends Parser { id = this.parseParenAndDistinguishExpression(true); if (id.type !== "ArrowFunctionExpression" && this.eat(tt.eq)) { this.checkYieldAwaitInDefaultParams(); - id = this.toAssignable(id, true, this.O_destructuring); + id = this.toAssignable(id, true); this.checkCellDeclaration(id); } else { body = id; @@ -229,10 +228,6 @@ 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}'`); diff --git a/test/input/destructure-trailing-comma.js b/test/input/destructure-trailing-comma.js new file mode 100644 index 0000000..39503b3 --- /dev/null +++ b/test/input/destructure-trailing-comma.js @@ -0,0 +1 @@ +([x], ) = [1] diff --git a/test/output/destructure-trailing-comma.js.json b/test/output/destructure-trailing-comma.js.json new file mode 100644 index 0000000..f129028 --- /dev/null +++ b/test/output/destructure-trailing-comma.js.json @@ -0,0 +1,11 @@ +{ + "error": { + "type": "SyntaxError", + "message": "Unexpected token (1:6)", + "pos": 6, + "loc": { + "line": 1, + "column": 6 + } + } +} \ No newline at end of file From 283fb42d564587398b526b45e0b12361d5cf6135 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Sat, 25 Dec 2021 10:33:22 -0800 Subject: [PATCH 05/10] simplify, and more tests --- src/parse.js | 4 +- test/input/arrow-function-expression.js | 1 + test/input/object-literal-async.js | 1 + test/input/object-literal-yield.js | 1 + test/output/arrow-function-expression.js.json | 11 +++++ test/output/object-literal-async.js.json | 46 ++++++++++++++++++ test/output/object-literal-yield.js.json | 47 +++++++++++++++++++ 7 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 test/input/arrow-function-expression.js create mode 100644 test/input/object-literal-async.js create mode 100644 test/input/object-literal-yield.js create mode 100644 test/output/arrow-function-expression.js.json create mode 100644 test/output/object-literal-async.js.json create mode 100644 test/output/object-literal-yield.js.json diff --git a/src/parse.js b/src/parse.js index da74e2a..d6e829c 100644 --- a/src/parse.js +++ b/src/parse.js @@ -135,10 +135,10 @@ export class CellParser extends Parser { else if (token.type !== tt.eof && token.type !== tt.semi) { // A destructuring cell, maybe? - // (But not an object expression or arrow function!) + // (A parenthesized expression followed by the equals operator.) if (token.type === tt.parenL) { id = this.parseParenAndDistinguishExpression(true); - if (id.type !== "ArrowFunctionExpression" && this.eat(tt.eq)) { + if (this.eat(tt.eq)) { this.checkYieldAwaitInDefaultParams(); id = this.toAssignable(id, true); this.checkCellDeclaration(id); diff --git a/test/input/arrow-function-expression.js b/test/input/arrow-function-expression.js new file mode 100644 index 0000000..6a1bfa0 --- /dev/null +++ b/test/input/arrow-function-expression.js @@ -0,0 +1 @@ +([x]) => { return [x]; } = 2 diff --git a/test/input/object-literal-async.js b/test/input/object-literal-async.js new file mode 100644 index 0000000..0cbb4d1 --- /dev/null +++ b/test/input/object-literal-async.js @@ -0,0 +1 @@ +({foo: await 42}) diff --git a/test/input/object-literal-yield.js b/test/input/object-literal-yield.js new file mode 100644 index 0000000..20dbf0e --- /dev/null +++ b/test/input/object-literal-yield.js @@ -0,0 +1 @@ +({foo: yield 42}) diff --git a/test/output/arrow-function-expression.js.json b/test/output/arrow-function-expression.js.json new file mode 100644 index 0000000..d7f58a0 --- /dev/null +++ b/test/output/arrow-function-expression.js.json @@ -0,0 +1,11 @@ +{ + "error": { + "type": "SyntaxError", + "message": "Assigning to rvalue (1:0)", + "pos": 0, + "loc": { + "line": 1, + "column": 0 + } + } +} \ No newline at end of file diff --git a/test/output/object-literal-async.js.json b/test/output/object-literal-async.js.json new file mode 100644 index 0000000..37d52c1 --- /dev/null +++ b/test/output/object-literal-async.js.json @@ -0,0 +1,46 @@ +{ + "type": "Cell", + "start": 0, + "end": 18, + "id": null, + "body": { + "type": "ObjectExpression", + "start": 1, + "end": 16, + "properties": [ + { + "type": "Property", + "start": 2, + "end": 15, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 2, + "end": 5, + "name": "foo" + }, + "value": { + "type": "AwaitExpression", + "start": 7, + "end": 15, + "argument": { + "type": "Literal", + "start": 13, + "end": 15, + "value": 42, + "raw": "42" + } + }, + "kind": "init" + } + ] + }, + "async": true, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file diff --git a/test/output/object-literal-yield.js.json b/test/output/object-literal-yield.js.json new file mode 100644 index 0000000..0f98d52 --- /dev/null +++ b/test/output/object-literal-yield.js.json @@ -0,0 +1,47 @@ +{ + "type": "Cell", + "start": 0, + "end": 18, + "id": null, + "body": { + "type": "ObjectExpression", + "start": 1, + "end": 16, + "properties": [ + { + "type": "Property", + "start": 2, + "end": 15, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 2, + "end": 5, + "name": "foo" + }, + "value": { + "type": "YieldExpression", + "start": 7, + "end": 15, + "delegate": false, + "argument": { + "type": "Literal", + "start": 13, + "end": 15, + "value": 42, + "raw": "42" + } + }, + "kind": "init" + } + ] + }, + "async": false, + "generator": true, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file From 2c93848a23a535ad18fbba0038c990899c1ee1a5 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Sat, 25 Dec 2021 10:39:55 -0800 Subject: [PATCH 06/10] tiny optimization --- src/parse.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse.js b/src/parse.js index d6e829c..7bd7ea0 100644 --- a/src/parse.js +++ b/src/parse.js @@ -142,11 +142,11 @@ export class CellParser extends Parser { this.checkYieldAwaitInDefaultParams(); id = this.toAssignable(id, true); this.checkCellDeclaration(id); + token = new Token(this); } else { body = id; id = null; } - token = new Token(this); } // A simple named cell? From 47d033b475529057b85fb82d19730b4842f51d89 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Sat, 25 Dec 2021 10:45:55 -0800 Subject: [PATCH 07/10] test parenthesized named function --- src/parse.js | 6 +-- test/input/parenthesized-named-function.js | 1 + .../parenthesized-named-function.js.json | 51 +++++++++++++++++++ 3 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 test/input/parenthesized-named-function.js create mode 100644 test/output/parenthesized-named-function.js.json diff --git a/src/parse.js b/src/parse.js index 7bd7ea0..f0b45f5 100644 --- a/src/parse.js +++ b/src/parse.js @@ -134,8 +134,8 @@ export class CellParser extends Parser { // A non-empty cell? else if (token.type !== tt.eof && token.type !== tt.semi) { - // A destructuring cell, maybe? - // (A parenthesized expression followed by the equals operator.) + // A destructuring cell, or parenthesized expression? (A destructuring + // cell is a parenthesized expression followed by the equals operator.) if (token.type === tt.parenL) { id = this.parseParenAndDistinguishExpression(true); if (this.eat(tt.eq)) { @@ -168,7 +168,7 @@ export class CellParser extends Parser { } } - // A block or an expression? + // A block or non-parenthesized expression? if (body === null) { body = token.type === tt.braceL ? this.parseBlock() diff --git a/test/input/parenthesized-named-function.js b/test/input/parenthesized-named-function.js new file mode 100644 index 0000000..40f3093 --- /dev/null +++ b/test/input/parenthesized-named-function.js @@ -0,0 +1 @@ +(function foo() { return 42; }) diff --git a/test/output/parenthesized-named-function.js.json b/test/output/parenthesized-named-function.js.json new file mode 100644 index 0000000..9683fa6 --- /dev/null +++ b/test/output/parenthesized-named-function.js.json @@ -0,0 +1,51 @@ +{ + "type": "Cell", + "start": 0, + "end": 32, + "id": { + "type": "Identifier", + "start": 10, + "end": 13, + "name": "foo" + }, + "body": { + "type": "FunctionExpression", + "start": 1, + "end": 30, + "id": { + "type": "Identifier", + "start": 10, + "end": 13, + "name": "foo" + }, + "expression": false, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "BlockStatement", + "start": 16, + "end": 30, + "body": [ + { + "type": "ReturnStatement", + "start": 18, + "end": 28, + "argument": { + "type": "Literal", + "start": 25, + "end": 27, + "value": 42, + "raw": "42" + } + } + ] + } + }, + "async": false, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [] +} \ No newline at end of file From a3640032342584093956af7c9622eeb5c4285d98 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Mon, 27 Dec 2021 08:16:26 -0800 Subject: [PATCH 08/10] comment on cell declaration restrictions --- src/parse.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/parse.js b/src/parse.js index f0b45f5..e091a17 100644 --- a/src/parse.js +++ b/src/parse.js @@ -218,6 +218,7 @@ export class CellParser extends Parser { this.checkCellDeclaration(node.left); break; default: + // Don’t allow destructuring into viewof or mutable declarations. this.unexpected(); break; } From 98467c866e5028a4e17397b827da3977abe408d3 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Mon, 27 Dec 2021 19:45:56 -0800 Subject: [PATCH 09/10] expose declaration nodes --- src/parse.js | 81 ++++++++++++++----- test/output/anonymous-block-cell.js.json | 3 +- test/output/anonymous-expression-cell.js.json | 3 +- test/output/anonymous-function.js.json | 3 +- test/output/await-block-cell.js.json | 3 +- ...await-in-arrow-function-expression.js.json | 3 +- test/output/await-in-arrow-function.js.json | 3 +- test/output/await-in-class.js.json | 3 +- test/output/await-in-function.js.json | 3 +- test/output/await-in-markdown.md.json | 3 +- test/output/await-yield.js.json | 3 +- .../backslash-after-dollar-markdown.md.json | 3 +- .../backslash-before-dollar-markdown.md.json | 3 +- test/output/backslash-markdown.md.json | 3 +- test/output/bare-dynamic-import.js.json | 3 +- test/output/basic.db.sql.json | 3 +- test/output/basic.html.json | 3 +- test/output/basic.sql.json | 3 +- test/output/basic.tex.json | 3 +- test/output/bigint-zero.js.json | 3 +- test/output/bigint.js.json | 3 +- test/output/binary-expression.js.json | 3 +- test/output/block-leading-comment.js.json | 10 ++- test/output/block-trailing-comment.js.json | 10 ++- test/output/catch-clause.js.json | 3 +- test/output/comment.js.json | 3 +- test/output/computed-property-name.js.json | 3 +- test/output/database-client.js.json | 3 +- test/output/destructure-array-literal.js.json | 16 +++- test/output/destructure-block.js.json | 16 +++- ...estructure-default-value-reference.js.json | 16 +++- .../destructure-default-value-secret.js.json | 14 ++++ test/output/destructure-default-value.js.json | 16 +++- .../output/destructure-dynamic-import.js.json | 10 ++- .../destructure-nested-object-literal.js.json | 10 ++- .../output/destructure-object-literal.js.json | 16 +++- .../destructured-arrow-with-default.js.json | 10 ++- ...structured-assignment-with-default.js.json | 3 +- .../destructured-object-with-default.js.json | 10 ++- test/output/dynamic-import.js.json | 10 ++- test/output/empty.js.json | 3 +- test/output/empty.md.json | 3 +- .../expression-trailing-comment.js.json | 10 ++- test/output/extra-semicolon.js.json | 10 ++- test/output/file-attachment-masked.js.json | 3 +- test/output/file-attachment-nested.js.json | 15 +++- test/output/file-attachment.js.json | 3 +- test/output/for-await-generator.js.json | 3 +- test/output/for-await-in-function.js.json | 10 ++- test/output/for-await.js.json | 3 +- test/output/import-empty.js.json | 3 +- test/output/import-mutable-as.js.json | 10 ++- test/output/import-mutable.js.json | 10 ++- test/output/import-semicolon.js.json | 16 +++- test/output/import-viewof-as.js.json | 10 ++- test/output/import-viewof.js.json | 10 ++- test/output/import-with-empty.js.json | 10 ++- test/output/import-with.js.json | 10 ++- test/output/import.js.json | 16 +++- test/output/legal-arguments.js.json | 3 +- test/output/logical-assignment.js.json | 3 +- test/output/markdown-interpolation.md.json | 3 +- test/output/markdown.md.json | 3 +- test/output/member-assignment.js.json | 3 +- test/output/multiple-input-references.js.json | 10 ++- test/output/mutable-as-property.js.json | 3 +- test/output/mutable-assign-default.js.json | 15 +++- test/output/mutable-assignment.js.json | 3 +- test/output/mutable-block-cell.js.json | 15 +++- test/output/mutable-default-value.js.json | 10 ++- test/output/mutable-destructure-array.js.json | 3 +- .../output/mutable-destructure-object.js.json | 3 +- test/output/mutable-in-markdown.md.json | 3 +- test/output/mutable-internal-comment.js.json | 3 +- test/output/mutable-reference.js.json | 3 +- test/output/named-async-function.js.json | 10 ++- test/output/named-block-cell.js.json | 10 ++- test/output/named-class-with-field.js.json | 10 ++- test/output/named-class-with-method.js.json | 10 ++- .../named-class-with-private-field.js.json | 10 ++- .../named-class-with-static-field.js.json | 10 ++- test/output/named-class.js.json | 10 ++- test/output/named-expression-cell.js.json | 10 ++- .../named-function-in-named-cell.js.json | 10 ++- test/output/named-function.js.json | 10 ++- test/output/named-generator-function.js.json | 10 ++- test/output/named-with-parens.js.json | 10 ++- test/output/nullish-coalescing.js.json | 10 ++- test/output/object-literal-async.js.json | 3 +- test/output/object-literal-yield.js.json | 3 +- test/output/object-literal.js.json | 3 +- test/output/optional-chaining.js.json | 10 ++- .../parenthesized-named-function.js.json | 10 ++- test/output/secret.js.json | 3 +- test/output/semicolon.js.json | 3 +- test/output/sequence-expression.js.json | 3 +- test/output/shadowed-view.js.json | 3 +- .../simple-await-tagged-template.js.json | 3 +- test/output/simple-await-template.js.json | 3 +- test/output/simple-await-template.md.json | 3 +- test/output/simple-identifier.js.json | 3 +- test/output/spread-element.js.json | 3 +- .../output/template-literal-semicolon.js.json | 3 +- test/output/this.js.json | 3 +- test/output/underline.tex.json | 3 +- test/output/viewof-block-cell.js.json | 15 +++- test/output/viewof-expression-cell.js.json | 15 +++- test/output/viewof-in-markdown.md.json | 3 +- test/output/viewof-internal-comment.js.json | 15 +++- test/output/viewof-member-expression.js.json | 3 +- test/output/viewof-property.js.json | 3 +- .../viewof-reference-internal-comment.js.json | 3 +- test/output/viewof-reference.js.json | 3 +- test/output/yield-await.js.json | 3 +- test/output/yield-block-cell.js.json | 3 +- test/output/yield-expression-cell.js.json | 3 +- test/output/yield-in-function.js.json | 3 +- .../output/yield-star-expression-cell.js.json | 3 +- test/parse-test.js | 2 +- 119 files changed, 700 insertions(+), 139 deletions(-) diff --git a/src/parse.js b/src/parse.js index e091a17..a22f84f 100644 --- a/src/parse.js +++ b/src/parse.js @@ -23,6 +23,7 @@ export function parseCell(input, {tag, raw, globals, ...options} = {}) { } parseReferences(cell, input, globals); parseFeatures(cell, input); + parseDeclarations(cell); return cell; } @@ -199,29 +200,12 @@ export class CellParser extends Parser { : super.toAssignable(node, isBinding, refDestructuringErrors); } checkCellDeclaration(node) { - switch (node.type) { - case "Identifier": - break; - case "ObjectPattern": - for (const p of node.properties) this.checkCellDeclaration(p); - break; - case "ArrayPattern": - for (const e of node.elements) e && this.checkCellDeclaration(e); - break; - case "Property": - this.checkCellDeclaration(node.value); - break; - case "RestElement": - this.checkCellDeclaration(node.argument); - break; - case "AssignmentPattern": - this.checkCellDeclaration(node.left); - break; - default: - // Don’t allow destructuring into viewof or mutable declarations. + // Don’t allow destructuring into viewof or mutable declarations. + declarePattern(node, id => { + if (id.type !== "Identifier") { this.unexpected(); - break; - } + } + }); } checkLocal(id) { const node = id.id || id; @@ -423,3 +407,56 @@ function parseFeatures(cell, input) { } return cell; } + +// Find declarations: things that this cell defines. +function parseDeclarations(cell) { + if (!cell.body) { + cell.declarations = []; + } else if (cell.body.type === "ImportDeclaration") { + cell.declarations = cell.body.specifiers.map(s => s.local); + } else if (!cell.id) { + cell.declarations = []; + } else { + switch (cell.id.type) { + case "Identifier": + case "ViewExpression": + case "MutableExpression": + cell.declarations = [cell.id]; + break; + case "ArrayPattern": + case "ObjectPattern": + cell.declarations = []; + declarePattern(cell.id, node => cell.declarations.push(node)); + break; + default: + throw new Error(`unexpected identifier: ${cell.id.type}`); + } + } +} + +function declarePattern(node, callback) { + switch (node.type) { + case "Identifier": + case "ViewExpression": + case "MutableExpression": + callback(node); + break; + case "ObjectPattern": + node.properties.forEach(node => declarePattern(node, callback)); + break; + case "ArrayPattern": + node.elements.forEach(node => node && declarePattern(node, callback)); + break; + case "Property": + declarePattern(node.value, callback); + break; + case "RestElement": + declarePattern(node.argument, callback); + break; + case "AssignmentPattern": + declarePattern(node.left, callback); + break; + default: + throw new Error(`unexpected declaration: ${node.type}`); + } +} diff --git a/test/output/anonymous-block-cell.js.json b/test/output/anonymous-block-cell.js.json index e225450..074bc40 100644 --- a/test/output/anonymous-block-cell.js.json +++ b/test/output/anonymous-block-cell.js.json @@ -27,5 +27,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/anonymous-expression-cell.js.json b/test/output/anonymous-expression-cell.js.json index 3b0de53..c35d704 100644 --- a/test/output/anonymous-expression-cell.js.json +++ b/test/output/anonymous-expression-cell.js.json @@ -15,5 +15,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/anonymous-function.js.json b/test/output/anonymous-function.js.json index b894aef..5b6d08d 100644 --- a/test/output/anonymous-function.js.json +++ b/test/output/anonymous-function.js.json @@ -37,5 +37,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/await-block-cell.js.json b/test/output/await-block-cell.js.json index 631d0cc..b7bca8d 100644 --- a/test/output/await-block-cell.js.json +++ b/test/output/await-block-cell.js.json @@ -38,5 +38,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/await-in-arrow-function-expression.js.json b/test/output/await-in-arrow-function-expression.js.json index 59ff424..90caf83 100644 --- a/test/output/await-in-arrow-function-expression.js.json +++ b/test/output/await-in-arrow-function-expression.js.json @@ -48,5 +48,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/await-in-arrow-function.js.json b/test/output/await-in-arrow-function.js.json index 00e0101..7d21bc3 100644 --- a/test/output/await-in-arrow-function.js.json +++ b/test/output/await-in-arrow-function.js.json @@ -74,5 +74,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/await-in-class.js.json b/test/output/await-in-class.js.json index 36c122a..71073b3 100644 --- a/test/output/await-in-class.js.json +++ b/test/output/await-in-class.js.json @@ -88,5 +88,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/await-in-function.js.json b/test/output/await-in-function.js.json index db5bf4a..58dc52e 100644 --- a/test/output/await-in-function.js.json +++ b/test/output/await-in-function.js.json @@ -60,5 +60,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/await-in-markdown.md.json b/test/output/await-in-markdown.md.json index 84b2643..8ae76e9 100644 --- a/test/output/await-in-markdown.md.json +++ b/test/output/await-in-markdown.md.json @@ -88,5 +88,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/await-yield.js.json b/test/output/await-yield.js.json index f033df3..2efc347 100644 --- a/test/output/await-yield.js.json +++ b/test/output/await-yield.js.json @@ -61,5 +61,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/backslash-after-dollar-markdown.md.json b/test/output/backslash-after-dollar-markdown.md.json index 8c0ae6e..8efd471 100644 --- a/test/output/backslash-after-dollar-markdown.md.json +++ b/test/output/backslash-after-dollar-markdown.md.json @@ -52,5 +52,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/backslash-before-dollar-markdown.md.json b/test/output/backslash-before-dollar-markdown.md.json index c331294..8c16e05 100644 --- a/test/output/backslash-before-dollar-markdown.md.json +++ b/test/output/backslash-before-dollar-markdown.md.json @@ -52,5 +52,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/backslash-markdown.md.json b/test/output/backslash-markdown.md.json index 70e4585..a20f390 100644 --- a/test/output/backslash-markdown.md.json +++ b/test/output/backslash-markdown.md.json @@ -52,5 +52,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/bare-dynamic-import.js.json b/test/output/bare-dynamic-import.js.json index 6200ed7..16d469c 100644 --- a/test/output/bare-dynamic-import.js.json +++ b/test/output/bare-dynamic-import.js.json @@ -20,5 +20,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/basic.db.sql.json b/test/output/basic.db.sql.json index c27a53d..788c15e 100644 --- a/test/output/basic.db.sql.json +++ b/test/output/basic.db.sql.json @@ -119,5 +119,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/basic.html.json b/test/output/basic.html.json index 4329cff..9d49045 100644 --- a/test/output/basic.html.json +++ b/test/output/basic.html.json @@ -89,5 +89,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/basic.sql.json b/test/output/basic.sql.json index 98f49c1..38b912f 100644 --- a/test/output/basic.sql.json +++ b/test/output/basic.sql.json @@ -88,5 +88,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/basic.tex.json b/test/output/basic.tex.json index 9192d88..d548b10 100644 --- a/test/output/basic.tex.json +++ b/test/output/basic.tex.json @@ -110,5 +110,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/bigint-zero.js.json b/test/output/bigint-zero.js.json index 4174f58..9bbed6b 100644 --- a/test/output/bigint-zero.js.json +++ b/test/output/bigint-zero.js.json @@ -16,5 +16,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/bigint.js.json b/test/output/bigint.js.json index f520b63..0e74966 100644 --- a/test/output/bigint.js.json +++ b/test/output/bigint.js.json @@ -35,5 +35,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/binary-expression.js.json b/test/output/binary-expression.js.json index 9af3f07..4b8ade3 100644 --- a/test/output/binary-expression.js.json +++ b/test/output/binary-expression.js.json @@ -34,5 +34,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/block-leading-comment.js.json b/test/output/block-leading-comment.js.json index c037841..89f7e04 100644 --- a/test/output/block-leading-comment.js.json +++ b/test/output/block-leading-comment.js.json @@ -32,5 +32,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 21, + "end": 24, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/block-trailing-comment.js.json b/test/output/block-trailing-comment.js.json index d570361..6a28303 100644 --- a/test/output/block-trailing-comment.js.json +++ b/test/output/block-trailing-comment.js.json @@ -32,5 +32,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/catch-clause.js.json b/test/output/catch-clause.js.json index e17c235..6b87b0b 100644 --- a/test/output/catch-clause.js.json +++ b/test/output/catch-clause.js.json @@ -125,5 +125,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/comment.js.json b/test/output/comment.js.json index c8396c8..507e8d9 100644 --- a/test/output/comment.js.json +++ b/test/output/comment.js.json @@ -9,5 +9,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/computed-property-name.js.json b/test/output/computed-property-name.js.json index 2de1725..d601d17 100644 --- a/test/output/computed-property-name.js.json +++ b/test/output/computed-property-name.js.json @@ -60,5 +60,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/database-client.js.json b/test/output/database-client.js.json index 7fb4c8f..6e2c653 100644 --- a/test/output/database-client.js.json +++ b/test/output/database-client.js.json @@ -72,5 +72,6 @@ ] ] ], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/destructure-array-literal.js.json b/test/output/destructure-array-literal.js.json index 124c648..5566337 100644 --- a/test/output/destructure-array-literal.js.json +++ b/test/output/destructure-array-literal.js.json @@ -59,5 +59,19 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 2, + "end": 5, + "name": "foo" + }, + { + "type": "Identifier", + "start": 10, + "end": 13, + "name": "bar" + } + ] } \ No newline at end of file diff --git a/test/output/destructure-block.js.json b/test/output/destructure-block.js.json index 7041b19..b3d538f 100644 --- a/test/output/destructure-block.js.json +++ b/test/output/destructure-block.js.json @@ -119,5 +119,19 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 2, + "end": 5, + "name": "foo" + }, + { + "type": "Identifier", + "start": 7, + "end": 10, + "name": "bar" + } + ] } \ No newline at end of file diff --git a/test/output/destructure-default-value-reference.js.json b/test/output/destructure-default-value-reference.js.json index 0bb6751..a96010f 100644 --- a/test/output/destructure-default-value-reference.js.json +++ b/test/output/destructure-default-value-reference.js.json @@ -70,5 +70,19 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + } + ] } \ No newline at end of file diff --git a/test/output/destructure-default-value-secret.js.json b/test/output/destructure-default-value-secret.js.json index 781e49d..40f7d74 100644 --- a/test/output/destructure-default-value-secret.js.json +++ b/test/output/destructure-default-value-secret.js.json @@ -83,5 +83,19 @@ } ] ] + ], + "declarations": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + } ] } \ No newline at end of file diff --git a/test/output/destructure-default-value.js.json b/test/output/destructure-default-value.js.json index 8b3d039..cef8ad1 100644 --- a/test/output/destructure-default-value.js.json +++ b/test/output/destructure-default-value.js.json @@ -52,5 +52,19 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + } + ] } \ No newline at end of file diff --git a/test/output/destructure-dynamic-import.js.json b/test/output/destructure-dynamic-import.js.json index f466bf3..23e9f29 100644 --- a/test/output/destructure-dynamic-import.js.json +++ b/test/output/destructure-dynamic-import.js.json @@ -47,5 +47,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 11, + "end": 19, + "name": "confetti" + } + ] } \ No newline at end of file diff --git a/test/output/destructure-nested-object-literal.js.json b/test/output/destructure-nested-object-literal.js.json index e6854b0..2d67ec5 100644 --- a/test/output/destructure-nested-object-literal.js.json +++ b/test/output/destructure-nested-object-literal.js.json @@ -85,5 +85,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 19, + "end": 22, + "name": "qux" + } + ] } \ No newline at end of file diff --git a/test/output/destructure-object-literal.js.json b/test/output/destructure-object-literal.js.json index 7b8ca5b..f77be0b 100644 --- a/test/output/destructure-object-literal.js.json +++ b/test/output/destructure-object-literal.js.json @@ -107,5 +107,19 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 2, + "end": 5, + "name": "foo" + }, + { + "type": "Identifier", + "start": 7, + "end": 10, + "name": "bar" + } + ] } \ No newline at end of file diff --git a/test/output/destructured-arrow-with-default.js.json b/test/output/destructured-arrow-with-default.js.json index 5cdf2b5..6d17c2a 100644 --- a/test/output/destructured-arrow-with-default.js.json +++ b/test/output/destructured-arrow-with-default.js.json @@ -70,5 +70,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "fun" + } + ] } \ No newline at end of file diff --git a/test/output/destructured-assignment-with-default.js.json b/test/output/destructured-assignment-with-default.js.json index 28b8420..5daae53 100644 --- a/test/output/destructured-assignment-with-default.js.json +++ b/test/output/destructured-assignment-with-default.js.json @@ -98,5 +98,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/destructured-object-with-default.js.json b/test/output/destructured-object-with-default.js.json index e9c62e4..7b69a77 100644 --- a/test/output/destructured-object-with-default.js.json +++ b/test/output/destructured-object-with-default.js.json @@ -75,5 +75,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "fun" + } + ] } \ No newline at end of file diff --git a/test/output/dynamic-import.js.json b/test/output/dynamic-import.js.json index e2c6386..083000e 100644 --- a/test/output/dynamic-import.js.json +++ b/test/output/dynamic-import.js.json @@ -25,5 +25,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/empty.js.json b/test/output/empty.js.json index 7032315..96a6856 100644 --- a/test/output/empty.js.json +++ b/test/output/empty.js.json @@ -9,5 +9,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/empty.md.json b/test/output/empty.md.json index 7032315..96a6856 100644 --- a/test/output/empty.md.json +++ b/test/output/empty.md.json @@ -9,5 +9,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/expression-trailing-comment.js.json b/test/output/expression-trailing-comment.js.json index e800b42..7028b57 100644 --- a/test/output/expression-trailing-comment.js.json +++ b/test/output/expression-trailing-comment.js.json @@ -20,5 +20,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/extra-semicolon.js.json b/test/output/extra-semicolon.js.json index ce396da..ad45cf1 100644 --- a/test/output/extra-semicolon.js.json +++ b/test/output/extra-semicolon.js.json @@ -20,5 +20,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/file-attachment-masked.js.json b/test/output/file-attachment-masked.js.json index 0352822..bcb48fb 100644 --- a/test/output/file-attachment-masked.js.json +++ b/test/output/file-attachment-masked.js.json @@ -108,5 +108,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/file-attachment-nested.js.json b/test/output/file-attachment-nested.js.json index 167bcee..20d33b1 100644 --- a/test/output/file-attachment-nested.js.json +++ b/test/output/file-attachment-nested.js.json @@ -383,5 +383,18 @@ ] ], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "ViewExpression", + "start": 0, + "end": 13, + "id": { + "type": "Identifier", + "start": 7, + "end": 13, + "name": "slider" + } + } + ] } \ No newline at end of file diff --git a/test/output/file-attachment.js.json b/test/output/file-attachment.js.json index 81e2bf4..ac588df 100644 --- a/test/output/file-attachment.js.json +++ b/test/output/file-attachment.js.json @@ -243,5 +243,6 @@ ] ], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/for-await-generator.js.json b/test/output/for-await-generator.js.json index 0c123a9..e8016bf 100644 --- a/test/output/for-await-generator.js.json +++ b/test/output/for-await-generator.js.json @@ -85,5 +85,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/for-await-in-function.js.json b/test/output/for-await-in-function.js.json index ed68077..acfdca3 100644 --- a/test/output/for-await-in-function.js.json +++ b/test/output/for-await-in-function.js.json @@ -162,5 +162,13 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 15, + "end": 18, + "name": "bar" + } + ] } \ No newline at end of file diff --git a/test/output/for-await.js.json b/test/output/for-await.js.json index ea9e46a..d88cf69 100644 --- a/test/output/for-await.js.json +++ b/test/output/for-await.js.json @@ -142,5 +142,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/import-empty.js.json b/test/output/import-empty.js.json index 85bd1ae..5e690db 100644 --- a/test/output/import-empty.js.json +++ b/test/output/import-empty.js.json @@ -21,5 +21,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/import-mutable-as.js.json b/test/output/import-mutable-as.js.json index 56b6c29..757a646 100644 --- a/test/output/import-mutable-as.js.json +++ b/test/output/import-mutable-as.js.json @@ -41,5 +41,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 23, + "end": 26, + "name": "bar" + } + ] } \ No newline at end of file diff --git a/test/output/import-mutable.js.json b/test/output/import-mutable.js.json index 4830a73..9746df5 100644 --- a/test/output/import-mutable.js.json +++ b/test/output/import-mutable.js.json @@ -41,5 +41,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 16, + "end": 19, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/import-semicolon.js.json b/test/output/import-semicolon.js.json index 77a5995..a1ec453 100644 --- a/test/output/import-semicolon.js.json +++ b/test/output/import-semicolon.js.json @@ -60,5 +60,19 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 8, + "end": 11, + "name": "foo" + }, + { + "type": "Identifier", + "start": 20, + "end": 23, + "name": "baz" + } + ] } \ No newline at end of file diff --git a/test/output/import-viewof-as.js.json b/test/output/import-viewof-as.js.json index 4f9b6c4..da8a057 100644 --- a/test/output/import-viewof-as.js.json +++ b/test/output/import-viewof-as.js.json @@ -41,5 +41,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 22, + "end": 25, + "name": "bar" + } + ] } \ No newline at end of file diff --git a/test/output/import-viewof.js.json b/test/output/import-viewof.js.json index bbd48bd..ebbb9c6 100644 --- a/test/output/import-viewof.js.json +++ b/test/output/import-viewof.js.json @@ -41,5 +41,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 15, + "end": 18, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/import-with-empty.js.json b/test/output/import-with-empty.js.json index 3f1de37..ee47bed 100644 --- a/test/output/import-with-empty.js.json +++ b/test/output/import-with-empty.js.json @@ -42,5 +42,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 8, + "end": 11, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/import-with.js.json b/test/output/import-with.js.json index daac0b4..2b7a758 100644 --- a/test/output/import-with.js.json +++ b/test/output/import-with.js.json @@ -69,5 +69,13 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 8, + "end": 11, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/import.js.json b/test/output/import.js.json index adb63a0..a759d81 100644 --- a/test/output/import.js.json +++ b/test/output/import.js.json @@ -60,5 +60,19 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 8, + "end": 11, + "name": "foo" + }, + { + "type": "Identifier", + "start": 20, + "end": 23, + "name": "baz" + } + ] } \ No newline at end of file diff --git a/test/output/legal-arguments.js.json b/test/output/legal-arguments.js.json index e75e846..dad79aa 100644 --- a/test/output/legal-arguments.js.json +++ b/test/output/legal-arguments.js.json @@ -49,5 +49,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/logical-assignment.js.json b/test/output/logical-assignment.js.json index 486cc17..15645a9 100644 --- a/test/output/logical-assignment.js.json +++ b/test/output/logical-assignment.js.json @@ -101,5 +101,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/markdown-interpolation.md.json b/test/output/markdown-interpolation.md.json index 085b706..06f2616 100644 --- a/test/output/markdown-interpolation.md.json +++ b/test/output/markdown-interpolation.md.json @@ -147,5 +147,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/markdown.md.json b/test/output/markdown.md.json index f60d1bc..44678b3 100644 --- a/test/output/markdown.md.json +++ b/test/output/markdown.md.json @@ -76,5 +76,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/member-assignment.js.json b/test/output/member-assignment.js.json index edd889d..5ccbfa0 100644 --- a/test/output/member-assignment.js.json +++ b/test/output/member-assignment.js.json @@ -47,5 +47,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/multiple-input-references.js.json b/test/output/multiple-input-references.js.json index e65d575..c4ba695 100644 --- a/test/output/multiple-input-references.js.json +++ b/test/output/multiple-input-references.js.json @@ -243,5 +243,13 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 4, + "name": "cell" + } + ] } \ No newline at end of file diff --git a/test/output/mutable-as-property.js.json b/test/output/mutable-as-property.js.json index c7d32d2..75732b4 100644 --- a/test/output/mutable-as-property.js.json +++ b/test/output/mutable-as-property.js.json @@ -63,5 +63,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/mutable-assign-default.js.json b/test/output/mutable-assign-default.js.json index c629e1a..7276468 100644 --- a/test/output/mutable-assign-default.js.json +++ b/test/output/mutable-assign-default.js.json @@ -69,5 +69,18 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "MutableExpression", + "start": 0, + "end": 13, + "id": { + "type": "Identifier", + "start": 8, + "end": 13, + "name": "state" + } + } + ] } \ No newline at end of file diff --git a/test/output/mutable-assignment.js.json b/test/output/mutable-assignment.js.json index e2e7eb8..3f9f0c0 100644 --- a/test/output/mutable-assignment.js.json +++ b/test/output/mutable-assignment.js.json @@ -56,5 +56,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/mutable-block-cell.js.json b/test/output/mutable-block-cell.js.json index cb72eda..0e1b891 100644 --- a/test/output/mutable-block-cell.js.json +++ b/test/output/mutable-block-cell.js.json @@ -81,5 +81,18 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "MutableExpression", + "start": 0, + "end": 11, + "id": { + "type": "Identifier", + "start": 8, + "end": 11, + "name": "foo" + } + } + ] } \ No newline at end of file diff --git a/test/output/mutable-default-value.js.json b/test/output/mutable-default-value.js.json index 0793f4a..6ef0431 100644 --- a/test/output/mutable-default-value.js.json +++ b/test/output/mutable-default-value.js.json @@ -81,5 +81,13 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 9, + "end": 11, + "name": "fn" + } + ] } \ No newline at end of file diff --git a/test/output/mutable-destructure-array.js.json b/test/output/mutable-destructure-array.js.json index 9b3a551..9cf91e6 100644 --- a/test/output/mutable-destructure-array.js.json +++ b/test/output/mutable-destructure-array.js.json @@ -58,5 +58,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/mutable-destructure-object.js.json b/test/output/mutable-destructure-object.js.json index 9888e62..dc3168f 100644 --- a/test/output/mutable-destructure-object.js.json +++ b/test/output/mutable-destructure-object.js.json @@ -93,5 +93,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/mutable-in-markdown.md.json b/test/output/mutable-in-markdown.md.json index b54d8d5..d7a63d4 100644 --- a/test/output/mutable-in-markdown.md.json +++ b/test/output/mutable-in-markdown.md.json @@ -171,5 +171,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/mutable-internal-comment.js.json b/test/output/mutable-internal-comment.js.json index 904e5a3..b5dd095 100644 --- a/test/output/mutable-internal-comment.js.json +++ b/test/output/mutable-internal-comment.js.json @@ -31,5 +31,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/mutable-reference.js.json b/test/output/mutable-reference.js.json index e91478d..202aff7 100644 --- a/test/output/mutable-reference.js.json +++ b/test/output/mutable-reference.js.json @@ -44,5 +44,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/named-async-function.js.json b/test/output/named-async-function.js.json index c523107..8657b15 100644 --- a/test/output/named-async-function.js.json +++ b/test/output/named-async-function.js.json @@ -58,5 +58,13 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 15, + "end": 18, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-block-cell.js.json b/test/output/named-block-cell.js.json index 307e396..44fcd6a 100644 --- a/test/output/named-block-cell.js.json +++ b/test/output/named-block-cell.js.json @@ -32,5 +32,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-class-with-field.js.json b/test/output/named-class-with-field.js.json index aac6b0f..679dbee 100644 --- a/test/output/named-class-with-field.js.json +++ b/test/output/named-class-with-field.js.json @@ -52,5 +52,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 6, + "end": 9, + "name": "Foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-class-with-method.js.json b/test/output/named-class-with-method.js.json index 6d02cdc..3a7420c 100644 --- a/test/output/named-class-with-method.js.json +++ b/test/output/named-class-with-method.js.json @@ -75,5 +75,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 6, + "end": 9, + "name": "Foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-class-with-private-field.js.json b/test/output/named-class-with-private-field.js.json index 4162546..d4e77c4 100644 --- a/test/output/named-class-with-private-field.js.json +++ b/test/output/named-class-with-private-field.js.json @@ -82,5 +82,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 6, + "end": 9, + "name": "Foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-class-with-static-field.js.json b/test/output/named-class-with-static-field.js.json index 0520808..8cf4420 100644 --- a/test/output/named-class-with-static-field.js.json +++ b/test/output/named-class-with-static-field.js.json @@ -52,5 +52,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 6, + "end": 9, + "name": "Foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-class.js.json b/test/output/named-class.js.json index 2b95f92..5a45678 100644 --- a/test/output/named-class.js.json +++ b/test/output/named-class.js.json @@ -31,5 +31,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 6, + "end": 9, + "name": "Foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-expression-cell.js.json b/test/output/named-expression-cell.js.json index 209ef2a..9c0a0f8 100644 --- a/test/output/named-expression-cell.js.json +++ b/test/output/named-expression-cell.js.json @@ -20,5 +20,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-function-in-named-cell.js.json b/test/output/named-function-in-named-cell.js.json index 0ca1237..dd6c365 100644 --- a/test/output/named-function-in-named-cell.js.json +++ b/test/output/named-function-in-named-cell.js.json @@ -47,5 +47,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-function.js.json b/test/output/named-function.js.json index 5ee6881..c1f620d 100644 --- a/test/output/named-function.js.json +++ b/test/output/named-function.js.json @@ -47,5 +47,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 9, + "end": 12, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-generator-function.js.json b/test/output/named-generator-function.js.json index fa6afad..5890496 100644 --- a/test/output/named-generator-function.js.json +++ b/test/output/named-generator-function.js.json @@ -53,5 +53,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 10, + "end": 13, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/named-with-parens.js.json b/test/output/named-with-parens.js.json index 803c05f..3f7b2ff 100644 --- a/test/output/named-with-parens.js.json +++ b/test/output/named-with-parens.js.json @@ -20,5 +20,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 1, + "end": 4, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/nullish-coalescing.js.json b/test/output/nullish-coalescing.js.json index feadd10..34ffab4 100644 --- a/test/output/nullish-coalescing.js.json +++ b/test/output/nullish-coalescing.js.json @@ -33,5 +33,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 3, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/object-literal-async.js.json b/test/output/object-literal-async.js.json index 37d52c1..a0fa8bf 100644 --- a/test/output/object-literal-async.js.json +++ b/test/output/object-literal-async.js.json @@ -42,5 +42,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/object-literal-yield.js.json b/test/output/object-literal-yield.js.json index 0f98d52..1fb5ac0 100644 --- a/test/output/object-literal-yield.js.json +++ b/test/output/object-literal-yield.js.json @@ -43,5 +43,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/object-literal.js.json b/test/output/object-literal.js.json index b9eb52c..340e55e 100644 --- a/test/output/object-literal.js.json +++ b/test/output/object-literal.js.json @@ -37,5 +37,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/optional-chaining.js.json b/test/output/optional-chaining.js.json index 61a0952..70ecf15 100644 --- a/test/output/optional-chaining.js.json +++ b/test/output/optional-chaining.js.json @@ -57,5 +57,13 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 0, + "end": 7, + "name": "dogName" + } + ] } \ No newline at end of file diff --git a/test/output/parenthesized-named-function.js.json b/test/output/parenthesized-named-function.js.json index 9683fa6..ce8b206 100644 --- a/test/output/parenthesized-named-function.js.json +++ b/test/output/parenthesized-named-function.js.json @@ -47,5 +47,13 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 10, + "end": 13, + "name": "foo" + } + ] } \ No newline at end of file diff --git a/test/output/secret.js.json b/test/output/secret.js.json index 665c995..758a66f 100644 --- a/test/output/secret.js.json +++ b/test/output/secret.js.json @@ -72,5 +72,6 @@ } ] ] - ] + ], + "declarations": [] } \ No newline at end of file diff --git a/test/output/semicolon.js.json b/test/output/semicolon.js.json index b3d875e..e8104c3 100644 --- a/test/output/semicolon.js.json +++ b/test/output/semicolon.js.json @@ -9,5 +9,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/sequence-expression.js.json b/test/output/sequence-expression.js.json index b790637..5279785 100644 --- a/test/output/sequence-expression.js.json +++ b/test/output/sequence-expression.js.json @@ -36,5 +36,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/shadowed-view.js.json b/test/output/shadowed-view.js.json index 4fbf2a3..92818d5 100644 --- a/test/output/shadowed-view.js.json +++ b/test/output/shadowed-view.js.json @@ -93,5 +93,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/simple-await-tagged-template.js.json b/test/output/simple-await-tagged-template.js.json index 6ff046b..a83b6d0 100644 --- a/test/output/simple-await-tagged-template.js.json +++ b/test/output/simple-await-tagged-template.js.json @@ -72,5 +72,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/simple-await-template.js.json b/test/output/simple-await-template.js.json index d26fdb4..6209d4e 100644 --- a/test/output/simple-await-template.js.json +++ b/test/output/simple-await-template.js.json @@ -55,5 +55,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/simple-await-template.md.json b/test/output/simple-await-template.md.json index 7902d25..8e43bf0 100644 --- a/test/output/simple-await-template.md.json +++ b/test/output/simple-await-template.md.json @@ -80,5 +80,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/simple-identifier.js.json b/test/output/simple-identifier.js.json index 37c9e5f..173457e 100644 --- a/test/output/simple-identifier.js.json +++ b/test/output/simple-identifier.js.json @@ -21,5 +21,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/spread-element.js.json b/test/output/spread-element.js.json index 7ae346d..184ff6b 100644 --- a/test/output/spread-element.js.json +++ b/test/output/spread-element.js.json @@ -64,5 +64,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/template-literal-semicolon.js.json b/test/output/template-literal-semicolon.js.json index 032c845..8fbe09f 100644 --- a/test/output/template-literal-semicolon.js.json +++ b/test/output/template-literal-semicolon.js.json @@ -44,5 +44,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/this.js.json b/test/output/this.js.json index 55036ac..a15c72f 100644 --- a/test/output/this.js.json +++ b/test/output/this.js.json @@ -13,5 +13,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/underline.tex.json b/test/output/underline.tex.json index 35b9071..d61431a 100644 --- a/test/output/underline.tex.json +++ b/test/output/underline.tex.json @@ -65,5 +65,6 @@ "references": [], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/viewof-block-cell.js.json b/test/output/viewof-block-cell.js.json index d505043..027a4e2 100644 --- a/test/output/viewof-block-cell.js.json +++ b/test/output/viewof-block-cell.js.json @@ -63,5 +63,18 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "ViewExpression", + "start": 0, + "end": 10, + "id": { + "type": "Identifier", + "start": 7, + "end": 10, + "name": "foo" + } + } + ] } \ No newline at end of file diff --git a/test/output/viewof-expression-cell.js.json b/test/output/viewof-expression-cell.js.json index 4b5c5b7..e1419e1 100644 --- a/test/output/viewof-expression-cell.js.json +++ b/test/output/viewof-expression-cell.js.json @@ -51,5 +51,18 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "ViewExpression", + "start": 0, + "end": 10, + "id": { + "type": "Identifier", + "start": 7, + "end": 10, + "name": "foo" + } + } + ] } \ No newline at end of file diff --git a/test/output/viewof-in-markdown.md.json b/test/output/viewof-in-markdown.md.json index b766387..1108f6a 100644 --- a/test/output/viewof-in-markdown.md.json +++ b/test/output/viewof-in-markdown.md.json @@ -105,5 +105,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/viewof-internal-comment.js.json b/test/output/viewof-internal-comment.js.json index 90f5057..c8bbec7 100644 --- a/test/output/viewof-internal-comment.js.json +++ b/test/output/viewof-internal-comment.js.json @@ -51,5 +51,18 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [ + { + "type": "ViewExpression", + "start": 0, + "end": 24, + "id": { + "type": "Identifier", + "start": 21, + "end": 24, + "name": "bar" + } + } + ] } \ No newline at end of file diff --git a/test/output/viewof-member-expression.js.json b/test/output/viewof-member-expression.js.json index 2ac484e..36f3753 100644 --- a/test/output/viewof-member-expression.js.json +++ b/test/output/viewof-member-expression.js.json @@ -44,5 +44,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/viewof-property.js.json b/test/output/viewof-property.js.json index 8977be9..1d6e693 100644 --- a/test/output/viewof-property.js.json +++ b/test/output/viewof-property.js.json @@ -63,5 +63,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/viewof-reference-internal-comment.js.json b/test/output/viewof-reference-internal-comment.js.json index 295fa9f..37bbbbb 100644 --- a/test/output/viewof-reference-internal-comment.js.json +++ b/test/output/viewof-reference-internal-comment.js.json @@ -31,5 +31,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/viewof-reference.js.json b/test/output/viewof-reference.js.json index 5420d38..bbe0c8f 100644 --- a/test/output/viewof-reference.js.json +++ b/test/output/viewof-reference.js.json @@ -44,5 +44,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/yield-await.js.json b/test/output/yield-await.js.json index b26bd67..5ea427f 100644 --- a/test/output/yield-await.js.json +++ b/test/output/yield-await.js.json @@ -61,5 +61,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/yield-block-cell.js.json b/test/output/yield-block-cell.js.json index 94bcada..1ca135f 100644 --- a/test/output/yield-block-cell.js.json +++ b/test/output/yield-block-cell.js.json @@ -39,5 +39,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/yield-expression-cell.js.json b/test/output/yield-expression-cell.js.json index c92cdc4..d976c0d 100644 --- a/test/output/yield-expression-cell.js.json +++ b/test/output/yield-expression-cell.js.json @@ -27,5 +27,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/yield-in-function.js.json b/test/output/yield-in-function.js.json index fd9ebe0..7bf9e55 100644 --- a/test/output/yield-in-function.js.json +++ b/test/output/yield-in-function.js.json @@ -61,5 +61,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/output/yield-star-expression-cell.js.json b/test/output/yield-star-expression-cell.js.json index 956d520..f782d4b 100644 --- a/test/output/yield-star-expression-cell.js.json +++ b/test/output/yield-star-expression-cell.js.json @@ -27,5 +27,6 @@ ], "fileAttachments": [], "databaseClients": [], - "secrets": [] + "secrets": [], + "declarations": [] } \ No newline at end of file diff --git a/test/parse-test.js b/test/parse-test.js index fd6a644..251c13a 100644 --- a/test/parse-test.js +++ b/test/parse-test.js @@ -75,6 +75,6 @@ import {parseCell} from "@observablehq/parser"; // Convert to a serializable representation. function stringify(key, value) { return typeof value === "bigint" ? value.toString() - : value instanceof Map ? [...value] + : value instanceof Map || value instanceof Set ? [...value] : value; } From c6b633f75f475d4ec70ded43c8559cb408f01a49 Mon Sep 17 00:00:00 2001 From: Mike Bostock Date: Tue, 28 Dec 2021 10:40:25 -0800 Subject: [PATCH 10/10] parseParenAndDistinguishCell --- src/parse.js | 128 ++++++++++++++---- .../input/destructure-object-default-value.js | 1 + test/output/arrow-function-expression.js.json | 6 +- test/output/destructure-multiple.js.json | 6 +- test/output/destructure-mutable.js.json | 6 +- .../destructure-object-default-value.js.json | 115 ++++++++++++++++ .../output/destructure-trailing-comma.js.json | 6 +- 7 files changed, 233 insertions(+), 35 deletions(-) create mode 100644 test/input/destructure-object-default-value.js create mode 100644 test/output/destructure-object-default-value.js.json diff --git a/src/parse.js b/src/parse.js index a22f84f..3a0c55f 100644 --- a/src/parse.js +++ b/src/parse.js @@ -1,4 +1,4 @@ -import {getLineInfo, TokContext, Token, tokTypes as tt, Parser} from "acorn"; +import {getLineInfo, TokContext, tokTypes as tt, Parser} from "acorn"; import defaultGlobals from "./globals.js"; import findReferences from "./references.js"; import findFeatures from "./features.js"; @@ -138,16 +138,7 @@ export class CellParser extends Parser { // A destructuring cell, or parenthesized expression? (A destructuring // cell is a parenthesized expression followed by the equals operator.) if (token.type === tt.parenL) { - id = this.parseParenAndDistinguishExpression(true); - if (this.eat(tt.eq)) { - this.checkYieldAwaitInDefaultParams(); - id = this.toAssignable(id, true); - this.checkCellDeclaration(id); - token = new Token(this); - } else { - body = id; - id = null; - } + ({id, body} = this.parseParenAndDistinguishCell()); } // A simple named cell? @@ -191,6 +182,99 @@ export class CellParser extends Parser { return this.finishCell(node, body, id); } + // Adapted from parseParenAndDistinguishExpression + parseParenAndDistinguishCell() { + let startPos = this.start, + startLoc = this.startLoc, + val; + + this.next(); + + let innerStartPos = this.start, + innerStartLoc = this.startLoc, + exprList = [], + first = true, + lastIsComma = false, + refDestructuringErrors = new DestructuringErrors, + oldYieldPos = this.yieldPos, + oldAwaitPos = this.awaitPos, + spreadStart; + + this.yieldPos = 0; + this.awaitPos = 0; + + // Do not save awaitIdentPos to allow checking awaits nested in parameters + while (this.type !== tt.parenR) { + first ? first = false : this.expect(tt.comma); + if (this.afterTrailingComma(tt.parenR, true)) { + lastIsComma = true; + break; + } else if (this.type === tt.ellipsis) { + spreadStart = this.start; + exprList.push(this.parseParenItem(this.parseRestBinding())); + if (this.type === tt.comma) this.raise(this.start, "Comma is not permitted after the rest element"); + break; + } else { + exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); + } + } + + let innerEndPos = this.lastTokEnd, innerEndLoc = this.lastTokEndLoc; + this.expect(tt.parenR); + + if (!this.canInsertSemicolon()) { + if (this.eat(tt.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + return { + id: null, + body: this.parseParenArrowList(startPos, startLoc, exprList) + }; + } + if (this.eat(tt.eq)) { + if (exprList.length !== 1 || lastIsComma) this.unexpected(this.lastTokStart); + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + + val = this.parseParenArrowList(startPos, startLoc, exprList); + + // Don’t allow destructuring into viewof or mutable declarations. + declarePattern(val.params[0], id => { + if (id.type !== "Identifier") { + this.unexpected(id.start); + } + }); + + return { + id: val.params[0], + body: val.body + }; + } + } + + if (!exprList.length || lastIsComma) this.unexpected(this.lastTokStart); + if (spreadStart) this.unexpected(spreadStart); + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + + if (exprList.length > 1) { + val = this.startNodeAt(innerStartPos, innerStartLoc); + val.expressions = exprList; + this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); + } else { + val = exprList[0]; + } + + return { + id: null, + body: val + }; + } parseTopLevel(node) { return this.parseCell(node, true); } @@ -199,14 +283,6 @@ export class CellParser extends Parser { ? node : super.toAssignable(node, isBinding, refDestructuringErrors); } - checkCellDeclaration(node) { - // Don’t allow destructuring into viewof or mutable declarations. - declarePattern(node, id => { - if (id.type !== "Identifier") { - this.unexpected(); - } - }); - } checkLocal(id) { const node = id.id || id; if (defaultGlobals.has(node.name) || node.name === "arguments") { @@ -227,10 +303,8 @@ export class CellParser extends Parser { ); } unexpected(pos) { - this.raise( - pos != null ? pos : this.start, - this.type === tt.eof ? "Unexpected end of input" : "Unexpected token" - ); + if (pos == null) pos = this.start; + this.raise(pos, pos === this.input.length ? "Unexpected end of input" : "Unexpected token"); } parseMaybeKeywordExpression(keyword, type) { if (this.isContextual(keyword)) { @@ -253,6 +327,14 @@ const o_tmpl = new TokContext( parser => readTemplateToken.call(parser) // override ); +function DestructuringErrors() { + this.shorthandAssign = + this.trailingComma = + this.parenthesizedAssign = + this.parenthesizedBind = + this.doubleProto = -1; +} + export class TemplateCellParser extends CellParser { constructor(...args) { super(...args); diff --git a/test/input/destructure-object-default-value.js b/test/input/destructure-object-default-value.js new file mode 100644 index 0000000..dc1a267 --- /dev/null +++ b/test/input/destructure-object-default-value.js @@ -0,0 +1 @@ +({x, y = 2}) = ({x: 1}) diff --git a/test/output/arrow-function-expression.js.json b/test/output/arrow-function-expression.js.json index d7f58a0..a118c4a 100644 --- a/test/output/arrow-function-expression.js.json +++ b/test/output/arrow-function-expression.js.json @@ -1,11 +1,11 @@ { "error": { "type": "SyntaxError", - "message": "Assigning to rvalue (1:0)", - "pos": 0, + "message": "Unexpected token (1:25)", + "pos": 25, "loc": { "line": 1, - "column": 0 + "column": 25 } } } \ No newline at end of file diff --git a/test/output/destructure-multiple.js.json b/test/output/destructure-multiple.js.json index b41dee9..0b75260 100644 --- a/test/output/destructure-multiple.js.json +++ b/test/output/destructure-multiple.js.json @@ -1,11 +1,11 @@ { "error": { "type": "SyntaxError", - "message": "Assigning to rvalue (1:1)", - "pos": 1, + "message": "Unexpected token (1:9)", + "pos": 9, "loc": { "line": 1, - "column": 1 + "column": 9 } } } \ No newline at end of file diff --git a/test/output/destructure-mutable.js.json b/test/output/destructure-mutable.js.json index 5a4ba8f..e516d62 100644 --- a/test/output/destructure-mutable.js.json +++ b/test/output/destructure-mutable.js.json @@ -1,11 +1,11 @@ { "error": { "type": "SyntaxError", - "message": "Unexpected token (1:18)", - "pos": 18, + "message": "Unexpected token (1:2)", + "pos": 2, "loc": { "line": 1, - "column": 18 + "column": 2 } } } \ No newline at end of file diff --git a/test/output/destructure-object-default-value.js.json b/test/output/destructure-object-default-value.js.json new file mode 100644 index 0000000..bb26352 --- /dev/null +++ b/test/output/destructure-object-default-value.js.json @@ -0,0 +1,115 @@ +{ + "type": "Cell", + "start": 0, + "end": 24, + "id": { + "type": "ObjectPattern", + "start": 1, + "end": 11, + "properties": [ + { + "type": "Property", + "start": 2, + "end": 3, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + "kind": "init", + "value": { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + } + }, + { + "type": "Property", + "start": 5, + "end": 10, + "method": false, + "shorthand": true, + "computed": false, + "key": { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + }, + "kind": "init", + "value": { + "type": "AssignmentPattern", + "start": 5, + "end": 10, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + }, + "right": { + "type": "Literal", + "start": 9, + "end": 10, + "value": 2, + "raw": "2" + } + } + } + ] + }, + "body": { + "type": "ObjectExpression", + "start": 16, + "end": 22, + "properties": [ + { + "type": "Property", + "start": 17, + "end": 21, + "method": false, + "shorthand": false, + "computed": false, + "key": { + "type": "Identifier", + "start": 17, + "end": 18, + "name": "x" + }, + "value": { + "type": "Literal", + "start": 20, + "end": 21, + "value": 1, + "raw": "1" + }, + "kind": "init" + } + ] + }, + "async": false, + "generator": false, + "references": [], + "fileAttachments": [], + "databaseClients": [], + "secrets": [], + "declarations": [ + { + "type": "Identifier", + "start": 2, + "end": 3, + "name": "x" + }, + { + "type": "Identifier", + "start": 5, + "end": 6, + "name": "y" + } + ] +} \ No newline at end of file diff --git a/test/output/destructure-trailing-comma.js.json b/test/output/destructure-trailing-comma.js.json index f129028..4418ae5 100644 --- a/test/output/destructure-trailing-comma.js.json +++ b/test/output/destructure-trailing-comma.js.json @@ -1,11 +1,11 @@ { "error": { "type": "SyntaxError", - "message": "Unexpected token (1:6)", - "pos": 6, + "message": "Unexpected token (1:8)", + "pos": 8, "loc": { "line": 1, - "column": 6 + "column": 8 } } } \ No newline at end of file