From 3ee5cc64af5c1d8fb606c73cbe6d965913031f8e Mon Sep 17 00:00:00 2001 From: Nic <162764842+Nic-Polumeyv@users.noreply.github.com> Date: Tue, 8 Sep 2026 17:22:40 -0400 Subject: [PATCH] loose mode asks the parser to recover: the bracket scanner, the synthetic declaration and the paren lookahead go, a placeholder spans what could not be read --- .../src/compiler/phases/1-parse/index.js | 1 + .../svelte/src/compiler/phases/1-parse/js.js | 30 +- .../src/compiler/phases/1-parse/state/tag.js | 41 +- .../compiler/phases/1-parse/utils/bracket.js | 144 ---- .../samples/malformed-snippet-2/_config.js | 6 +- .../samples/loose-invalid-block/output.json | 30 + .../loose-invalid-expression/output.json | 715 +++++++++++++++++- .../samples/loose-declaration-tag/output.json | 207 ++++- .../samples/loose-invalid-block/output.json | 33 +- .../loose-invalid-expression/output.json | 703 ++++++++++++++++- 10 files changed, 1598 insertions(+), 312 deletions(-) diff --git a/packages/svelte/src/compiler/phases/1-parse/index.js b/packages/svelte/src/compiler/phases/1-parse/index.js index 2729dec81f..c520c8ea5c 100644 --- a/packages/svelte/src/compiler/phases/1-parse/index.js +++ b/packages/svelte/src/compiler/phases/1-parse/index.js @@ -97,6 +97,7 @@ export class Parser { comments: true, locations: true, scopes: true, + errorRecovery: loose, // a script may export what the component declares elsewhere allowUndeclaredExports: true }); diff --git a/packages/svelte/src/compiler/phases/1-parse/js.js b/packages/svelte/src/compiler/phases/1-parse/js.js index cb5128fade..ab82c2d8df 100644 --- a/packages/svelte/src/compiler/phases/1-parse/js.js +++ b/packages/svelte/src/compiler/phases/1-parse/js.js @@ -3,7 +3,6 @@ /** @import { Parser } from './index.js' */ import * as teasel from '@teasel/parser'; import * as e from '../../errors.js'; -import { find_matching_bracket } from './utils/bracket.js'; import { keep_tables } from '../../utils/ast.js'; /** @@ -67,6 +66,7 @@ export function parse_script(parser, start, end) { /** @type {teasel.Comment[]} */ (ast.comments) ); delete ast.comments; + delete ast.errors; keep_tables(ast, tables(ast)); unsupported(ast.typescript); delete ast.typescript; @@ -105,29 +105,19 @@ function read(parser, run) { /** * @param {Parser} parser * @param {string[]} [stop_at] the template's own tokens after the expression, which end it - * @param {string} [opening_token] the bracket the expression sits in, for loose mode * @returns {Expression} */ -export function read_expression(parser, stop_at, opening_token = '{') { +export function read_expression(parser, stop_at) { const start = parser.index; - - try { - const answer = read(parser, (js) => js.parseExpressionAt(start, stop_at)); - keep_tables(answer.node, tables(answer)); - return answer.node; - } catch (err) { - if (parser.loose) { - // Find the next } and treat it as the end of the expression - const end = find_matching_bracket(parser.template, start, opening_token); - if (end !== undefined) { - parser.index = end; - // We don't know what the expression is and signal this by returning an empty identifier - return { type: 'Identifier', start, end, name: '' }; - } - } - - throw err; + const answer = read(parser, (js) => js.parseExpressionAt(start, stop_at)); + keep_tables(answer.node, tables(answer)); + const node = answer.node; + // the language tools copy an expression's text by its node's range, so the placeholder standing for one that could not be read spans what was read + if (node.type === 'Identifier' && node.name === '' && node.start === node.end) { + node.start = start; + node.end = answer.end; } + return node; } /** diff --git a/packages/svelte/src/compiler/phases/1-parse/state/tag.js b/packages/svelte/src/compiler/phases/1-parse/state/tag.js index 3f8821f9fb..e432accaee 100644 --- a/packages/svelte/src/compiler/phases/1-parse/state/tag.js +++ b/packages/svelte/src/compiler/phases/1-parse/state/tag.js @@ -4,7 +4,7 @@ import * as e from '../../../errors.js'; import { create_fragment, ExpressionMetadata } from '../../nodes.js'; import { read_expression, read_params, read_pattern, read_statement } from '../js.js'; -import { find_matching_bracket, match_bracket } from '../utils/bracket.js'; +import { match_bracket } from '../utils/bracket.js'; const regex_whitespace_with_closing_curly_brace = /\s*}/y; const regex_supported_declaration = /(?:let|const)\b/y; @@ -84,40 +84,7 @@ function read_declaration(parser) { const initial_comment_count = parser.root.comments.length; - /** @type {import('estree').Statement | import('estree').VariableDeclaration} */ - let declaration; - try { - declaration = read_statement(parser); - } catch (error) { - if (!parser.loose) throw error; - - const end = find_matching_bracket(parser.template, start, '{'); - if (end === undefined) throw error; - - parser.index = end; - const kind = parser.template.startsWith('const', start) ? 'const' : 'let'; - - declaration = { - type: 'VariableDeclaration', - kind, - declarations: [ - { - type: 'VariableDeclarator', - id: { - type: 'Identifier', - name: '', - start: parser.index, - end: parser.index - }, - init: null, - start: parser.index, - end: parser.index - } - ], - start, - end - }; - } + const declaration = read_statement(parser); if (declaration.type !== 'VariableDeclaration') { if (declaration.type === 'ExpressionStatement') { @@ -348,10 +315,6 @@ function open(parser) { let parameters = []; if (parser.match('(')) { - if (find_matching_bracket(parser.template, parser.index + 1, '(') === undefined) { - e.expected_token(parser.template.length, ')'); - } - parameters = read_params(parser); } else if (!parser.loose) { e.expected_token(parser.index, '('); diff --git a/packages/svelte/src/compiler/phases/1-parse/utils/bracket.js b/packages/svelte/src/compiler/phases/1-parse/utils/bracket.js index 47299c9de5..4857895c94 100644 --- a/packages/svelte/src/compiler/phases/1-parse/utils/bracket.js +++ b/packages/svelte/src/compiler/phases/1-parse/utils/bracket.js @@ -1,150 +1,6 @@ /** @import { Parser } from '../index.js' */ import * as e from '../../../errors.js'; -/** - * @param {number} num - * @returns {number} Infinity if {@link num} is negative, else {@link num}. - */ -function infinity_if_negative(num) { - if (num < 0) { - return Infinity; - } - return num; -} - -/** - * @param {string} string The string to search. - * @param {number} search_start_index The index to start searching at. - * @param {"'" | '"' | '`'} string_start_char The character that started this string. - * @returns {number} The index of the end of this string expression, or `Infinity` if not found. - */ -function find_string_end(string, search_start_index, string_start_char) { - let string_to_search; - if (string_start_char === '`') { - string_to_search = string; - } else { - // we could slice at the search start index, but this way the index remains valid - string_to_search = string.slice( - 0, - infinity_if_negative(string.indexOf('\n', search_start_index)) - ); - } - - return find_unescaped_char(string_to_search, search_start_index, string_start_char); -} - -/** - * @param {string} string The string to search. - * @param {number} search_start_index The index to start searching at. - * @returns {number} The index of the end of this regex expression, or `Infinity` if not found. - */ -function find_regex_end(string, search_start_index) { - const slash = find_unescaped_char(string, search_start_index, '/'); - const eol = find_unescaped_char(string, search_start_index, '\n'); - return slash < eol ? slash : Infinity; -} - -/** - * - * @param {string} string The string to search. - * @param {number} search_start_index The index to begin the search at. - * @param {string} char The character to search for. - * @returns {number} The index of the first unescaped instance of {@link char}, or `Infinity` if not found. - */ -function find_unescaped_char(string, search_start_index, char) { - let i = search_start_index; - while (true) { - const found_index = string.indexOf(char, i); - if (found_index === -1) { - return Infinity; - } - if (count_leading_backslashes(string, found_index - 1) % 2 === 0) { - return found_index; - } - i = found_index + 1; - } -} - -/** - * Count consecutive leading backslashes before {@link search_start_index}. - * - * @example - * ```js - * count_leading_backslashes('\\\\\\foo', 2); // 3 (the backslashes have to be escaped in the string literal, there are three in reality) - * ``` - * - * @param {string} string The string to search. - * @param {number} search_start_index The index to begin the search at. - */ -function count_leading_backslashes(string, search_start_index) { - let i = search_start_index; - let count = 0; - while (string[i] === '\\') { - count++; - i--; - } - return count; -} - -/** - * Finds the corresponding closing bracket, ignoring brackets found inside comments, strings, or regex expressions. - * @param {string} template The string to search. - * @param {number} index The index to begin the search at. - * @param {string} open The opening bracket (ex: `'{'` will search for `'}'`). - * @returns {number | undefined} The index of the closing bracket, or undefined if not found. - */ -export function find_matching_bracket(template, index, open) { - const close = default_brackets[open]; - let brackets = 1; - let i = index; - while (brackets > 0 && i < template.length) { - const char = template[i]; - switch (char) { - case "'": - case '"': - case '`': - i = find_string_end(template, i + 1, char) + 1; - continue; - case '/': { - const next_char = template[i + 1]; - if (!next_char) { - // `/` is the last character; advance past it so we don't loop forever - i++; - continue; - } - if (next_char === '/') { - i = infinity_if_negative(template.indexOf('\n', i + 1)) + '\n'.length; - continue; - } - if (next_char === '*') { - i = infinity_if_negative(template.indexOf('*/', i + 1)) + '*/'.length; - continue; - } - const end = find_regex_end(template, i + 1) + '/'.length; - if (end === Infinity) { - i++; - } else { - i = end; - } - continue; - } - default: { - const char = template[i]; - if (char === open) { - brackets++; - } else if (char === close) { - brackets--; - } - if (brackets === 0) { - return i; - } - i++; - } - } - } - return undefined; -} - /** @type {Record} */ const default_brackets = { '{': '}', diff --git a/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js b/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js index 73154e8971..05de749918 100644 --- a/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js +++ b/packages/svelte/tests/compiler-errors/samples/malformed-snippet-2/_config.js @@ -2,8 +2,8 @@ import { test } from '../../test'; export default test({ error: { - code: 'expected_token', - message: 'Expected token )', - position: [31, 31] + code: 'js_parse_error', + message: 'Unexpected token', + position: [21, 21] } }); diff --git a/packages/svelte/tests/parser-legacy/samples/loose-invalid-block/output.json b/packages/svelte/tests/parser-legacy/samples/loose-invalid-block/output.json index c4d0dd4aa4..2d9ce36572 100644 --- a/packages/svelte/tests/parser-legacy/samples/loose-invalid-block/output.json +++ b/packages/svelte/tests/parser-legacy/samples/loose-invalid-block/output.json @@ -12,6 +12,16 @@ "type": "Identifier", "start": 5, "end": 5, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 5 + } + }, "name": "" }, "children": [], @@ -28,6 +38,16 @@ "type": "Identifier", "start": 17, "end": 17, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 10 + } + }, "name": "" }, "children": [], @@ -59,6 +79,16 @@ "type": "Identifier", "start": 42, "end": 42, + "loc": { + "start": { + "line": 6, + "column": 7 + }, + "end": { + "line": 6, + "column": 7 + } + }, "name": "" } }, diff --git a/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json b/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json index 4339b7af5d..976b56c2b2 100644 --- a/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json +++ b/packages/svelte/tests/parser-legacy/samples/loose-invalid-expression/output.json @@ -95,6 +95,16 @@ "type": "Identifier", "start": 25, "end": 25, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 10 + } + }, "name": "" } } @@ -139,10 +149,53 @@ "start": 44, "end": 48, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 45, "end": 47, - "name": "" + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 12 + } + }, + "object": { + "type": "Identifier", + "start": 45, + "end": 46, + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 11 + } + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 47, + "end": 47, + "loc": { + "start": { + "line": 4, + "column": 12 + }, + "end": { + "line": 4, + "column": 12 + } + }, + "name": "" + }, + "computed": false, + "optional": false } } ] @@ -186,10 +239,54 @@ "start": 65, "end": 73, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 66, "end": 72, - "name": "" + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 16 + } + }, + "object": { + "type": "Literal", + "start": 66, + "end": 71, + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "value": "hi}", + "raw": "'hi}'" + }, + "property": { + "type": "Identifier", + "start": 72, + "end": 72, + "loc": { + "start": { + "line": 5, + "column": 16 + }, + "end": { + "line": 5, + "column": 16 + } + }, + "name": "" + }, + "computed": false, + "optional": false } } ] @@ -233,10 +330,73 @@ "start": 100, "end": 110, "expression": { - "type": "Identifier", + "type": "ArrowFunctionExpression", "start": 101, "end": 109, - "name": "" + "loc": { + "start": { + "line": 6, + "column": 20 + }, + "end": { + "line": 6, + "column": 28 + } + }, + "id": null, + "expression": true, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "MemberExpression", + "start": 107, + "end": 109, + "loc": { + "start": { + "line": 6, + "column": 26 + }, + "end": { + "line": 6, + "column": 28 + } + }, + "object": { + "type": "Identifier", + "start": 107, + "end": 108, + "loc": { + "start": { + "line": 6, + "column": 26 + }, + "end": { + "line": 6, + "column": 27 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 109, + "end": 109, + "loc": { + "start": { + "line": 6, + "column": 28 + }, + "end": { + "line": 6, + "column": 28 + } + }, + "name": "" + }, + "computed": false, + "optional": false + } } } ] @@ -275,10 +435,53 @@ } }, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 134, "end": 136, - "name": "" + "loc": { + "start": { + "line": 8, + "column": 19 + }, + "end": { + "line": 8, + "column": 21 + } + }, + "object": { + "type": "Identifier", + "start": 134, + "end": 135, + "loc": { + "start": { + "line": 8, + "column": 19 + }, + "end": { + "line": 8, + "column": 20 + } + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 136, + "end": 136, + "loc": { + "start": { + "line": 8, + "column": 21 + }, + "end": { + "line": 8, + "column": 21 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "modifiers": [] } @@ -297,10 +500,53 @@ "start": 145, "end": 149, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 146, "end": 148, - "name": "" + "loc": { + "start": { + "line": 10, + "column": 4 + }, + "end": { + "line": 10, + "column": 6 + } + }, + "object": { + "type": "Identifier", + "start": 146, + "end": 147, + "loc": { + "start": { + "line": 10, + "column": 4 + }, + "end": { + "line": 10, + "column": 5 + } + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 148, + "end": 148, + "loc": { + "start": { + "line": 10, + "column": 6 + }, + "end": { + "line": 10, + "column": 6 + } + }, + "name": "" + }, + "computed": false, + "optional": false } }, { @@ -315,10 +561,86 @@ "start": 153, "end": 164, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 154, "end": 163, - "name": "" + "loc": { + "start": { + "line": 11, + "column": 1 + }, + "end": { + "line": 11, + "column": 10 + } + }, + "object": { + "type": "Identifier", + "start": 154, + "end": 157, + "loc": { + "start": { + "line": 11, + "column": 1 + }, + "end": { + "line": 11, + "column": 4 + } + }, + "name": "foo" + }, + "property": { + "type": "MemberExpression", + "start": 158, + "end": 162, + "loc": { + "start": { + "line": 11, + "column": 5 + }, + "end": { + "line": 11, + "column": 9 + } + }, + "object": { + "type": "Identifier", + "start": 158, + "end": 161, + "loc": { + "start": { + "line": 11, + "column": 5 + }, + "end": { + "line": 11, + "column": 8 + } + }, + "name": "bar" + }, + "property": { + "type": "Identifier", + "start": 162, + "end": 162, + "loc": { + "start": { + "line": 11, + "column": 9 + }, + "end": { + "line": 11, + "column": 9 + } + }, + "name": "" + }, + "computed": false, + "optional": false + }, + "computed": true, + "optional": false } }, { @@ -333,10 +655,53 @@ "start": 166, "end": 179, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 171, "end": 173, - "name": "" + "loc": { + "start": { + "line": 13, + "column": 5 + }, + "end": { + "line": 13, + "column": 7 + } + }, + "object": { + "type": "Identifier", + "start": 171, + "end": 172, + "loc": { + "start": { + "line": 13, + "column": 5 + }, + "end": { + "line": 13, + "column": 6 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 173, + "end": 173, + "loc": { + "start": { + "line": 13, + "column": 7 + }, + "end": { + "line": 13, + "column": 7 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "children": [] }, @@ -387,10 +752,53 @@ "name": "array" }, "key": { - "type": "Identifier", + "type": "MemberExpression", "start": 203, "end": 208, - "name": "" + "loc": { + "start": { + "line": 15, + "column": 22 + }, + "end": { + "line": 15, + "column": 27 + } + }, + "object": { + "type": "Identifier", + "start": 203, + "end": 207, + "loc": { + "start": { + "line": 15, + "column": 22 + }, + "end": { + "line": 15, + "column": 26 + } + }, + "name": "item" + }, + "property": { + "type": "Identifier", + "start": 208, + "end": 208, + "loc": { + "start": { + "line": 15, + "column": 27 + }, + "end": { + "line": 15, + "column": 27 + } + }, + "name": "" + }, + "computed": false, + "optional": false } }, { @@ -405,12 +813,72 @@ "start": 219, "end": 246, "children": [], - "context": null, - "expression": { + "context": { "type": "Identifier", - "start": 226, + "name": "item", + "start": 234, "end": 238, - "name": "" + "loc": { + "start": { + "line": 17, + "column": 15, + "character": 234 + }, + "end": { + "line": 17, + "column": 19, + "character": 238 + } + } + }, + "expression": { + "type": "MemberExpression", + "start": 226, + "end": 231, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 12 + } + }, + "object": { + "type": "Identifier", + "start": 226, + "end": 229, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 10 + } + }, + "name": "obj" + }, + "property": { + "type": "Identifier", + "start": 231, + "end": 231, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 12 + } + }, + "name": "" + }, + "computed": false, + "optional": false } }, { @@ -425,10 +893,53 @@ "start": 248, "end": 267, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 256, "end": 258, - "name": "" + "loc": { + "start": { + "line": 19, + "column": 8 + }, + "end": { + "line": 19, + "column": 10 + } + }, + "object": { + "type": "Identifier", + "start": 256, + "end": 257, + "loc": { + "start": { + "line": 19, + "column": 8 + }, + "end": { + "line": 19, + "column": 9 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 258, + "end": 258, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 10 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "value": null, "error": null, @@ -466,26 +977,86 @@ "start": 269, "end": 295, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 277, + "end": 280, + "loc": { + "start": { + "line": 21, + "column": 8 + }, + "end": { + "line": 21, + "column": 11 + } + }, + "object": { + "type": "Identifier", + "start": 277, + "end": 278, + "loc": { + "start": { + "line": 21, + "column": 8 + }, + "end": { + "line": 21, + "column": 9 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 280, + "end": 280, + "loc": { + "start": { + "line": 21, + "column": 11 + }, + "end": { + "line": 21, + "column": 11 + } + }, + "name": "" + }, + "computed": false, + "optional": false + }, + "value": { + "type": "Identifier", + "name": "y", + "start": 285, "end": 286, - "name": "" + "loc": { + "start": { + "line": 21, + "column": 16, + "character": 285 + }, + "end": { + "line": 21, + "column": 17, + "character": 286 + } + } }, - "value": null, "error": null, "pending": { "type": "PendingBlock", - "start": 287, - "end": 287, + "start": null, + "end": null, "children": [], - "skip": false + "skip": true }, "then": { "type": "ThenBlock", - "start": null, - "end": null, + "start": 287, + "end": 267, "children": [], - "skip": true + "skip": false }, "catch": { "type": "CatchBlock", @@ -507,19 +1078,79 @@ "start": 297, "end": 324, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 305, - "end": 315, - "name": "" + "end": 308, + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 23, + "column": 11 + } + }, + "object": { + "type": "Identifier", + "start": 305, + "end": 306, + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 23, + "column": 9 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 308, + "end": 308, + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 11 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "value": null, - "error": null, + "error": { + "type": "Identifier", + "name": "y", + "start": 314, + "end": 315, + "loc": { + "start": { + "line": 23, + "column": 17, + "character": 314 + }, + "end": { + "line": 23, + "column": 18, + "character": 315 + } + } + }, "pending": { "type": "PendingBlock", - "start": 316, - "end": 316, + "start": null, + "end": null, "children": [], - "skip": false + "skip": true }, "then": { "type": "ThenBlock", @@ -530,12 +1161,12 @@ }, "catch": { "type": "CatchBlock", - "start": null, - "end": null, + "start": 316, + "end": 295, "children": [], - "skip": true + "skip": false } } ] } -} \ No newline at end of file +} diff --git a/packages/svelte/tests/parser-modern/samples/loose-declaration-tag/output.json b/packages/svelte/tests/parser-modern/samples/loose-declaration-tag/output.json index 270d16af94..f66606e154 100644 --- a/packages/svelte/tests/parser-modern/samples/loose-declaration-tag/output.json +++ b/packages/svelte/tests/parser-modern/samples/loose-declaration-tag/output.json @@ -45,23 +45,53 @@ "end": 18, "declaration": { "type": "VariableDeclaration", - "kind": "let", + "start": 13, + "end": 17, + "loc": { + "start": { + "line": 2, + "column": 2 + }, + "end": { + "line": 2, + "column": 6 + } + }, "declarations": [ { "type": "VariableDeclarator", + "start": 17, + "end": 17, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 6 + } + }, "id": { "type": "Identifier", - "name": "", "start": 17, - "end": 17 + "end": 17, + "loc": { + "start": { + "line": 2, + "column": 6 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "name": "" }, - "init": null, - "start": 17, - "end": 17 + "init": null } ], - "start": 13, - "end": 17 + "kind": "let" } }, { @@ -77,23 +107,68 @@ "end": 32, "declaration": { "type": "VariableDeclaration", - "kind": "const", + "start": 21, + "end": 31, + "loc": { + "start": { + "line": 3, + "column": 2 + }, + "end": { + "line": 3, + "column": 12 + } + }, "declarations": [ { "type": "VariableDeclarator", + "start": 27, + "end": 31, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 12 + } + }, "id": { "type": "Identifier", - "name": "", - "start": 31, - "end": 31 + "start": 27, + "end": 28, + "loc": { + "start": { + "line": 3, + "column": 8 + }, + "end": { + "line": 3, + "column": 9 + } + }, + "name": "x" }, - "init": null, - "start": 31, - "end": 31 + "init": { + "type": "Identifier", + "start": 31, + "end": 31, + "loc": { + "start": { + "line": 3, + "column": 12 + }, + "end": { + "line": 3, + "column": 12 + } + }, + "name": "" + } } ], - "start": 21, - "end": 31 + "kind": "const" } }, { @@ -109,23 +184,100 @@ "end": 48, "declaration": { "type": "VariableDeclaration", - "kind": "let", + "start": 35, + "end": 47, + "loc": { + "start": { + "line": 4, + "column": 2 + }, + "end": { + "line": 4, + "column": 14 + } + }, "declarations": [ { "type": "VariableDeclarator", + "start": 39, + "end": 47, + "loc": { + "start": { + "line": 4, + "column": 6 + }, + "end": { + "line": 4, + "column": 14 + } + }, "id": { "type": "Identifier", - "name": "", - "start": 47, - "end": 47 + "start": 39, + "end": 40, + "loc": { + "start": { + "line": 4, + "column": 6 + }, + "end": { + "line": 4, + "column": 7 + } + }, + "name": "x" }, - "init": null, - "start": 47, - "end": 47 + "init": { + "type": "BinaryExpression", + "start": 43, + "end": 47, + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 14 + } + }, + "left": { + "type": "Identifier", + "start": 43, + "end": 44, + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 11 + } + }, + "name": "a" + }, + "operator": "/", + "right": { + "type": "Identifier", + "start": 47, + "end": 47, + "loc": { + "start": { + "line": 4, + "column": 14 + }, + "end": { + "line": 4, + "column": 14 + } + }, + "name": "" + } + } } ], - "start": 35, - "end": 47 + "kind": "let" } }, { @@ -141,5 +293,6 @@ } ] }, - "options": null + "options": null, + "comments": [] } diff --git a/packages/svelte/tests/parser-modern/samples/loose-invalid-block/output.json b/packages/svelte/tests/parser-modern/samples/loose-invalid-block/output.json index 69fc7a0c81..ee480341b4 100644 --- a/packages/svelte/tests/parser-modern/samples/loose-invalid-block/output.json +++ b/packages/svelte/tests/parser-modern/samples/loose-invalid-block/output.json @@ -16,6 +16,16 @@ "type": "Identifier", "start": 5, "end": 5, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 5 + } + }, "name": "" }, "consequent": { @@ -42,6 +52,16 @@ "type": "Identifier", "start": 17, "end": 17, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 10 + } + }, "name": "" }, "consequent": { @@ -87,6 +107,16 @@ "type": "Identifier", "start": 42, "end": 42, + "loc": { + "start": { + "line": 6, + "column": 7 + }, + "end": { + "line": 6, + "column": 7 + } + }, "name": "" }, "body": { @@ -191,5 +221,6 @@ } ] }, - "options": null + "options": null, + "comments": [] } diff --git a/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json b/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json index fa4ddda140..0d88a9fb12 100644 --- a/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json +++ b/packages/svelte/tests/parser-modern/samples/loose-invalid-expression/output.json @@ -122,6 +122,16 @@ "type": "Identifier", "start": 25, "end": 25, + "loc": { + "start": { + "line": 2, + "column": 10 + }, + "end": { + "line": 2, + "column": 10 + } + }, "name": "" } } @@ -179,10 +189,53 @@ "start": 44, "end": 48, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 45, "end": 47, - "name": "" + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 12 + } + }, + "object": { + "type": "Identifier", + "start": 45, + "end": 46, + "loc": { + "start": { + "line": 4, + "column": 10 + }, + "end": { + "line": 4, + "column": 11 + } + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 47, + "end": 47, + "loc": { + "start": { + "line": 4, + "column": 12 + }, + "end": { + "line": 4, + "column": 12 + } + }, + "name": "" + }, + "computed": false, + "optional": false } } } @@ -239,10 +292,54 @@ "start": 65, "end": 73, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 66, "end": 72, - "name": "" + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 16 + } + }, + "object": { + "type": "Literal", + "start": 66, + "end": 71, + "loc": { + "start": { + "line": 5, + "column": 10 + }, + "end": { + "line": 5, + "column": 15 + } + }, + "value": "hi}", + "raw": "'hi}'" + }, + "property": { + "type": "Identifier", + "start": 72, + "end": 72, + "loc": { + "start": { + "line": 5, + "column": 16 + }, + "end": { + "line": 5, + "column": 16 + } + }, + "name": "" + }, + "computed": false, + "optional": false } } } @@ -299,10 +396,73 @@ "start": 100, "end": 110, "expression": { - "type": "Identifier", + "type": "ArrowFunctionExpression", "start": 101, "end": 109, - "name": "" + "loc": { + "start": { + "line": 6, + "column": 20 + }, + "end": { + "line": 6, + "column": 28 + } + }, + "id": null, + "expression": true, + "generator": false, + "async": false, + "params": [], + "body": { + "type": "MemberExpression", + "start": 107, + "end": 109, + "loc": { + "start": { + "line": 6, + "column": 26 + }, + "end": { + "line": 6, + "column": 28 + } + }, + "object": { + "type": "Identifier", + "start": 107, + "end": 108, + "loc": { + "start": { + "line": 6, + "column": 26 + }, + "end": { + "line": 6, + "column": 27 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 109, + "end": 109, + "loc": { + "start": { + "line": 6, + "column": 28 + }, + "end": { + "line": 6, + "column": 28 + } + }, + "name": "" + }, + "computed": false, + "optional": false + } } } } @@ -355,10 +515,53 @@ } }, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 134, "end": 136, - "name": "" + "loc": { + "start": { + "line": 8, + "column": 19 + }, + "end": { + "line": 8, + "column": 21 + } + }, + "object": { + "type": "Identifier", + "start": 134, + "end": 135, + "loc": { + "start": { + "line": 8, + "column": 19 + }, + "end": { + "line": 8, + "column": 20 + } + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 136, + "end": 136, + "loc": { + "start": { + "line": 8, + "column": 21 + }, + "end": { + "line": 8, + "column": 21 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "modifiers": [] } @@ -380,10 +583,53 @@ "start": 145, "end": 149, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 146, "end": 148, - "name": "" + "loc": { + "start": { + "line": 10, + "column": 4 + }, + "end": { + "line": 10, + "column": 6 + } + }, + "object": { + "type": "Identifier", + "start": 146, + "end": 147, + "loc": { + "start": { + "line": 10, + "column": 4 + }, + "end": { + "line": 10, + "column": 5 + } + }, + "name": "a" + }, + "property": { + "type": "Identifier", + "start": 148, + "end": 148, + "loc": { + "start": { + "line": 10, + "column": 6 + }, + "end": { + "line": 10, + "column": 6 + } + }, + "name": "" + }, + "computed": false, + "optional": false } }, { @@ -398,10 +644,86 @@ "start": 153, "end": 164, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 154, "end": 163, - "name": "" + "loc": { + "start": { + "line": 11, + "column": 1 + }, + "end": { + "line": 11, + "column": 10 + } + }, + "object": { + "type": "Identifier", + "start": 154, + "end": 157, + "loc": { + "start": { + "line": 11, + "column": 1 + }, + "end": { + "line": 11, + "column": 4 + } + }, + "name": "foo" + }, + "property": { + "type": "MemberExpression", + "start": 158, + "end": 162, + "loc": { + "start": { + "line": 11, + "column": 5 + }, + "end": { + "line": 11, + "column": 9 + } + }, + "object": { + "type": "Identifier", + "start": 158, + "end": 161, + "loc": { + "start": { + "line": 11, + "column": 5 + }, + "end": { + "line": 11, + "column": 8 + } + }, + "name": "bar" + }, + "property": { + "type": "Identifier", + "start": 162, + "end": 162, + "loc": { + "start": { + "line": 11, + "column": 9 + }, + "end": { + "line": 11, + "column": 9 + } + }, + "name": "" + }, + "computed": false, + "optional": false + }, + "computed": true, + "optional": false } }, { @@ -417,10 +739,53 @@ "start": 166, "end": 179, "test": { - "type": "Identifier", + "type": "MemberExpression", "start": 171, "end": 173, - "name": "" + "loc": { + "start": { + "line": 13, + "column": 5 + }, + "end": { + "line": 13, + "column": 7 + } + }, + "object": { + "type": "Identifier", + "start": 171, + "end": 172, + "loc": { + "start": { + "line": 13, + "column": 5 + }, + "end": { + "line": 13, + "column": 6 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 173, + "end": 173, + "loc": { + "start": { + "line": 13, + "column": 7 + }, + "end": { + "line": 13, + "column": 7 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "consequent": { "type": "Fragment", @@ -478,10 +843,53 @@ } }, "key": { - "type": "Identifier", + "type": "MemberExpression", "start": 203, "end": 208, - "name": "" + "loc": { + "start": { + "line": 15, + "column": 22 + }, + "end": { + "line": 15, + "column": 27 + } + }, + "object": { + "type": "Identifier", + "start": 203, + "end": 207, + "loc": { + "start": { + "line": 15, + "column": 22 + }, + "end": { + "line": 15, + "column": 26 + } + }, + "name": "item" + }, + "property": { + "type": "Identifier", + "start": 208, + "end": 208, + "loc": { + "start": { + "line": 15, + "column": 27 + }, + "end": { + "line": 15, + "column": 27 + } + }, + "name": "" + }, + "computed": false, + "optional": false } }, { @@ -496,16 +904,76 @@ "start": 219, "end": 246, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 226, - "end": 238, - "name": "" + "end": 231, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 12 + } + }, + "object": { + "type": "Identifier", + "start": 226, + "end": 229, + "loc": { + "start": { + "line": 17, + "column": 7 + }, + "end": { + "line": 17, + "column": 10 + } + }, + "name": "obj" + }, + "property": { + "type": "Identifier", + "start": 231, + "end": 231, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 12 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "body": { "type": "Fragment", "nodes": [] }, - "context": null + "context": { + "type": "Identifier", + "name": "item", + "start": 234, + "end": 238, + "loc": { + "start": { + "line": 17, + "column": 15, + "character": 234 + }, + "end": { + "line": 17, + "column": 19, + "character": 238 + } + } + } }, { "type": "Text", @@ -519,10 +987,53 @@ "start": 248, "end": 267, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 256, "end": 258, - "name": "" + "loc": { + "start": { + "line": 19, + "column": 8 + }, + "end": { + "line": 19, + "column": 10 + } + }, + "object": { + "type": "Identifier", + "start": 256, + "end": 257, + "loc": { + "start": { + "line": 19, + "column": 8 + }, + "end": { + "line": 19, + "column": 9 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 258, + "end": 258, + "loc": { + "start": { + "line": 19, + "column": 10 + }, + "end": { + "line": 19, + "column": 10 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "value": null, "error": null, @@ -545,18 +1056,78 @@ "start": 269, "end": 295, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 277, + "end": 280, + "loc": { + "start": { + "line": 21, + "column": 8 + }, + "end": { + "line": 21, + "column": 11 + } + }, + "object": { + "type": "Identifier", + "start": 277, + "end": 278, + "loc": { + "start": { + "line": 21, + "column": 8 + }, + "end": { + "line": 21, + "column": 9 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 280, + "end": 280, + "loc": { + "start": { + "line": 21, + "column": 11 + }, + "end": { + "line": 21, + "column": 11 + } + }, + "name": "" + }, + "computed": false, + "optional": false + }, + "value": { + "type": "Identifier", + "name": "y", + "start": 285, "end": 286, - "name": "" + "loc": { + "start": { + "line": 21, + "column": 16, + "character": 285 + }, + "end": { + "line": 21, + "column": 17, + "character": 286 + } + } }, - "value": null, "error": null, - "pending": { + "pending": null, + "then": { "type": "Fragment", "nodes": [] }, - "then": null, "catch": null }, { @@ -571,22 +1142,82 @@ "start": 297, "end": 324, "expression": { - "type": "Identifier", + "type": "MemberExpression", "start": 305, - "end": 315, - "name": "" + "end": 308, + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 23, + "column": 11 + } + }, + "object": { + "type": "Identifier", + "start": 305, + "end": 306, + "loc": { + "start": { + "line": 23, + "column": 8 + }, + "end": { + "line": 23, + "column": 9 + } + }, + "name": "x" + }, + "property": { + "type": "Identifier", + "start": 308, + "end": 308, + "loc": { + "start": { + "line": 23, + "column": 11 + }, + "end": { + "line": 23, + "column": 11 + } + }, + "name": "" + }, + "computed": false, + "optional": false }, "value": null, - "error": null, - "pending": { - "type": "Fragment", - "nodes": [] + "error": { + "type": "Identifier", + "name": "y", + "start": 314, + "end": 315, + "loc": { + "start": { + "line": 23, + "column": 17, + "character": 314 + }, + "end": { + "line": 23, + "column": 18, + "character": 315 + } + } }, + "pending": null, "then": null, - "catch": null + "catch": { + "type": "Fragment", + "nodes": [] + } } ] }, "options": null, "comments": [] -} \ No newline at end of file +}