fix: preserve node locations for better sourcemaps (#17269)

* preserve node locations

* preserve component IDs

* update tests

* use IDs for elements

* more

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* WIP

* tweak

* tidy up

* changeset

* oops
pull/17284/head
Rich Harris 9 months ago committed by GitHub
parent 6d696be170
commit 617e179e68
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: preserve node locations for better sourcemaps

@ -1,4 +1,6 @@
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { Location } from 'locate-character' */
/** @import * as ESTree from 'estree' */
// @ts-expect-error acorn type definitions are borked in the release we use // @ts-expect-error acorn type definitions are borked in the release we use
import { isIdentifierStart, isIdentifierChar } from 'acorn'; import { isIdentifierStart, isIdentifierChar } from 'acorn';
import fragment from './state/fragment.js'; import fragment from './state/fragment.js';
@ -218,31 +220,45 @@ export class Parser {
return result; return result;
} }
/** @param {any} allow_reserved */ /**
read_identifier(allow_reserved = false) { * @returns {ESTree.Identifier & { start: number, end: number, loc: { start: Location, end: Location } }}
*/
read_identifier() {
const start = this.index; const start = this.index;
let end = start;
let name = '';
let i = this.index; const code = /** @type {number} */ (this.template.codePointAt(this.index));
const code = /** @type {number} */ (this.template.codePointAt(i)); if (isIdentifierStart(code, true)) {
if (!isIdentifierStart(code, true)) return null; let i = this.index;
end += code <= 0xffff ? 1 : 2;
i += code <= 0xffff ? 1 : 2; while (end < this.template.length) {
const code = /** @type {number} */ (this.template.codePointAt(end));
while (i < this.template.length) { if (!isIdentifierChar(code, true)) break;
const code = /** @type {number} */ (this.template.codePointAt(i)); end += code <= 0xffff ? 1 : 2;
}
if (!isIdentifierChar(code, true)) break;
i += code <= 0xffff ? 1 : 2;
}
const identifier = this.template.slice(this.index, (this.index = i)); name = this.template.slice(start, end);
this.index = end;
if (!allow_reserved && is_reserved(identifier)) { if (is_reserved(name)) {
e.unexpected_reserved_word(start, identifier); e.unexpected_reserved_word(start, name);
}
} }
return identifier; return {
type: 'Identifier',
name,
start,
end,
loc: {
start: state.locator(start),
end: state.locator(end)
}
};
} }
/** @param {RegExp} pattern */ /** @param {RegExp} pattern */

@ -1,11 +1,9 @@
/** @import { Location } from 'locate-character' */
/** @import { Pattern } from 'estree' */ /** @import { Pattern } from 'estree' */
/** @import { Parser } from '../index.js' */ /** @import { Parser } from '../index.js' */
import { match_bracket } from '../utils/bracket.js'; import { match_bracket } from '../utils/bracket.js';
import { parse_expression_at } from '../acorn.js'; import { parse_expression_at } from '../acorn.js';
import { regex_not_newline_characters } from '../../patterns.js'; import { regex_not_newline_characters } from '../../patterns.js';
import * as e from '../../../errors.js'; import * as e from '../../../errors.js';
import { locator } from '../../../state.js';
/** /**
* @param {Parser} parser * @param {Parser} parser
@ -15,20 +13,13 @@ export default function read_pattern(parser) {
const start = parser.index; const start = parser.index;
let i = parser.index; let i = parser.index;
const name = parser.read_identifier(); const id = parser.read_identifier();
if (name !== null) { if (id.name !== '') {
const annotation = read_type_annotation(parser); const annotation = read_type_annotation(parser);
return { return {
type: 'Identifier', ...id,
name,
start,
loc: {
start: /** @type {Location} */ (locator(start)),
end: /** @type {Location} */ (locator(parser.index))
},
end: parser.index,
typeAnnotation: annotation typeAnnotation: annotation
}; };
} }

