put locations on template, instead of on the side

pull/15538/head
Rich Harris 4 months ago
parent af7846518c
commit 40be734f94

@ -170,8 +170,7 @@ export function client_component(analysis, options) {
update: /** @type {any} */ (null),
expressions: /** @type {any} */ (null),
after_update: /** @type {any} */ (null),
template: /** @type {any} */ (null),
locations: /** @type {any} */ (null)
template: /** @type {any} */ (null)
};
const module = /** @type {ESTree.Program} */ (

@ -1,7 +1,8 @@
/** @import { ComponentClientTransformState } from '../types.js' */
/** @import { Location } from 'locate-character' */
/** @import { Namespace } from '#compiler' */
/** @import { SourceLocation } from '#shared' */
import { dev } from '../../../../state.js';
/** @import { ComponentClientTransformState } from '../types.js' */
/** @import { Node } from './types.js' */
import { dev, locator } from '../../../../state.js';
import * as b from '../../../../utils/builders.js';
import { template_to_functions } from './to-functions.js';
import { template_to_string } from './to-string.js';
@ -28,20 +29,27 @@ function get_template_function(namespace, state) {
}
/**
* @param {SourceLocation[]} locations
* @param {Node[]} nodes
*/
function build_locations(locations) {
return b.array(
locations.map((loc) => {
const expression = b.array([b.literal(loc[0]), b.literal(loc[1])]);
function build_locations(nodes) {
const array = b.array([]);
for (const node of nodes) {
if (node.type !== 'element') continue;
const { line, column } = /** @type {Location} */ (locator(node.start));
if (loc.length === 3) {
expression.elements.push(build_locations(loc[2]));
const expression = b.array([b.literal(line), b.literal(column)]);
const children = build_locations(node.children);
if (children.elements.length > 0) {
expression.elements.push(children);
}
return expression;
})
);
array.elements.push(expression);
}
return array;
}
/**
@ -66,7 +74,7 @@ export function transform_template(state, namespace, flags) {
'$.add_locations',
call,
b.member(b.id(state.analysis.name), '$.FILENAME', true),
build_locations(state.locations)
build_locations(state.template.nodes)
);
}

@ -22,13 +22,17 @@ export class Template {
#fragment = this.nodes;
/** @param {string} name */
create_element(name) {
/**
* @param {string} name
* @param {number} start
*/
create_element(name, start) {
this.#element = {
type: 'element',
name,
attributes: {},
children: []
children: [],
start
};
this.#fragment.push(this.#element);

@ -5,6 +5,8 @@ export interface Element {
name: string;
attributes: Record<string, string | undefined>;
children: Node[];
/** used for populating __svelte_meta */
start: number;
}
export interface Text {

@ -3,16 +3,14 @@ import type {
Statement,
LabeledStatement,
Identifier,
PrivateIdentifier,
Expression,
AssignmentExpression,
UpdateExpression,
VariableDeclaration
} from 'estree';
import type { AST, Namespace, StateField, ValidatedCompileOptions } from '#compiler';
import type { AST, Namespace, ValidatedCompileOptions } from '#compiler';
import type { TransformState } from '../types.js';
import type { ComponentAnalysis } from '../../types.js';
import type { SourceLocation } from '#shared';
import type { Template } from './transform-template/template.js';
export interface ClientTransformState extends TransformState {
@ -55,7 +53,6 @@ export interface ComponentClientTransformState extends ClientTransformState {
readonly expressions: Expression[];
/** The HTML template string */
readonly template: Template;
readonly locations: SourceLocation[];
readonly metadata: {
namespace: Namespace;
bound_contenteditable: boolean;

@ -67,7 +67,6 @@ export function Fragment(node, context) {
expressions: [],
after_update: [],
template: new Template(),
locations: [],
transform: { ...context.state.transform },
metadata: {
namespace,

@ -1,17 +1,14 @@
/** @import { ArrayExpression, Expression, ExpressionStatement, Identifier, MemberExpression, ObjectExpression } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { SourceLocation } from '#shared' */
/** @import { ComponentClientTransformState, ComponentContext } from '../types' */
/** @import { Scope } from '../../../scope' */
import {
cannot_be_set_statically,
is_boolean_attribute,
is_dom_property,
is_load_error_element,
is_void
is_load_error_element
} from '../../../../../utils.js';
import { escape_html } from '../../../../../escaping.js';
import { dev, is_ignored, locator } from '../../../../state.js';
import { is_ignored } from '../../../../state.js';
import { is_event_attribute, is_text_attribute } from '../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { is_custom_element_node } from '../../../nodes.js';
@ -39,20 +36,9 @@ import { visit_event_attribute } from './shared/events.js';
* @param {ComponentContext} context
*/
export function RegularElement(node, context) {
/** @type {SourceLocation} */
let location = [-1, -1];
if (dev) {
const loc = locator(node.start);
if (loc) {
location[0] = loc.line;
location[1] = loc.column;
context.state.locations.push(location);
}
}
context.state.template.create_element(node.name, node.start);
if (node.name === 'noscript') {
context.state.template.create_element('noscript');
return;
}
@ -68,8 +54,6 @@ export function RegularElement(node, context) {
context.state.template.contains_script_tag ||= node.name === 'script';
context.state.template.create_element(node.name);
/** @type {Array<AST.Attribute | AST.SpreadAttribute>} */
const attributes = [];
@ -345,7 +329,6 @@ export function RegularElement(node, context) {
const state = {
...context.state,
metadata,
locations: [],
scope: /** @type {Scope} */ (context.state.scopes.get(node.fragment)),
preserve_whitespace:
context.state.preserve_whitespace || node.name === 'pre' || node.name === 'textarea'
@ -439,10 +422,6 @@ export function RegularElement(node, context) {
context.state.update.push(b.stmt(b.assignment('=', dir, dir)));
}
if (state.locations.length > 0) {
// @ts-expect-error
location.push(state.locations);
}
context.state.template.pop_element();
}

@ -1,7 +1,7 @@
/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, Statement } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { ComponentContext } from '../../types.js' */
import { dev, is_ignored, locator } from '../../../../../state.js';
import { dev, is_ignored } from '../../../../../state.js';
import { get_attribute_chunks, object } from '../../../../../utils/ast.js';
import * as b from '#compiler/builders';
import { build_bind_this, memoize_expression, validate_binding } from '../shared/utils.js';
@ -440,19 +440,12 @@ export function build_component(node, component_name, context, anchor = context.
}
if (Object.keys(custom_css_props).length > 0) {
if (dev) {
const loc = locator(node.start);
if (loc) {
context.state.locations.push([loc.line, loc.column]);
}
}
if (context.state.metadata.namespace === 'svg') {
// this boils down to <g><!></g>
context.state.template.create_element('g');
context.state.template.create_element('g', node.start);
} else {
// this boils down to <svelte-css-wrapper style='display: contents'><!></svelte-css-wrapper>
context.state.template.create_element('svelte-css-wrapper');
context.state.template.create_element('svelte-css-wrapper', node.start);
context.state.template.set_prop('style', 'display: contents');
}

@ -1,4 +1,4 @@
/** @import { SourceLocation } from '#shared' */
/** @import { SourceLocation } from '#client' */
import { HYDRATION_END, HYDRATION_START, HYDRATION_START_ELSE } from '../../../constants.js';
import { hydrating } from '../dom/hydration.js';

@ -183,4 +183,8 @@ export type ProxyStateObject<T = Record<string | symbol, any>> = T & {
[STATE_SYMBOL]: T;
};
export type SourceLocation =
| [line: number, column: number]
| [line: number, column: number, SourceLocation[]];
export * from './reactivity/types';

@ -3,10 +3,6 @@ export type Store<V> = {
set(value: V): void;
};
export type SourceLocation =
| [line: number, column: number]
| [line: number, column: number, SourceLocation[]];
export type Getters<T> = {
[K in keyof T]: () => T[K];
};

Loading…
Cancel
Save