@ -1,4 +1,5 @@
/** @import { Expression } from 'estree' */ /** @import { Expression, Identifier, SourceLocation } from 'estree' */
/** @import { Location } from 'locate-character' */
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { Parser } from '../index.js' */ /** @import { Parser } from '../index.js' */
import { is_void } from '../../../../utils.js'; import { is_void } from '../../../../utils.js';
@ -13,6 +14,8 @@ import { create_attribute, ExpressionMetadata, is_element_node } from '../../nod
import { get_attribute_expression, is_expression_attribute } from '../../../utils/ast.js'; import { get_attribute_expression, is_expression_attribute } from '../../../utils/ast.js';
import { closing_tag_omitted } from '../../../../html-tree-validation.js'; import { closing_tag_omitted } from '../../../../html-tree-validation.js';
import { list } from '../../../utils/string.js'; import { list } from '../../../utils/string.js';
import { locator } from '../../../state.js';
import * as b from '#compiler/builders';
const regex_invalid_unquoted_attribute_value = /^(\/>|[\s"'=<>`])/; const regex_invalid_unquoted_attribute_value = /^(\/>|[\s"'=<>`])/;
const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i; const regex_closing_textarea_tag = /^<\/textarea(\s[^>]*)?>/i;
@ -67,10 +70,9 @@ export default function element(parser) {
return; return;
} }
const is_closing_tag = parser.eat('/'); if (parser.eat('/')) {
const name = parser.read_until(regex_whitespace_or_slash_or_closing_tag); const name = parser.read_until(regex_whitespace_or_slash_or_closing_tag);
if (is_closing_tag) {
parser.allow_whitespace(); parser.allow_whitespace();
parser.eat('>', true); parser.eat('>', true);
@ -125,39 +127,41 @@ export default function element(parser) {
return; return;
} }
if (name.startsWith('svelte:') && !meta_tags.has(name)) { const tag = read_tag(parser, regex_whitespace_or_slash_or_closing_tag);
const bounds = { start: start + 1, end: start + 1 + name.length };
if (tag.name.startsWith('svelte:') && !meta_tags.has(tag.name)) {
const bounds = { start: start + 1, end: start + 1 + tag.name.length };
e.svelte_meta_invalid_tag(bounds, list(Array.from(meta_tags.keys()))); e.svelte_meta_invalid_tag(bounds, list(Array.from(meta_tags.keys())));
} }
if (!regex_valid_element_name.test(name) && !regex_valid_component_name.test(name)) { if (!regex_valid_element_name.test(tag.name) && !regex_valid_component_name.test(tag.name)) {
// <div. -> in the middle of typing -> allow in loose mode // <div. -> in the middle of typing -> allow in loose mode
if (!parser.loose || !name.endsWith('.')) { if (!parser.loose || !tag.name.endsWith('.')) {
const bounds = { start: start + 1, end: start + 1 + name.length }; const bounds = { start: start + 1, end: start + 1 + tag.name.length };
e.tag_invalid_name(bounds); e.tag_invalid_name(bounds);
} }
} }
if (root_only_meta_tags.has(name)) { if (root_only_meta_tags.has(tag.name)) {
if (name in parser.meta_tags) { if (tag.name in parser.meta_tags) {
e.svelte_meta_duplicate(start, name); e.svelte_meta_duplicate(start, tag.name);
} }
if (parent.type !== 'Root') { if (parent.type !== 'Root') {
e.svelte_meta_invalid_placement(start, name); e.svelte_meta_invalid_placement(start, tag.name);
} }
parser.meta_tags[name] = true; parser.meta_tags[tag.name] = true;
} }
const type = meta_tags.has(name) const type = meta_tags.has(tag.name)
? meta_tags.get(name) ? meta_tags.get(tag.name)
: regex_valid_component_name.test(name) || (parser.loose && name.endsWith('.')) : regex_valid_component_name.test(tag.name) || (parser.loose && tag.name.endsWith('.'))
? 'Component' ? 'Component'
: name === 'title' && parent_is_head(parser.stack) : tag.name === 'title' && parent_is_head(parser.stack)
? 'TitleElement' ? 'TitleElement'
: // TODO Svelte 6/7: once slots are removed in favor of snippets, always keep slot as a regular element : // TODO Svelte 6/7: once slots are removed in favor of snippets, always keep slot as a regular element
name === 'slot' && !parent_is_shadowroot_template(parser.stack) tag.name === 'slot' && !parent_is_shadowroot_template(parser.stack)
? 'SlotElement' ? 'SlotElement'
: 'RegularElement'; : 'RegularElement';
@ -168,7 +172,8 @@ export default function element(parser) {
type, type,
start, start,
end: -1, end: -1,
name, name: tag.name,
name_loc: tag.loc,
attributes: [], attributes: [],
fragment: create_fragment(true), fragment: create_fragment(true),
metadata: { metadata: {
@ -184,7 +189,8 @@ export default function element(parser) {
type, type,
start, start,
end: -1, end: -1,
name, name: tag.name,
name_loc: tag.loc,
attributes: [], attributes: [],
fragment: create_fragment(true), fragment: create_fragment(true),
metadata: { metadata: {
@ -194,14 +200,14 @@ export default function element(parser) {
parser.allow_whitespace(); parser.allow_whitespace();
if (parent.type === 'RegularElement' && closing_tag_omitted(parent.name, name)) { if (parent.type === 'RegularElement' && closing_tag_omitted(parent.name, tag.name)) {
const end = parent.fragment.nodes[0]?.start ?? start; const end = parent.fragment.nodes[0]?.start ?? start;
w.element_implicitly_closed({ start: parent.start, end }, `<${name}>`, `</${parent.name}>`); w.element_implicitly_closed({ start: parent.start, end }, `<${tag.name}>`, `</${parent.name}>`);
parent.end = start; parent.end = start;
parser.pop(); parser.pop();
parser.last_auto_closed_tag = { parser.last_auto_closed_tag = {
tag: parent.name, tag: parent.name,
reason: name, reason: tag.name,
depth: parser.stack.length depth: parser.stack.length
}; };
} }
@ -211,7 +217,7 @@ export default function element(parser) {
const current = parser.current(); const current = parser.current();
const is_top_level_script_or_style = const is_top_level_script_or_style =
(name === 'script' || name === 'style') && current.type === 'Root'; (tag.name === 'script' || tag.name === 'style') && current.type === 'Root';
const read = is_top_level_script_or_style ? read_static_attribute : read_attribute; const read = is_top_level_script_or_style ? read_static_attribute : read_attribute;
@ -324,7 +330,7 @@ export default function element(parser) {
} }
} }
if (name === 'script') { if (tag.name === 'script') {
const content = read_script(parser, start, element.attributes); const content = read_script(parser, start, element.attributes);
if (prev_comment) { if (prev_comment) {
// We take advantage of the fact that the root will never have leadingComments set, // We take advantage of the fact that the root will never have leadingComments set,
@ -352,7 +358,7 @@ export default function element(parser) {
parser.append(element); parser.append(element);
const self_closing = parser.eat('/') || is_void(name); const self_closing = parser.eat('/') || is_void(tag.name);
const closed = parser.eat('>', true, false); const closed = parser.eat('>', true, false);
// Loose parsing mode // Loose parsing mode
@ -382,7 +388,7 @@ export default function element(parser) {
if (self_closing || !closed) { if (self_closing || !closed) {
// don't push self-closing elements onto the stack // don't push self-closing elements onto the stack
element.end = parser.index; element.end = parser.index;
} else if (name === 'textarea') { } else if (tag.name === 'textarea') {
// special case // special case
element.fragment.nodes = read_sequence( element.fragment.nodes = read_sequence(
parser, parser,
@ -391,10 +397,10 @@ export default function element(parser) {
); );
parser.read(regex_closing_textarea_tag); parser.read(regex_closing_textarea_tag);
element.end = parser.index; element.end = parser.index;
} else if (name === 'script' || name === 'style') { } else if (tag.name === 'script' || tag.name === 'style') {
// special case // special case
const start = parser.index; const start = parser.index;
const data = parser.read_until(new RegExp(`</${name}>`)); const data = parser.read_until(new RegExp(`</${tag.name}>`));
const end = parser.index; const end = parser.index;
/** @type {AST.Text} */ /** @type {AST.Text} */
@ -407,7 +413,7 @@ export default function element(parser) {
}; };
element.fragment.nodes.push(node); element.fragment.nodes.push(node);
parser.eat(`</${name}>`, true); parser.eat(`</${tag.name}>`, true);
element.end = parser.index; element.end = parser.index;
} else { } else {
parser.stack.push(element); parser.stack.push(element);
@ -450,8 +456,8 @@ function parent_is_shadowroot_template(stack) {
function read_static_attribute(parser) { function read_static_attribute(parser) {
const start = parser.index; const start = parser.index;
const name = parser.read_until(regex_token_ending_character); const tag = read_tag(parser, regex_token_ending_character);
if (!name) return null; if (!tag.name) return null;
/** @type {true | Array<AST.Text | AST.ExpressionTag>} */ /** @type {true | Array<AST.Text | AST.ExpressionTag>} */
let value = true; let value = true;
@ -485,7 +491,7 @@ function read_static_attribute(parser) {
e.expected_token(parser.index, '='); e.expected_token(parser.index, '=');
} }
return create_attribute(name, start, parser.index, value); return create_attribute(tag.name, tag.loc, start, parser.index, value);
} }
/** /**
@ -538,10 +544,9 @@ function read_attribute(parser) {
return spread; return spread;
} else { } else {
const value_start = parser.index; const id = parser.read_identifier();
let name = parser.read_identifier();
if (name === null) { if (id.name === '') {
if ( if (
parser.loose && parser.loose &&
(parser.match('#') || parser.match('/') || parser.match('@') || parser.match(':')) (parser.match('#') || parser.match('/') || parser.match('@') || parser.match(':'))
@ -551,7 +556,6 @@ function read_attribute(parser) {
return null; return null;
} else if (parser.loose && parser.match('}')) { } else if (parser.loose && parser.match('}')) {
// Likely in the middle of typing, just created the shorthand // Likely in the middle of typing, just created the shorthand
name = '';
} else { } else {
e.attribute_empty_shorthand(start); e.attribute_empty_shorthand(start);
} }
@ -563,32 +567,28 @@ function read_attribute(parser) {
/** @type {AST.ExpressionTag} */ /** @type {AST.ExpressionTag} */
const expression = { const expression = {
type: 'ExpressionTag', type: 'ExpressionTag',
start: value_start, start: id.start,
end: value_start + name.length, end: id.end,
expression: { expression: id,
start: value_start,
end: value_start + name.length,
type: 'Identifier',
name
},
metadata: { metadata: {
expression: new ExpressionMetadata() expression: new ExpressionMetadata()
} }
}; };
return create_attribute(name, start, parser.index, expression); return create_attribute(id.name, id.loc, start, parser.index, expression);
} }
} }
const name = parser.read_until(regex_token_ending_character); const tag = read_tag(parser, regex_token_ending_character);
if (!name) return null;
if (!tag.name) return null;
let end = parser.index; let end = parser.index;
parser.allow_whitespace(); parser.allow_whitespace();
const colon_index = name.indexOf(':'); const colon_index = tag.name.indexOf(':');
const type = colon_index !== -1 && get_directive_type(name.slice(0, colon_index)); const type = colon_index !== -1 && get_directive_type(tag.name.slice(0, colon_index));
/** @type {true | AST.ExpressionTag | Array<AST.Text | AST.ExpressionTag>} */ /** @type {true | AST.ExpressionTag | Array<AST.Text | AST.ExpressionTag>} */
let value = true; let value = true;
@ -617,10 +617,10 @@ function read_attribute(parser) {
} }
if (type) { if (type) {
const [directive_name, ...modifiers] = name.slice(colon_index + 1).split('|'); const [directive_name, ...modifiers] = tag.name.slice(colon_index + 1).split('|');
if (directive_name === '') { if (directive_name === '') {
e.directive_missing_name({ start, end: start + colon_index + 1 }, name); e.directive_missing_name({ start, end: start + colon_index + 1 }, tag.name);
} }
if (type === 'StyleDirective') { if (type === 'StyleDirective') {
@ -629,6 +629,7 @@ function read_attribute(parser) {
end, end,
type, type,
name: directive_name, name: directive_name,
name_loc: tag.loc,
modifiers: /** @type {Array<'important'>} */ (modifiers), modifiers: /** @type {Array<'important'>} */ (modifiers),
value, value,
metadata: { metadata: {
@ -659,6 +660,7 @@ function read_attribute(parser) {
end, end,
type, type,
name: directive_name, name: directive_name,
name_loc: tag.loc,
expression, expression,
metadata: { metadata: {
expression: new ExpressionMetadata() expression: new ExpressionMetadata()
@ -669,7 +671,7 @@ function read_attribute(parser) {
directive.modifiers = modifiers; directive.modifiers = modifiers;
if (directive.type === 'TransitionDirective') { if (directive.type === 'TransitionDirective') {
const direction = name.slice(0, colon_index); const direction = tag.name.slice(0, colon_index);
directive.intro = direction === 'in' || direction === 'transition'; directive.intro = direction === 'in' || direction === 'transition';
directive.outro = direction === 'out' || direction === 'transition'; directive.outro = direction === 'out' || direction === 'transition';
} }
@ -690,7 +692,7 @@ function read_attribute(parser) {
return directive; return directive;
} }
return create_attribute(name, start, end, value); return create_attribute(tag.name, tag.loc, start, end, value);
} }
/** /**
@ -851,3 +853,25 @@ function read_sequence(parser, done, location) {
e.unexpected_eof(parser.template.length); e.unexpected_eof(parser.template.length);
} }
} }
/**
* @param {Parser} parser
* @param {RegExp} regex
* @returns {Identifier & { start: number, end: number, loc: SourceLocation }}
*/
function read_tag(parser, regex) {
const start = parser.index;
const name = parser.read_until(regex);
const end = parser.index;
return {
type: 'Identifier',
name,
start,
end,
loc: {
start: locator(start),
end: locator(end)
}
};
}

@ -177,7 +177,7 @@ function open(parser) {
if (parser.eat(',')) { if (parser.eat(',')) {
parser.allow_whitespace(); parser.allow_whitespace();
index = parser.read_identifier(); index = parser.read_identifier().name;
if (!index) { if (!index) {
e.expected_identifier(parser.index); e.expected_identifier(parser.index);
} }
@ -347,16 +347,10 @@ function open(parser) {
if (parser.eat('snippet')) { if (parser.eat('snippet')) {
parser.require_whitespace(); parser.require_whitespace();
const name_start = parser.index; const id = parser.read_identifier();
let name = parser.read_identifier();
const name_end = parser.index;
if (name === null) { if (id.name === '' && !parser.loose) {
if (parser.loose) { e.expected_identifier(parser.index);
name = '';
} else {
e.expected_identifier(parser.index);
}
} }
parser.allow_whitespace(); parser.allow_whitespace();
@ -415,12 +409,7 @@ function open(parser) {
type: 'SnippetBlock', type: 'SnippetBlock',
start, start,
end: -1, end: -1,
expression: { expression: id,
type: 'Identifier',
start: name_start,
end: name_end,
name
},
typeParams: type_params, typeParams: type_params,
parameters: function_expression.params, parameters: function_expression.params,
body: create_fragment(), body: create_fragment(),

@ -900,7 +900,7 @@ export function analyze_component(root, source, options) {
// We need an empty class to generate the set_class() or class="" correctly // We need an empty class to generate the set_class() or class="" correctly
if (!has_spread && !has_class && (node.metadata.scoped || has_class_directive)) { if (!has_spread && !has_class && (node.metadata.scoped || has_class_directive)) {
node.attributes.push( node.attributes.push(
create_attribute('class', -1, -1, [ create_attribute('class', null, -1, -1, [
{ {
type: 'Text', type: 'Text',
data: '', data: '',
@ -915,7 +915,7 @@ export function analyze_component(root, source, options) {
// We need an empty style to generate the set_style() correctly // We need an empty style to generate the set_style() correctly
if (!has_spread && !has_style && has_style_directive) { if (!has_spread && !has_style && has_style_directive) {
node.attributes.push( node.attributes.push(
create_attribute('style', -1, -1, [ create_attribute('style', null, -1, -1, [
{ {
type: 'Text', type: 'Text',
data: '', data: '',

@ -48,8 +48,9 @@ export function RegularElement(node, context) {
node.attributes.push( node.attributes.push(
create_attribute( create_attribute(
'value', 'value',
/** @type {AST.Text} */ (node.fragment.nodes.at(0)).start, null,
/** @type {AST.Text} */ (node.fragment.nodes.at(-1)).end, -1,
-1,
// @ts-ignore // @ts-ignore
node.fragment.nodes node.fragment.nodes
) )

@ -1,4 +1,3 @@
/** @import { Location } from 'locate-character' */
/** @import { Namespace } from '#compiler' */ /** @import { Namespace } from '#compiler' */
/** @import { ComponentClientTransformState } from '../types.js' */ /** @import { ComponentClientTransformState } from '../types.js' */
/** @import { Node } from './types.js' */ /** @import { Node } from './types.js' */
@ -15,7 +14,7 @@ function build_locations(nodes) {
for (const node of nodes) { for (const node of nodes) {
if (node.type !== 'element') continue; if (node.type !== 'element') continue;
const { line, column } = /** @type {Location} */ (locator(node.start)); const { line, column } = locator(node.start);
const expression = b.array([b.literal(line), b.literal(column)]); const expression = b.array([b.literal(line), b.literal(column)]);
const children = build_locations(node.children); const children = build_locations(node.children);

@ -40,22 +40,38 @@ export function BindDirective(node, context) {
validate_binding(context.state, node, expression); validate_binding(context.state, node, expression);
} }
get = b.thunk(expression); const assignment = /** @type {Expression} */ (
context.visit(b.assignment('=', /** @type {Pattern} */ (node.expression), b.id('$$value')))
);
/** @type {Expression | undefined} */ if (dev) {
set = b.unthunk( // in dev, create named functions, so that `$inspect(...)` delivers
b.arrow( // useful stack traces
get = b.function(b.id('get', node.name_loc), [], b.block([b.return(expression)]));
set = b.function(
b.id('set', node.name_loc),
[b.id('$$value')], [b.id('$$value')],
/** @type {Expression} */ ( b.block([b.stmt(assignment)])
context.visit( );
b.assignment('=', /** @type {Pattern} */ (node.expression), b.id('$$value')) } else {
// in prod, optimise for brevity
get = b.thunk(expression);
/** @type {Expression | undefined} */
set = b.unthunk(
b.arrow(
[b.id('$$value')],
/** @type {Expression} */ (
context.visit(
b.assignment('=', /** @type {Pattern} */ (node.expression), b.id('$$value'))
)
) )
) )
) );
);
if (get === set) { if (get === set) {
set = undefined; set = undefined;
}
} }
} }

@ -39,7 +39,8 @@ export function CallExpression(node, context) {
} }
} }
return b.call('$.state', value); const callee = b.id('$.state', node.callee.loc);
return b.call(callee, value);
} }
case '$derived': case '$derived':

@ -1,6 +1,5 @@
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */ /** @import { ComponentContext } from '../types' */
import { regex_is_valid_identifier } from '../../../patterns.js';
import { build_component } from './shared/component.js'; import { build_component } from './shared/component.js';
/** /**
@ -8,6 +7,6 @@ import { build_component } from './shared/component.js';
* @param {ComponentContext} context * @param {ComponentContext} context
*/ */
export function Component(node, context) { export function Component(node, context) {
const component = build_component(node, node.name, context); const component = build_component(node, node.name, node.name_loc, context);
context.state.init.push(component); context.state.init.push(component);
} }

@ -81,7 +81,7 @@ export function Fragment(node, context) {
if (is_single_element) { if (is_single_element) {
const element = /** @type {AST.RegularElement} */ (trimmed[0]); const element = /** @type {AST.RegularElement} */ (trimmed[0]);
const id = b.id(context.state.scope.generate(element.name)); const id = b.id(context.state.scope.generate(element.name), element.name_loc);
context.visit(element, { context.visit(element, {
...state, ...state,

@ -407,6 +407,7 @@ export function RegularElement(node, context) {
const synthetic_node = node.metadata.synthetic_value_node; const synthetic_node = node.metadata.synthetic_value_node;
const synthetic_attribute = create_attribute( const synthetic_attribute = create_attribute(
'value', 'value',
null,
synthetic_node.start, synthetic_node.start,
synthetic_node.end, synthetic_node.end,
[synthetic_node] [synthetic_node]

@ -1,12 +1,13 @@
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */ /** @import { ComponentContext } from '../types' */
import { build_component } from './shared/component.js'; import { build_component } from './shared/component.js';
import * as b from '#compiler/builders';
/** /**
* @param {AST.SvelteComponent} node * @param {AST.SvelteComponent} node
* @param {ComponentContext} context * @param {ComponentContext} context
*/ */
export function SvelteComponent(node, context) { export function SvelteComponent(node, context) {
const component = build_component(node, '$$component', context); const component = build_component(node, '$$component', null, context);
context.state.init.push(component); context.state.init.push(component);
} }

@ -14,7 +14,7 @@ export function SvelteHead(node, context) {
context.state.init.push( context.state.init.push(
b.stmt( b.stmt(
b.call( b.call(
'$.head', b.id('$.head', node.name_loc),
b.literal(hash(filename)), b.literal(hash(filename)),
b.arrow([b.id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.fragment))) b.arrow([b.id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.fragment)))
) )

@ -1,5 +1,6 @@
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../types' */ /** @import { ComponentContext } from '../types' */
import { component_name } from '../../../../state.js';
import { build_component } from './shared/component.js'; import { build_component } from './shared/component.js';
/** /**
@ -7,6 +8,6 @@ import { build_component } from './shared/component.js';
* @param {ComponentContext} context * @param {ComponentContext} context
*/ */
export function SvelteSelf(node, context) { export function SvelteSelf(node, context) {
const component = build_component(node, context.state.analysis.name, context); const component = build_component(node, component_name, node.name_loc, context);
context.state.init.push(component); context.state.init.push(component);
} }

@ -20,7 +20,7 @@ export function TitleElement(node, context) {
const statement = b.stmt( const statement = b.stmt(
b.assignment( b.assignment(
'=', '=',
b.id('$.document.title'), b.member(b.id('$.document'), b.id('title', node.name_loc)),
evaluated.is_known evaluated.is_known
? b.literal(evaluated.value) ? b.literal(evaluated.value)
: evaluated.is_defined : evaluated.is_defined

@ -136,7 +136,8 @@ export function VariableDeclaration(node, context) {
} }
if (is_state) { if (is_state) {
value = b.call('$.state', value); const callee = b.id('$.state', /** @type {CallExpression} */ (init).callee.loc);
value = b.call(callee, value);
if (dev) { if (dev) {
value = b.call('$.tag', value, b.literal(id.name)); value = b.call('$.tag', value, b.literal(id.name));

@ -1,4 +1,4 @@
/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, Statement } from 'estree' */ /** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, SourceLocation, Statement } from 'estree' */
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types.js' */ /** @import { ComponentContext } from '../../types.js' */
import { dev, is_ignored } from '../../../../../state.js'; import { dev, is_ignored } from '../../../../../state.js';
@ -12,10 +12,11 @@ import { determine_slot } from '../../../../../utils/slot.js';
/** /**
* @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node
* @param {string} component_name * @param {string} component_name
* @param {SourceLocation | null} loc
* @param {ComponentContext} context * @param {ComponentContext} context
* @returns {Statement} * @returns {Statement}
*/ */
export function build_component(node, component_name, context) { export function build_component(node, component_name, loc, context) {
/** @type {Expression} */ /** @type {Expression} */
const anchor = context.state.node; const anchor = context.state.node;
@ -259,15 +260,9 @@ export function build_component(node, component_name, context) {
attribute.expression.type === 'Identifier' && attribute.expression.type === 'Identifier' &&
context.state.scope.get(attribute.expression.name)?.kind === 'store_sub'; context.state.scope.get(attribute.expression.name)?.kind === 'store_sub';
// Delay prop pushes so bindings come at the end, to avoid spreads overwriting them const get = is_store_sub
if (is_store_sub) { ? b.get(attribute.name, [b.stmt(b.call('$.mark_store_binding')), b.return(expression)])
push_prop( : b.get(attribute.name, [b.return(expression)]);
b.get(attribute.name, [b.stmt(b.call('$.mark_store_binding')), b.return(expression)]),
true
);
} else {
push_prop(b.get(attribute.name, [b.return(expression)]), true);
}
const assignment = b.assignment( const assignment = b.assignment(
'=', '=',
@ -275,10 +270,16 @@ export function build_component(node, component_name, context) {
b.id('$$value') b.id('$$value')
); );
push_prop( const set = b.set(attribute.name, [
b.set(attribute.name, [b.stmt(/** @type {Expression} */ (context.visit(assignment)))]), b.stmt(/** @type {Expression} */ (context.visit(assignment)))
true ]);
);
get.key.loc = attribute.name_loc;
set.key.loc = attribute.name_loc;
// Delay prop pushes so bindings come at the end, to avoid spreads overwriting them
push_prop(get, true);
push_prop(set, true);
} }
} }
} else if (attribute.type === 'AttachTag') { } else if (attribute.type === 'AttachTag') {
@ -434,16 +435,17 @@ export function build_component(node, component_name, context) {
/** @param {Expression} node_id */ /** @param {Expression} node_id */
let fn = (node_id) => { let fn = (node_id) => {
return b.call( // TODO We can remove this ternary once we remove legacy mode, since in runes mode dynamic components
// TODO We can remove this ternary once we remove legacy mode, since in runes mode dynamic components // will be handled separately through the `$.component` function, and then the component name will
// will be handled separately through the `$.component` function, and then the component name will // always be referenced through just the identifier here.
// always be referenced through just the identifier here. const callee = is_component_dynamic
is_component_dynamic ? b.id(intermediate_name)
? intermediate_name : /** @type {Expression} */ (context.visit(b.member_id(component_name)));
: /** @type {Expression} */ (context.visit(b.member_id(component_name))),
node_id, // line up the `Foo` in `Foo(...)` and `<Foo>` for usable stack traces
props_expression callee.loc = loc;
);
return b.call(callee, node_id, props_expression);
}; };
if (bind_this !== null) { if (bind_this !== null) {

@ -32,7 +32,13 @@ export function visit_event_attribute(node, context) {
} }
context.state.init.push( context.state.init.push(
b.stmt(b.assignment('=', b.member(context.state.node, '__' + event_name), handler)) b.stmt(
b.assignment(
'=',
b.member(context.state.node, b.id('__' + event_name, node.name_loc)),
handler
)
)
); );
} else { } else {
const statement = b.stmt( const statement = b.stmt(
@ -140,7 +146,7 @@ export function build_event_handler(node, metadata, context) {
b.this, b.this,
b.id('$$args'), b.id('$$args'),
b.id(context.state.analysis.name), b.id(context.state.analysis.name),
loc && b.array([b.literal(loc.line), b.literal(loc.column)]), b.array([b.literal(loc.line), b.literal(loc.column)]),
has_side_effects(node) && b.true, has_side_effects(node) && b.true,
remove_parens && b.true remove_parens && b.true
); );

@ -1,4 +1,4 @@
/** @import { Expression } from 'estree' */ /** @import { Expression, Identifier, SourceLocation } from 'estree' */
/** @import { AST } from '#compiler' */ /** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types' */ /** @import { ComponentContext } from '../../types' */
import { cannot_be_set_statically } from '../../../../../../utils.js'; import { cannot_be_set_statically } from '../../../../../../utils.js';
@ -42,13 +42,14 @@ export function process_children(nodes, initial, is_element, context) {
/** /**
* @param {boolean} is_text * @param {boolean} is_text
* @param {string} name * @param {string} name
* @param {SourceLocation | null} [loc]
*/ */
function flush_node(is_text, name) { function flush_node(is_text, name, loc) {
const expression = get_node(is_text); const expression = get_node(is_text);
let id = expression; let id = expression;
if (id.type !== 'Identifier') { if (id.type !== 'Identifier') {
id = b.id(context.state.scope.generate(name)); id = b.id(context.state.scope.generate(name), loc);
context.state.init.push(b.var(id, expression)); context.state.init.push(b.var(id, expression));
} }
@ -109,7 +110,12 @@ export function process_children(nodes, initial, is_element, context) {
) { ) {
node.metadata.is_controlled = true; node.metadata.is_controlled = true;
} else { } else {
const id = flush_node(false, node.type === 'RegularElement' ? node.name : 'node'); const id = flush_node(
false,
node.type === 'RegularElement' ? node.name : 'node',
node.type === 'RegularElement' ? node.name_loc : null
);
child_state = { ...context.state, node: id }; child_state = { ...context.state, node: id };
} }

@ -366,8 +366,8 @@ export function validate_binding(state, binding, expression) {
: b.literal(/** @type {Identifier} */ (expression.property).name) : b.literal(/** @type {Identifier} */ (expression.property).name)
) )
), ),
loc && b.literal(loc.line), b.literal(loc.line),
loc && b.literal(loc.column) b.literal(loc.column)
) )
) )
); );

@ -99,7 +99,7 @@ export function RegularElement(node, context) {
} }
if (dev) { if (dev) {
const location = /** @type {Location} */ (locator(node.start)); const location = locator(node.start);
state.template.push( state.template.push(
b.stmt( b.stmt(
b.call( b.call(

@ -50,7 +50,7 @@ export function SvelteElement(node, context) {
build_element_attributes(node, { ...context, state }, optimiser.transform); build_element_attributes(node, { ...context, state }, optimiser.transform);
if (dev) { if (dev) {
const location = /** @type {Location} */ (locator(node.start)); const location = locator(node.start);
statements.push( statements.push(
b.stmt( b.stmt(
b.call( b.call(

@ -142,7 +142,7 @@ export function build_element_attributes(node, context, transform) {
); );
attributes.push( attributes.push(
create_attribute('checked', -1, -1, [ create_attribute('checked', null, -1, -1, [
{ {
type: 'ExpressionTag', type: 'ExpressionTag',
start: -1, start: -1,
@ -165,7 +165,7 @@ export function build_element_attributes(node, context, transform) {
); );
} else { } else {
attributes.push( attributes.push(
create_attribute(attribute.name, -1, -1, [ create_attribute(attribute.name, null, -1, -1, [
{ {
type: 'ExpressionTag', type: 'ExpressionTag',
start: -1, start: -1,

@ -1,4 +1,4 @@
/** @import { Expression, PrivateIdentifier } from 'estree' */ /** @import { Expression, PrivateIdentifier, SourceLocation } from 'estree' */
/** @import { AST, Binding } from '#compiler' */ /** @import { AST, Binding } from '#compiler' */
import * as b from '#compiler/builders'; import * as b from '#compiler/builders';
@ -47,17 +47,19 @@ export function is_custom_element_node(node) {
/** /**
* @param {string} name * @param {string} name
* @param {SourceLocation | null} name_loc
* @param {number} start * @param {number} start
* @param {number} end * @param {number} end
* @param {AST.Attribute['value']} value * @param {AST.Attribute['value']} value
* @returns {AST.Attribute} * @returns {AST.Attribute}
*/ */
export function create_attribute(name, start, end, value) { export function create_attribute(name, name_loc, start, end, value) {
return { return {
type: 'Attribute', type: 'Attribute',
start, start,
end, end,
name, name,
name_loc,
value, value,
metadata: { metadata: {
delegated: false, delegated: false,

@ -40,19 +40,28 @@ export let dev;
export let runes = false; export let runes = false;
export let locator = getLocator('', { offsetLine: 1 }); /** @type {(index: number) => Location} */
export let locator;
/** @param {string} value */ /** @param {string} value */
export function set_source(value) { export function set_source(value) {
source = value; source = value;
locator = getLocator(source, { offsetLine: 1 });
const l = getLocator(source, { offsetLine: 1 });
locator = (i) => {
const loc = l(i);
if (!loc) throw new Error('An impossible situation occurred');
return loc;
};
} }
/** /**
* @param {AST.SvelteNode & { start?: number | undefined }} node * @param {AST.SvelteNode & { start?: number | undefined }} node
*/ */
export function locate_node(node) { export function locate_node(node) {
const loc = /** @type {Location} */ (locator(/** @type {number} */ (node.start))); const loc = locator(/** @type {number} */ (node.start));
return `${sanitize_location(filename)}:${loc?.line}:${loc.column}`; return `${sanitize_location(filename)}:${loc?.line}:${loc.column}`;
} }
@ -103,7 +112,6 @@ export function reset(state) {
runes = false; runes = false;
component_name = UNKNOWN_FILENAME; component_name = UNKNOWN_FILENAME;
source = ''; source = '';
locator = () => undefined;
filename = (state.filename ?? UNKNOWN_FILENAME).replace(/\\/g, '/'); filename = (state.filename ?? UNKNOWN_FILENAME).replace(/\\/g, '/');
warning_filter = state.warning ?? (() => true); warning_filter = state.warning ?? (() => true);
warnings = []; warnings = [];

@ -13,7 +13,8 @@ import type {
Program, Program,
ChainExpression, ChainExpression,
SimpleCallExpression, SimpleCallExpression,
SequenceExpression SequenceExpression,
SourceLocation
} from 'estree'; } from 'estree';
import type { Scope } from '../phases/scope'; import type { Scope } from '../phases/scope';
import type { _CSS } from './css'; import type { _CSS } from './css';
@ -188,7 +189,7 @@ export namespace AST {
} }
/** An `animate:` directive */ /** An `animate:` directive */
export interface AnimateDirective extends BaseNode { export interface AnimateDirective extends BaseAttribute {
type: 'AnimateDirective'; type: 'AnimateDirective';
/** The 'x' in `animate:x` */ /** The 'x' in `animate:x` */
name: string; name: string;
@ -201,7 +202,7 @@ export namespace AST {
} }
/** A `bind:` directive */ /** A `bind:` directive */
export interface BindDirective extends BaseNode { export interface BindDirective extends BaseAttribute {
type: 'BindDirective'; type: 'BindDirective';
/** The 'x' in `bind:x` */ /** The 'x' in `bind:x` */
name: string; name: string;
@ -217,7 +218,7 @@ export namespace AST {
} }
/** A `class:` directive */ /** A `class:` directive */
export interface ClassDirective extends BaseNode { export interface ClassDirective extends BaseAttribute {
type: 'ClassDirective'; type: 'ClassDirective';
/** The 'x' in `class:x` */ /** The 'x' in `class:x` */
name: 'class'; name: 'class';
@ -230,7 +231,7 @@ export namespace AST {
} }
/** A `let:` directive */ /** A `let:` directive */
export interface LetDirective extends BaseNode { export interface LetDirective extends BaseAttribute {
type: 'LetDirective'; type: 'LetDirective';
/** The 'x' in `let:x` */ /** The 'x' in `let:x` */
name: string; name: string;
@ -239,7 +240,7 @@ export namespace AST {
} }
/** An `on:` directive */ /** An `on:` directive */
export interface OnDirective extends BaseNode { export interface OnDirective extends BaseAttribute {
type: 'OnDirective'; type: 'OnDirective';
/** The 'x' in `on:x` */ /** The 'x' in `on:x` */
name: string; name: string;
@ -263,7 +264,7 @@ export namespace AST {
} }
/** A `style:` directive */ /** A `style:` directive */
export interface StyleDirective extends BaseNode { export interface StyleDirective extends BaseAttribute {
type: 'StyleDirective'; type: 'StyleDirective';
/** The 'x' in `style:x` */ /** The 'x' in `style:x` */
name: string; name: string;
@ -278,7 +279,7 @@ export namespace AST {
// TODO have separate in/out/transition directives // TODO have separate in/out/transition directives
/** A `transition:`, `in:` or `out:` directive */ /** A `transition:`, `in:` or `out:` directive */
export interface TransitionDirective extends BaseNode { export interface TransitionDirective extends BaseAttribute {
type: 'TransitionDirective'; type: 'TransitionDirective';
/** The 'x' in `transition:x` */ /** The 'x' in `transition:x` */
name: string; name: string;
@ -296,7 +297,7 @@ export namespace AST {
} }
/** A `use:` directive */ /** A `use:` directive */
export interface UseDirective extends BaseNode { export interface UseDirective extends BaseAttribute {
type: 'UseDirective'; type: 'UseDirective';
/** The 'x' in `use:x` */ /** The 'x' in `use:x` */
name: string; name: string;
@ -310,6 +311,7 @@ export namespace AST {
export interface BaseElement extends BaseNode { export interface BaseElement extends BaseNode {
name: string; name: string;
name_loc: SourceLocation;
attributes: Array<Attribute | SpreadAttribute | Directive | AttachTag>; attributes: Array<Attribute | SpreadAttribute | Directive | AttachTag>;
fragment: Fragment; fragment: Fragment;
} }
@ -528,9 +530,13 @@ export namespace AST {
}; };
} }
export interface Attribute extends BaseNode { export interface BaseAttribute extends BaseNode {
type: 'Attribute';
name: string; name: string;
name_loc: SourceLocation | null;
}
export interface Attribute extends BaseAttribute {
type: 'Attribute';
/** /**
* Quoted/string values are represented by an array, even if they contain a single expression like `"{x}"` * Quoted/string values are represented by an array, even if they contain a single expression like `"{x}"`
*/ */

@ -262,10 +262,14 @@ export function get(name, body) {
/** /**
* @param {string} name * @param {string} name
* @param {ESTree.SourceLocation | null} [loc]
* @returns {ESTree.Identifier} * @returns {ESTree.Identifier}
*/ */
export function id(name) { export function id(name, loc) {
return { type: 'Identifier', name }; const node = /** @type {ESTree.Identifier} */ ({ type: 'Identifier', name });
if (loc) node.loc = loc;
return node;
} }
/** /**

@ -15,6 +15,18 @@
"end": 20, "end": 20,
"type": "Action", "type": "Action",
"name": "autofocus", "name": "autofocus",
"name_loc": {
"start": {
"line": 1,
"column": 7,
"character": 7
},
"end": {
"line": 1,
"column": 20,
"character": 20
}
},
"expression": null, "expression": null,
"modifiers": [] "modifiers": []
}, },
@ -23,6 +35,18 @@
"end": 34, "end": 34,
"type": "Action", "type": "Action",
"name": "autofocus", "name": "autofocus",
"name_loc": {
"start": {
"line": 1,
"column": 21,
"character": 21
},
"end": {
"line": 1,
"column": 34,
"character": 34
}
},
"expression": null, "expression": null,
"modifiers": [] "modifiers": []
} }
@ -31,4 +55,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 39, "end": 39,
"type": "Action", "type": "Action",
"name": "tooltip", "name": "tooltip",
"name_loc": {
"start": {
"line": 1,
"column": 7,
"character": 7
},
"end": {
"line": 1,
"column": 18,
"character": 18
}
},
"expression": { "expression": {
"type": "CallExpression", "type": "CallExpression",
"start": 21, "start": 21,
@ -73,4 +85,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 28, "end": 28,
"type": "Action", "type": "Action",
"name": "tooltip", "name": "tooltip",
"name_loc": {
"start": {
"line": 1,
"column": 7,
"character": 7
},
"end": {
"line": 1,
"column": 18,
"character": 18
}
},
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 20, "start": 20,
@ -38,4 +50,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 36, "end": 36,
"type": "Action", "type": "Action",
"name": "tooltip", "name": "tooltip",
"name_loc": {
"start": {
"line": 1,
"column": 7,
"character": 7
},
"end": {
"line": 1,
"column": 18,
"character": 18
}
},
"expression": { "expression": {
"type": "Literal", "type": "Literal",
"start": 21, "start": 21,
@ -39,4 +51,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 20, "end": 20,
"type": "Action", "type": "Action",
"name": "autofocus", "name": "autofocus",
"name_loc": {
"start": {
"line": 1,
"column": 7,
"character": 7
},
"end": {
"line": 1,
"column": 20,
"character": 20
}
},
"expression": null, "expression": null,
"modifiers": [] "modifiers": []
} }
@ -23,4 +35,4 @@
} }
] ]
} }
} }

@ -20,6 +20,18 @@
"end": 50, "end": 50,
"type": "Animation", "type": "Animation",
"name": "flip", "name": "flip",
"name_loc": {
"start": {
"line": 2,
"column": 6,
"character": 38
},
"end": {
"line": 2,
"column": 18,
"character": 50
}
},
"expression": null, "expression": null,
"modifiers": [] "modifiers": []
} }
@ -39,6 +51,7 @@
"type": "Identifier", "type": "Identifier",
"name": "thing", "name": "thing",
"start": 17, "start": 17,
"end": 22,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
@ -50,8 +63,7 @@
"column": 22, "column": 22,
"character": 22 "character": 22
} }
}, }
"end": 22
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -88,4 +100,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 22, "end": 22,
"type": "Class", "type": "Class",
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 14,
"character": 14
}
},
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 16, "start": 16,
@ -38,4 +50,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 3, "start": 3,
"end": 30, "end": 30,
"name": "href", "name": "href",
"name_loc": {
"start": {
"line": 1,
"column": 3,
"character": 3
},
"end": {
"line": 1,
"column": 7,
"character": 7
}
},
"value": [ "value": [
{ {
"start": 8, "start": 8,
@ -38,4 +50,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 7, "start": 7,
"end": 15, "end": 15,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 1,
"column": 7,
"character": 7
},
"end": {
"line": 1,
"column": 10,
"character": 10
}
},
"value": [ "value": [
{ {
"start": 11, "start": 11,
@ -52,4 +64,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 10, "start": 10,
"end": 29, "end": 29,
"name": "readonly", "name": "readonly",
"name_loc": {
"start": {
"line": 1,
"column": 10,
"character": 10
},
"end": {
"line": 1,
"column": 18,
"character": 18
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -44,4 +56,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 5, "start": 5,
"end": 28, "end": 28,
"name": "style", "name": "style",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 10,
"character": 10
}
},
"value": [ "value": [
{ {
"start": 12, "start": 12,
@ -80,4 +92,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 5, "start": 5,
"end": 9, "end": 9,
"name": "a", "name": "a",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 6,
"character": 6
}
},
"value": [ "value": [
{ {
"start": 8, "start": 8,
@ -30,6 +42,18 @@
"start": 10, "start": 10,
"end": 16, "end": 16,
"name": "b", "name": "b",
"name_loc": {
"start": {
"line": 1,
"column": 10,
"character": 10
},
"end": {
"line": 1,
"column": 11,
"character": 11
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -60,6 +84,18 @@
"start": 17, "start": 17,
"end": 21, "end": 21,
"name": "c", "name": "c",
"name_loc": {
"start": {
"line": 1,
"column": 17,
"character": 17
},
"end": {
"line": 1,
"column": 18,
"character": 18
}
},
"value": [ "value": [
{ {
"start": 20, "start": 20,
@ -75,6 +111,18 @@
"start": 22, "start": 22,
"end": 30, "end": 30,
"name": "d", "name": "d",
"name_loc": {
"start": {
"line": 1,
"column": 22,
"character": 22
},
"end": {
"line": 1,
"column": 23,
"character": 23
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -105,4 +153,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 5, "start": 5,
"end": 76, "end": 76,
"name": "data-foo", "name": "data-foo",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 13,
"character": 13
}
},
"value": [ "value": [
{ {
"start": 15, "start": 15,
@ -30,4 +42,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 5, "start": 5,
"end": 11, "end": 11,
"name": "id", "name": "id",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 7,
"character": 7
}
},
"value": [ "value": [
{ {
"start": 9, "start": 9,
@ -30,6 +42,18 @@
"start": 12, "start": 12,
"end": 21, "end": 21,
"name": "class", "name": "class",
"name_loc": {
"start": {
"line": 1,
"column": 12,
"character": 12
},
"end": {
"line": 1,
"column": 17,
"character": 17
}
},
"value": [ "value": [
{ {
"start": 19, "start": 19,
@ -45,4 +69,4 @@
} }
] ]
} }
} }

@ -15,16 +15,40 @@
"start": 5, "start": 5,
"end": 9, "end": 9,
"name": "id", "name": "id",
"name_loc": {
"start": {
"line": 1,
"column": 6,
"character": 6
},
"end": {
"line": 1,
"column": 8,
"character": 8
}
},
"value": [ "value": [
{ {
"type": "AttributeShorthand", "type": "AttributeShorthand",
"start": 6, "start": 6,
"end": 8, "end": 8,
"expression": { "expression": {
"type": "Identifier",
"name": "id",
"start": 6, "start": 6,
"end": 8, "end": 8,
"type": "Identifier", "loc": {
"name": "id" "start": {
"line": 1,
"column": 6,
"character": 6
},
"end": {
"line": 1,
"column": 8,
"character": 8
}
}
} }
} }
] ]
@ -34,4 +58,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 10, "start": 10,
"end": 18, "end": 18,
"name": "readonly", "name": "readonly",
"name_loc": {
"start": {
"line": 1,
"column": 10,
"character": 10
},
"end": {
"line": 1,
"column": 18,
"character": 18
}
},
"value": true "value": true
} }
], ],
@ -22,4 +34,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 5, "start": 5,
"end": 16, "end": 16,
"name": "class", "name": "class",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 10,
"character": 10
}
},
"value": [ "value": [
{ {
"start": 12, "start": 12,
@ -30,4 +42,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 36, "end": 36,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 26,
"character": 26
}
},
"modifiers": [ "modifiers": [
"important" "important"
], ],
@ -47,4 +59,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 16, "end": 16,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 16,
"character": 16
}
},
"modifiers": [], "modifiers": [],
"value": true "value": true
} }
@ -23,4 +35,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 22, "end": 22,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 16,
"character": 16
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -47,6 +59,18 @@
"end": 52, "end": 52,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 2,
"column": 5,
"character": 35
},
"end": {
"line": 2,
"column": 16,
"character": 46
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -79,6 +103,18 @@
"end": 80, "end": 80,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 3,
"column": 5,
"character": 65
},
"end": {
"line": 3,
"column": 16,
"character": 76
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -111,6 +147,18 @@
"end": 120, "end": 120,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 4,
"column": 5,
"character": 93
},
"end": {
"line": 4,
"column": 16,
"character": 104
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -164,6 +212,18 @@
"end": 160, "end": 160,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 5,
"column": 5,
"character": 133
},
"end": {
"line": 5,
"column": 16,
"character": 144
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -217,6 +277,18 @@
"end": 198, "end": 198,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 6,
"column": 5,
"character": 173
},
"end": {
"line": 6,
"column": 16,
"character": 184
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -270,6 +342,18 @@
"end": 245, "end": 245,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 7,
"column": 5,
"character": 211
},
"end": {
"line": 7,
"column": 16,
"character": 222
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -359,4 +443,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 26, "end": 26,
"type": "StyleDirective", "type": "StyleDirective",
"name": "color", "name": "color",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 16,
"character": 16
}
},
"modifiers": [], "modifiers": [],
"value": [ "value": [
{ {
@ -45,4 +57,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 5, "start": 5,
"end": 24, "end": 24,
"name": "style", "name": "style",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 10,
"character": 10
}
},
"value": [ "value": [
{ {
"start": 12, "start": 12,
@ -38,4 +50,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 5, "start": 5,
"end": 14, "end": 14,
"name": "class", "name": "class",
"name_loc": {
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 10,
"character": 10
}
},
"value": [ "value": [
{ {
"start": 11, "start": 11,
@ -46,6 +58,18 @@
"start": 25, "start": 25,
"end": 31, "end": 31,
"name": "href", "name": "href",
"name_loc": {
"start": {
"line": 2,
"column": 3,
"character": 25
},
"end": {
"line": 2,
"column": 7,
"character": 29
}
},
"value": [ "value": [
{ {
"start": 30, "start": 30,
@ -85,6 +109,18 @@
"start": 44, "start": 44,
"end": 53, "end": 53,
"name": "href", "name": "href",
"name_loc": {
"start": {
"line": 3,
"column": 3,
"character": 44
},
"end": {
"line": 3,
"column": 7,
"character": 48
}
},
"value": [ "value": [
{ {
"start": 49, "start": 49,
@ -108,4 +144,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 23, "end": 23,
"type": "EventHandler", "type": "EventHandler",
"name": "click", "name": "click",
"name_loc": {
"start": {
"line": 1,
"column": 8,
"character": 8
},
"end": {
"line": 1,
"column": 16,
"character": 16
}
},
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 19, "start": 19,
@ -46,4 +58,4 @@
} }
] ]
} }
} }

@ -29,6 +29,7 @@
"type": "Identifier", "type": "Identifier",
"name": "theError", "name": "theError",
"start": 47, "start": 47,
"end": 55,
"loc": { "loc": {
"start": { "start": {
"line": 3, "line": 3,
@ -40,8 +41,7 @@
"column": 16, "column": 16,
"character": 55 "character": 55
} }
}, }
"end": 55
}, },
"pending": { "pending": {
"type": "PendingBlock", "type": "PendingBlock",
@ -183,4 +183,4 @@
} }
] ]
} }
} }

@ -28,6 +28,7 @@
"type": "Identifier", "type": "Identifier",
"name": "theValue", "name": "theValue",
"start": 46, "start": 46,
"end": 54,
"loc": { "loc": {
"start": { "start": {
"line": 3, "line": 3,
@ -39,13 +40,13 @@
"column": 15, "column": 15,
"character": 54 "character": 54
} }
}, }
"end": 54
}, },
"error": { "error": {
"type": "Identifier", "type": "Identifier",
"name": "theError", "name": "theError",
"start": 96, "start": 96,
"end": 104,
"loc": { "loc": {
"start": { "start": {
"line": 5, "line": 5,
@ -57,8 +58,7 @@
"column": 16, "column": 16,
"character": 104 "character": 104
} }
}, }
"end": 104
}, },
"pending": { "pending": {
"type": "PendingBlock", "type": "PendingBlock",
@ -252,4 +252,4 @@
} }
] ]
} }
} }

@ -22,6 +22,18 @@
"end": 46, "end": 46,
"type": "Binding", "type": "Binding",
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 5,
"column": 8,
"character": 38
},
"end": {
"line": 5,
"column": 16,
"character": 46
}
},
"expression": { "expression": {
"start": 43, "start": 43,
"end": 46, "end": 46,
@ -109,4 +121,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -22,6 +22,18 @@
"end": 55, "end": 55,
"type": "Binding", "type": "Binding",
"name": "value", "name": "value",
"name_loc": {
"start": {
"line": 5,
"column": 7,
"character": 38
},
"end": {
"line": 5,
"column": 17,
"character": 48
}
},
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 50, "start": 50,
@ -119,4 +131,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -82,4 +82,4 @@
"comment": null "comment": null
} }
} }
} }

@ -156,6 +156,18 @@
"start": 263, "start": 263,
"end": 274, "end": 274,
"name": "class", "name": "class",
"name_loc": {
"start": {
"line": 7,
"column": 29,
"character": 263
},
"end": {
"line": 7,
"column": 34,
"character": 268
}
},
"value": [ "value": [
{ {
"start": 270, "start": 270,
@ -171,4 +183,4 @@
} }
] ]
} }
} }

@ -62,6 +62,18 @@
"start": 72, "start": 72,
"end": 83, "end": 83,
"name": "class", "name": "class",
"name_loc": {
"start": {
"line": 2,
"column": 27,
"character": 72
},
"end": {
"line": 2,
"column": 32,
"character": 77
}
},
"value": [ "value": [
{ {
"start": 79, "start": 79,
@ -77,4 +89,4 @@
} }
] ]
} }
} }

@ -481,4 +481,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -266,4 +266,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -44,6 +44,7 @@
"type": "Identifier", "type": "Identifier",
"name": "animal", "name": "animal",
"start": 18, "start": 18,
"end": 24,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
@ -55,8 +56,7 @@
"column": 24, "column": 24,
"character": 24 "character": 24
} }
}, }
"end": 24
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -100,4 +100,4 @@
} }
] ]
} }
} }

@ -72,6 +72,7 @@
"type": "Identifier", "type": "Identifier",
"name": "animal", "name": "animal",
"start": 18, "start": 18,
"end": 24,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
@ -83,8 +84,7 @@
"column": 24, "column": 24,
"character": 24 "character": 24
} }
}, }
"end": 24
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -106,4 +106,4 @@
} }
] ]
} }
} }

@ -44,6 +44,7 @@
"type": "Identifier", "type": "Identifier",
"name": "todo", "name": "todo",
"start": 16, "start": 16,
"end": 20,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
@ -55,8 +56,7 @@
"column": 20, "column": 20,
"character": 20 "character": 20
} }
}, }
"end": 20
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -126,4 +126,4 @@
} }
] ]
} }
} }

@ -44,6 +44,7 @@
"type": "Identifier", "type": "Identifier",
"name": "animal", "name": "animal",
"start": 18, "start": 18,
"end": 24,
"loc": { "loc": {
"start": { "start": {
"line": 1, "line": 1,
@ -55,8 +56,7 @@
"column": 24, "column": 24,
"character": 24 "character": 24
} }
}, }
"end": 24
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -77,4 +77,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 6, "start": 6,
"end": 13, "end": 13,
"name": "attr", "name": "attr",
"name_loc": {
"start": {
"line": 1,
"column": 6,
"character": 6
},
"end": {
"line": 1,
"column": 10,
"character": 10
}
},
"value": [ "value": [
{ {
"start": 12, "start": 12,
@ -46,6 +58,18 @@
"start": 28, "start": 28,
"end": 35, "end": 35,
"name": "attr", "name": "attr",
"name_loc": {
"start": {
"line": 2,
"column": 6,
"character": 28
},
"end": {
"line": 2,
"column": 10,
"character": 32
}
},
"value": [ "value": [
{ {
"start": 34, "start": 34,
@ -61,4 +85,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 6, "start": 6,
"end": 16, "end": 16,
"name": "attr", "name": "attr",
"name_loc": {
"start": {
"line": 1,
"column": 6,
"character": 6
},
"end": {
"line": 1,
"column": 10,
"character": 10
}
},
"value": [ "value": [
{ {
"start": 12, "start": 12,
@ -46,6 +58,18 @@
"start": 31, "start": 31,
"end": 41, "end": 41,
"name": "attr", "name": "attr",
"name_loc": {
"start": {
"line": 2,
"column": 6,
"character": 31
},
"end": {
"line": 2,
"column": 10,
"character": 35
}
},
"value": [ "value": [
{ {
"start": 37, "start": 37,
@ -61,4 +85,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"start": 10, "start": 10,
"end": 14, "end": 14,
"name": "html", "name": "html",
"name_loc": {
"start": {
"line": 1,
"column": 10,
"character": 10
},
"end": {
"line": 1,
"column": 14,
"character": 14
}
},
"value": true "value": true
} }
], ],
@ -22,4 +34,4 @@
} }
] ]
} }
} }

@ -15,6 +15,18 @@
"end": 45, "end": 45,
"type": "EventHandler", "type": "EventHandler",
"name": "click", "name": "click",
"name_loc": {
"start": {
"line": 1,
"column": 8,
"character": 8
},
"end": {
"line": 1,
"column": 16,
"character": 16
}
},
"expression": { "expression": {
"type": "ArrowFunctionExpression", "type": "ArrowFunctionExpression",
"start": 19, "start": 19,
@ -161,4 +173,4 @@
} }
] ]
} }
} }

@ -17,9 +17,21 @@
"end": 92, "end": 92,
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"name": "generic",
"start": 40, "start": 40,
"end": 47, "end": 47,
"name": "generic" "loc": {
"start": {
"line": 4,
"column": 10,
"character": 40
},
"end": {
"line": 4,
"column": 17,
"character": 47
}
}
}, },
"parameters": [ "parameters": [
{ {
@ -123,9 +135,21 @@
"end": 192, "end": 192,
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"name": "complex_generic",
"start": 104, "start": 104,
"end": 119, "end": 119,
"name": "complex_generic" "loc": {
"start": {
"line": 8,
"column": 10,
"character": 104
},
"end": {
"line": 8,
"column": 25,
"character": 119
}
}
}, },
"parameters": [ "parameters": [
{ {
@ -241,4 +265,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -22,6 +22,18 @@
"end": 692, "end": 692,
"type": "EventHandler", "type": "EventHandler",
"name": "click", "name": "click",
"name_loc": {
"start": {
"line": 34,
"column": 1,
"character": 574
},
"end": {
"line": 34,
"column": 9,
"character": 582
}
},
"expression": { "expression": {
"type": "ArrowFunctionExpression", "type": "ArrowFunctionExpression",
"start": 596, "start": 596,
@ -869,4 +881,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -75,9 +75,21 @@
"end": 75, "end": 75,
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"name": "",
"start": 63, "start": 63,
"end": 63, "end": 63,
"name": "" "loc": {
"start": {
"line": 9,
"column": 10,
"character": 63
},
"end": {
"line": 9,
"column": 10,
"character": 63
}
}
}, },
"parameters": [], "parameters": [],
"children": [] "children": []
@ -95,13 +107,25 @@
"end": 102, "end": 102,
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"name": "foo",
"start": 87, "start": 87,
"end": 90, "end": 90,
"name": "foo" "loc": {
"start": {
"line": 12,
"column": 10,
"character": 87
},
"end": {
"line": 12,
"column": 13,
"character": 90
}
}
}, },
"parameters": [], "parameters": [],
"children": [] "children": []
} }
] ]
} }
} }

@ -15,16 +15,40 @@
"start": 5, "start": 5,
"end": 7, "end": 7,
"name": "", "name": "",
"name_loc": {
"start": {
"line": 1,
"column": 6,
"character": 6
},
"end": {
"line": 1,
"column": 6,
"character": 6
}
},
"value": [ "value": [
{ {
"type": "AttributeShorthand", "type": "AttributeShorthand",
"start": 6, "start": 6,
"end": 6, "end": 6,
"expression": { "expression": {
"type": "Identifier",
"name": "",
"start": 6, "start": 6,
"end": 6, "end": 6,
"type": "Identifier", "loc": {
"name": "" "start": {
"line": 1,
"column": 6,
"character": 6
},
"end": {
"line": 1,
"column": 6,
"character": 6
}
}
} }
} }
] ]
@ -50,6 +74,18 @@
"start": 20, "start": 20,
"end": 26, "end": 26,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 2,
"column": 5,
"character": 20
},
"end": {
"line": 2,
"column": 8,
"character": 23
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -85,6 +121,18 @@
"start": 40, "start": 40,
"end": 48, "end": 48,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 4,
"column": 5,
"character": 40
},
"end": {
"line": 4,
"column": 8,
"character": 43
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -120,6 +168,18 @@
"start": 61, "start": 61,
"end": 73, "end": 73,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 5,
"column": 5,
"character": 61
},
"end": {
"line": 5,
"column": 8,
"character": 64
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -155,6 +215,18 @@
"start": 92, "start": 92,
"end": 110, "end": 110,
"name": "onclick", "name": "onclick",
"name_loc": {
"start": {
"line": 6,
"column": 11,
"character": 92
},
"end": {
"line": 6,
"column": 18,
"character": 99
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -190,6 +262,18 @@
"end": 137, "end": 137,
"type": "Binding", "type": "Binding",
"name": "value", "name": "value",
"name_loc": {
"start": {
"line": 8,
"column": 7,
"character": 122
},
"end": {
"line": 8,
"column": 17,
"character": 132
}
},
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 134, "start": 134,
@ -272,6 +356,7 @@
"type": "Identifier", "type": "Identifier",
"name": "item", "name": "item",
"start": 197, "start": 197,
"end": 201,
"loc": { "loc": {
"start": { "start": {
"line": 15, "line": 15,
@ -283,8 +368,7 @@
"column": 20, "column": 20,
"character": 201 "character": 201
} }
}, }
"end": 201
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -325,6 +409,7 @@
"type": "Identifier", "type": "Identifier",
"name": "item", "name": "item",
"start": 234, "start": 234,
"end": 238,
"loc": { "loc": {
"start": { "start": {
"line": 17, "line": 17,
@ -336,8 +421,7 @@
"column": 19, "column": 19,
"character": 238 "character": 238
} }
}, }
"end": 238
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -408,6 +492,7 @@
"type": "Identifier", "type": "Identifier",
"name": "y", "name": "y",
"start": 285, "start": 285,
"end": 286,
"loc": { "loc": {
"start": { "start": {
"line": 21, "line": 21,
@ -419,8 +504,7 @@
"column": 17, "column": 17,
"character": 286 "character": 286
} }
}, }
"end": 286
}, },
"error": null, "error": null,
"pending": { "pending": {
@ -467,6 +551,7 @@
"type": "Identifier", "type": "Identifier",
"name": "y", "name": "y",
"start": 314, "start": 314,
"end": 315,
"loc": { "loc": {
"start": { "start": {
"line": 23, "line": 23,
@ -478,8 +563,7 @@
"column": 18, "column": 18,
"character": 315 "character": 315
} }
}, }
"end": 315
}, },
"pending": { "pending": {
"type": "PendingBlock", "type": "PendingBlock",
@ -505,4 +589,4 @@
} }
] ]
} }
} }

@ -240,6 +240,7 @@
"type": "Identifier", "type": "Identifier",
"name": "y", "name": "y",
"start": 138, "start": 138,
"end": 139,
"loc": { "loc": {
"start": { "start": {
"line": 19, "line": 19,
@ -251,8 +252,7 @@
"column": 13, "column": 13,
"character": 139 "character": 139
} }
}, }
"end": 139
}, },
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
@ -273,4 +273,4 @@
} }
] ]
} }
} }

@ -29,6 +29,18 @@
"start": 13, "start": 13,
"end": 22, "end": 22,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 2,
"column": 7,
"character": 13
},
"end": {
"line": 2,
"column": 10,
"character": 16
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -90,6 +102,18 @@
"start": 44, "start": 44,
"end": 53, "end": 53,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 6,
"column": 7,
"character": 44
},
"end": {
"line": 6,
"column": 10,
"character": 47
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -158,6 +182,18 @@
"start": 79, "start": 79,
"end": 88, "end": 88,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 10,
"column": 7,
"character": 79
},
"end": {
"line": 10,
"column": 10,
"character": 82
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -226,6 +262,18 @@
"start": 113, "start": 113,
"end": 122, "end": 122,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 14,
"column": 7,
"character": 113
},
"end": {
"line": 14,
"column": 10,
"character": 116
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -317,6 +365,18 @@
"start": 161, "start": 161,
"end": 170, "end": 170,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 20,
"column": 5,
"character": 161
},
"end": {
"line": 20,
"column": 8,
"character": 164
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -346,4 +406,4 @@
} }
] ]
} }
} }

@ -68,6 +68,18 @@
"start": 35, "start": 35,
"end": 44, "end": 44,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 6,
"column": 7,
"character": 35
},
"end": {
"line": 6,
"column": 10,
"character": 38
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -275,6 +287,18 @@
"start": 159, "start": 159,
"end": 168, "end": 168,
"name": "foo", "name": "foo",
"name_loc": {
"start": {
"line": 26,
"column": 7,
"character": 159
},
"end": {
"line": 26,
"column": 10,
"character": 162
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -360,4 +384,4 @@
} }
] ]
} }
} }

@ -119,6 +119,7 @@
"type": "Identifier", "type": "Identifier",
"name": "f", "name": "f",
"start": 97, "start": 97,
"end": 98,
"loc": { "loc": {
"start": { "start": {
"line": 13, "line": 13,
@ -130,8 +131,7 @@
"column": 8, "column": 8,
"character": 98 "character": 98
} }
}, }
"end": 98
}, },
"error": null, "error": null,
"pending": { "pending": {
@ -219,6 +219,7 @@
"type": "Identifier", "type": "Identifier",
"name": "f", "name": "f",
"start": 137, "start": 137,
"end": 138,
"loc": { "loc": {
"start": { "start": {
"line": 18, "line": 18,
@ -230,8 +231,7 @@
"column": 8, "column": 8,
"character": 138 "character": 138
} }
}, }
"end": 138
}, },
"error": null, "error": null,
"pending": { "pending": {
@ -289,4 +289,4 @@
} }
] ]
} }
} }

@ -22,6 +22,18 @@
"end": 53, "end": 53,
"type": "Binding", "type": "Binding",
"name": "this", "name": "this",
"name_loc": {
"start": {
"line": 5,
"column": 8,
"character": 38
},
"end": {
"line": 5,
"column": 17,
"character": 47
}
},
"expression": { "expression": {
"type": "Identifier", "type": "Identifier",
"start": 49, "start": 49,
@ -119,4 +131,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -147,4 +147,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -176,4 +176,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -147,4 +147,4 @@
"sourceType": "module" "sourceType": "module"
} }
} }
} }

@ -69,6 +69,18 @@
"start": 30, "start": 30,
"end": 49, "end": 49,
"name": "depth", "name": "depth",
"name_loc": {
"start": {
"line": 2,
"column": 14,
"character": 30
},
"end": {
"line": 2,
"column": 19,
"character": 35
}
},
"value": [ "value": [
{ {
"type": "MustacheTag", "type": "MustacheTag",
@ -133,4 +145,4 @@
} }
] ]
} }
} }

@ -22,6 +22,18 @@
"start": 16, "start": 16,
"end": 26, "end": 26,
"name": "slot", "name": "slot",
"name_loc": {
"start": {
"line": 1,
"column": 16,
"character": 16
},
"end": {
"line": 1,
"column": 20,
"character": 20
}
},
"value": [ "value": [
{ {
"start": 22, "start": 22,
@ -39,4 +51,4 @@
} }
] ]
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save