merge local branches (#16757)

* use fragment as async hoist boundary

* remove async_hoist_boundary

* only dewaterfall when necessary

* unused

* simplify/fix

* de-waterfall awaits in separate elements

* update snapshots

* remove unnecessary wrapper

* fix

* fix

* remove suspends_without_fallback

---------

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/16762/head
Elliott Johnson 6 days ago committed by GitHub
parent 127c5a73cb
commit 49241764bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -1,4 +1,5 @@
/** @import { AST } from '#compiler' */
import * as b from '#compiler/builders';
/**
* @param {any} transparent
@ -13,7 +14,7 @@ export function create_fragment(transparent = false) {
dynamic: false,
has_await: false,
// name is added later, after we've done scope analysis
hoisted_promises: { name: '', promises: [] }
hoisted_promises: { id: b.id('$$promises'), promises: [] }
}
};
}

@ -131,9 +131,6 @@ const visitors = {
ignore_map.set(node, structuredClone(ignore_stack));
const scope = state.scopes.get(node);
if (node.type === 'Fragment') {
node.metadata.hoisted_promises.name = state.scope.generate('promises');
}
next(scope !== undefined && scope !== state.scope ? { ...state, scope } : state);
if (ignores.length > 0) {
@ -309,8 +306,7 @@ export function analyze_module(source, options) {
title: null,
boundary: null,
parent_element: null,
reactive_statement: null,
async_hoist_boundary: null
reactive_statement: null
},
visitors
);
@ -547,7 +543,6 @@ export function analyze_component(root, source, options) {
snippet_renderers: new Map(),
snippets: new Set(),
async_deriveds: new Set(),
suspends_without_fallback: false,
hoisted_promises: new Map()
};
@ -709,8 +704,7 @@ export function analyze_component(root, source, options) {
expression: null,
state_fields: new Map(),
function_depth: scope.function_depth,
reactive_statement: null,
async_hoist_boundary: ast === template.ast ? ast : null
reactive_statement: null
};
walk(/** @type {AST.SvelteNode} */ (ast), state, visitors);
@ -779,8 +773,7 @@ export function analyze_component(root, source, options) {
component_slots: new Set(),
expression: null,
state_fields: new Map(),
function_depth: scope.function_depth,
async_hoist_boundary: ast === template.ast ? ast : null
function_depth: scope.function_depth
};
walk(/** @type {AST.SvelteNode} */ (ast), state, visitors);

@ -11,14 +11,6 @@ export interface AnalysisState {
fragment: AST.Fragment | null;
title: AST.TitleElement | null;
boundary: AST.SvelteBoundary | null;
/**
* The "anchor" fragment for any hoisted promises. This is the root fragment when
* walking starts and until another boundary fragment is encountered, like a
* consequent or alternate of an `#if` or `#each` block. When this fragment is emitted
* during server transformation, the promise expressions will be hoisted out of the fragment
* and placed right above it in an array.
*/
async_hoist_boundary: AST.Fragment | null;
/**
* Tag name of the parent element. `null` if the parent is `svelte:element`, `#snippet`, a component or the root.
* Parent doesn't necessarily mean direct path predecessor because there could be `#each`, `#if` etc in-between.

@ -44,22 +44,7 @@ export function AwaitBlock(node, context) {
// this one doesn't get the new state because it still hoists to the existing scope
context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
if (node.pending) {
context.visit(node.pending, {
...context.state,
async_hoist_boundary: node.pending
});
}
if (node.then) {
context.visit(node.then, {
...context.state,
async_hoist_boundary: node.then
});
}
if (node.catch) {
context.visit(node.catch, {
...context.state,
async_hoist_boundary: node.catch
});
}
if (node.pending) context.visit(node.pending);
if (node.then) context.visit(node.then);
if (node.catch) context.visit(node.catch);
}

@ -17,17 +17,11 @@ export function AwaitExpression(node, context) {
context.state.fragment.metadata.has_await = true;
}
if (context.state.async_hoist_boundary) {
const len = context.state.async_hoist_boundary.metadata.hoisted_promises.promises.push(
node.argument
);
if (context.state.fragment) {
const len = context.state.fragment.metadata.hoisted_promises.promises.push(node.argument);
context.state.analysis.hoisted_promises.set(
node.argument,
b.member(
b.id(context.state.async_hoist_boundary.metadata.hoisted_promises.name),
b.literal(len - 1),
true
)
b.member(context.state.fragment.metadata.hoisted_promises.id, b.literal(len - 1), true)
);
}
@ -48,8 +42,6 @@ export function AwaitExpression(node, context) {
if (!context.state.analysis.runes) {
e.legacy_await_invalid(node);
}
context.state.analysis.suspends_without_fallback ||= !context.state.boundary?.metadata.pending;
}
context.next();

@ -35,16 +35,10 @@ export function EachBlock(node, context) {
scope: /** @type {Scope} */ (context.state.scope.parent)
});
context.visit(node.body, {
...context.state,
async_hoist_boundary: node.body
});
context.visit(node.body);
if (node.key) context.visit(node.key);
if (node.fallback) {
context.visit(node.fallback, {
...context.state,
async_hoist_boundary: node.fallback
});
context.visit(node.fallback);
}
if (!context.state.analysis.runes) {

@ -7,4 +7,16 @@
*/
export function Fragment(node, context) {
context.next({ ...context.state, fragment: node });
// TODO this indicates whether the fragment contains an `await` expression (not inside
// a child fragment), which is necessary for ensuring that a `SnippetBlock` creates an
// async function in SSR. It feels like this is probably duplicative, but it's late
// and it works, so for now I'm doing it like this
node.metadata.is_async = node.metadata.hoisted_promises.promises.length > 0;
if (node.metadata.hoisted_promises.promises.length === 1) {
// if there's only one promise in this fragment, we don't need to de-waterfall it
context.state.analysis.hoisted_promises.delete(node.metadata.hoisted_promises.promises[0]);
node.metadata.hoisted_promises.promises.length = 0;
}
}

@ -22,14 +22,8 @@ export function IfBlock(node, context) {
expression: node.metadata.expression
});
context.visit(node.consequent, {
...context.state,
async_hoist_boundary: node.consequent
});
context.visit(node.consequent);
if (node.alternate) {
context.visit(node.alternate, {
...context.state,
async_hoist_boundary: node.alternate
});
context.visit(node.alternate);
}
}

@ -17,9 +17,5 @@ export function KeyBlock(node, context) {
mark_subtree_dynamic(context.path);
context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
context.visit(node.fragment, {
...context.state,
async_hoist_boundary: node.fragment
});
context.visit(node.fragment);
}

@ -23,11 +23,7 @@ export function SnippetBlock(node, context) {
}
}
context.next({
...context.state,
parent_element: null,
async_hoist_boundary: node.body
});
context.next({ ...context.state, parent_element: null });
const can_hoist =
context.path.length === 1 &&

@ -34,9 +34,5 @@ export function SvelteBoundary(node, context) {
)
) ?? null;
context.next({
...context.state,
boundary: node,
async_hoist_boundary: node.fragment
});
context.next({ ...context.state, boundary: node });
}

@ -238,16 +238,15 @@ export function server_component(analysis, options) {
template.body.push(b.stmt(b.call('$.bind_props', b.id('$$props'), b.object(props))));
}
const component_block = b.block([
call_child_payload(
b.block([
.../** @type {Statement[]} */ (instance.body),
.../** @type {Statement[]} */ (template.body)
]),
analysis.suspends_without_fallback
)
let component_block = b.block([
.../** @type {Statement[]} */ (instance.body),
.../** @type {Statement[]} */ (template.body)
]);
if (analysis.instance.has_await) {
component_block = b.block([call_child_payload(component_block, true)]);
}
// trick esrap into including comments
component_block.loc = instance.loc;

@ -1,4 +1,5 @@
/** @import { AST } from '#compiler' */
/** @import { Statement } from 'estree' */
/** @import { ComponentContext, ComponentServerTransformState } from '../types.js' */
import { clean_nodes, infer_namespace } from '../../utils.js';
import * as b from '#compiler/builders';
@ -47,15 +48,20 @@ export function Fragment(node, context) {
process_children(trimmed, { ...context, state });
if (node.metadata.hoisted_promises.promises.length > 0) {
return b.block([
b.const(
node.metadata.hoisted_promises.name,
b.array(node.metadata.hoisted_promises.promises)
),
...state.init,
call_child_payload(b.block(build_template(state.template)), true)
]);
if (node.metadata.is_async) {
/** @type {Statement[]} */
const statements = [];
if (node.metadata.hoisted_promises.promises.length > 0) {
statements.push(
b.const(node.metadata.hoisted_promises.id, b.array(node.metadata.hoisted_promises.promises))
);
}
statements.push(...state.init);
statements.push(...build_template(state.template));
return b.block([call_child_payload(b.block(statements), true)]);
}
return b.block([...state.init, ...build_template(state.template)]);

@ -78,6 +78,7 @@ export function RegularElement(node, context) {
}
let select_with_value = false;
let select_with_value_async = false;
const template_start = state.template.length;
if (node.name === 'select') {
@ -86,8 +87,12 @@ export function RegularElement(node, context) {
(attribute.type === 'Attribute' || attribute.type === 'BindDirective') &&
attribute.name === 'value'
);
if (node.attributes.some((attribute) => attribute.type === 'SpreadAttribute')) {
const spread = node.attributes.find((attribute) => attribute.type === 'SpreadAttribute');
if (spread) {
select_with_value = true;
select_with_value_async ||= spread.metadata.expression.has_await;
state.template.push(
b.stmt(
b.assignment(
@ -113,6 +118,13 @@ export function RegularElement(node, context) {
);
} else if (value) {
select_with_value = true;
if (value.type === 'Attribute' && value.value !== true) {
select_with_value_async ||= (Array.isArray(value.value) ? value.value : [value.value]).some(
(tag) => tag.type === 'ExpressionTag' && tag.metadata.expression.has_await
);
}
const left = b.id('$$payload.local.select_value');
if (value.type === 'Attribute') {
state.template.push(
@ -164,7 +176,7 @@ export function RegularElement(node, context) {
b.arrow(
[b.id('$$payload')],
b.block([...inner_state.init, ...build_template(inner_state.template)]),
context.state.analysis.suspends_without_fallback
node.fragment.metadata.is_async
)
)
)
@ -192,7 +204,11 @@ export function RegularElement(node, context) {
)
);
} else {
process_children(trimmed, { ...context, state });
if (node.fragment.metadata.is_async) {
state.template.push(/** @type {Statement} */ (context.visit(node.fragment)));
} else {
process_children(trimmed, { ...context, state });
}
}
if (select_with_value) {
@ -208,7 +224,7 @@ export function RegularElement(node, context) {
// TODO this will always produce correct results (because it will produce an async function if the surrounding component is async)
// but it will false-positive and create unnecessary async functions (eg. when the component is async but the select element is not)
// we could probably optimize by checking if the select element is async. Might be worth it.
context.state.analysis.suspends_without_fallback
select_with_value_async
)
);
}

@ -12,7 +12,8 @@ export function SnippetBlock(node, context) {
let fn = b.function_declaration(
node.expression,
[b.id('$$payload'), ...node.parameters],
/** @type {BlockStatement} */ (context.visit(node.body))
/** @type {BlockStatement} */ (context.visit(node.body)),
node.body.metadata.is_async
);
// @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone

@ -15,9 +15,7 @@ export function SvelteHead(node, context) {
b.call(
'$.head',
b.id('$$payload'),
// same thing as elsewhere; this will create more async functions than necessary but should never be _wrong_
// because the component rendering this head block will always be async if the head block is async
b.arrow([b.id('$$payload')], block, context.state.analysis.suspends_without_fallback)
b.arrow([b.id('$$payload')], block, node.fragment.metadata.is_sync)
)
)
);

@ -8,6 +8,15 @@ import { process_children, build_template, call_child_payload } from './shared/u
* @param {ComponentContext} context
*/
export function TitleElement(node, context) {
if (node.fragment.metadata.hoisted_promises.promises.length > 0) {
context.state.init.push(
b.const(
node.fragment.metadata.hoisted_promises.name,
b.array(node.fragment.metadata.hoisted_promises.promises)
)
);
}
// title is guaranteed to contain only text/expression tag children
const template = [b.literal('<title>')];
process_children(node.fragment.nodes, { ...context, state: { ...context.state, template } });

@ -233,9 +233,7 @@ export function build_inline_component(node, expression, context) {
// if the current component is an async component, but it may produce async functions where they're
// not necessary -- eg. when the component is asynchronous but the child content is not.
// May or may not be worth optimizing.
b.block([
call_child_payload(b.block(block.body), context.state.analysis.suspends_without_fallback)
])
b.block([call_child_payload(b.block(block.body), node.fragment.metadata.is_async)])
);
if (slot_name === 'default' && !has_children_prop) {

@ -107,8 +107,6 @@ export interface ComponentAnalysis extends Analysis {
* Every snippet that is declared locally
*/
snippets: Set<AST.SnippetBlock>;
/** Whether the component uses `await` in a context that causes suspense outside of any boundary with a pending snippet. */
suspends_without_fallback: boolean;
hoisted_promises: Map<Expression, MemberExpression>;
}

@ -57,7 +57,7 @@ export namespace AST {
*/
dynamic: boolean;
has_await: boolean;
hoisted_promises: { name: string; promises: Expression[] };
hoisted_promises: { id: Identifier; promises: Expression[] };
};
}

@ -2,32 +2,26 @@ import * as $ from 'svelte/internal/server';
export default function Async_each_fallback_hoisting($$payload) {
$$payload.child(async ($$payload) => {
const promises = [Promise.resolve([])];
const each_array = $.ensure_array_like(await promises[0]);
const each_array = $.ensure_array_like(await Promise.resolve([]));
$$payload.child(async ($$payload) => {
if (each_array.length !== 0) {
$$payload.push('<!--[-->');
if (each_array.length !== 0) {
$$payload.push('<!--[-->');
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
const promises_1 = [Promise.reject('This should never be reached')];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await promises_1[0])}`);
});
}
} else {
$$payload.push('<!--[!-->');
const promises_2 = [Promise.resolve(4)];
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await promises_2[0])}`);
$$payload.push(`<!---->${$.escape(await Promise.reject('This should never be reached'))}`);
});
}
} else {
$$payload.push('<!--[!-->');
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await Promise.resolve(4))}`);
});
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
});
}

@ -1,26 +1,23 @@
import * as $ from 'svelte/internal/server';
export default function Async_each_hoisting($$payload) {
const first = Promise.resolve(1);
const second = Promise.resolve(2);
const third = Promise.resolve(3);
$$payload.child(async ($$payload) => {
const first = Promise.resolve(1);
const second = Promise.resolve(2);
const third = Promise.resolve(3);
const promises = [Promise.resolve([first, second, third])];
const each_array = $.ensure_array_like(await promises[0]);
const each_array = $.ensure_array_like(await Promise.resolve([first, second, third]));
$$payload.child(async ($$payload) => {
$$payload.push(`<!--[-->`);
$$payload.push(`<!--[-->`);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
const promises_1 = [item];
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await promises_1[0])}`);
});
}
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await item)}`);
});
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
});
}

@ -2,28 +2,20 @@ import * as $ from 'svelte/internal/server';
export default function Async_if_alternate_hoisting($$payload) {
$$payload.child(async ($$payload) => {
const promises = [Promise.resolve(false)];
if (await Promise.resolve(false)) {
$$payload.push('<!--[-->');
$$payload.child(async ($$payload) => {
if (await promises[0]) {
$$payload.push('<!--[-->');
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await Promise.reject('no no no'))}`);
});
} else {
$$payload.push('<!--[!-->');
const promises_1 = [Promise.reject('no no no')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await Promise.resolve('yes yes yes'))}`);
});
}
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_1[0])}`);
});
} else {
$$payload.push('<!--[!-->');
const promises_2 = [Promise.resolve('yes yes yes')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_2[0])}`);
});
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
});
}

@ -2,28 +2,20 @@ import * as $ from 'svelte/internal/server';
export default function Async_if_hoisting($$payload) {
$$payload.child(async ($$payload) => {
const promises = [Promise.resolve(true)];
if (await Promise.resolve(true)) {
$$payload.push('<!--[-->');
$$payload.child(async ($$payload) => {
if (await promises[0]) {
$$payload.push('<!--[-->');
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await Promise.resolve('yes yes yes'))}`);
});
} else {
$$payload.push('<!--[!-->');
const promises_1 = [Promise.resolve('yes yes yes')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await Promise.reject('no no no'))}`);
});
}
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_1[0])}`);
});
} else {
$$payload.push('<!--[!-->');
const promises_2 = [Promise.reject('no no no')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_2[0])}`);
});
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
});
}

@ -1,16 +1,14 @@
import * as $ from 'svelte/internal/server';
export default function Await_block_scope($$payload) {
$$payload.child(($$payload) => {
let counter = { count: 0 };
const promise = Promise.resolve(counter);
let counter = { count: 0 };
const promise = Promise.resolve(counter);
function increment() {
counter.count += 1;
}
function increment() {
counter.count += 1;
}
$$payload.push(`<button>clicks: ${$.escape(counter.count)}</button> `);
$.await($$payload, promise, () => {}, (counter) => {});
$$payload.push(`<!--]--> ${$.escape(counter.count)}`);
});
$$payload.push(`<button>clicks: ${$.escape(counter.count)}</button> `);
$.await($$payload, promise, () => {}, (counter) => {});
$$payload.push(`<!--]--> ${$.escape(counter.count)}`);
}

@ -6,33 +6,31 @@ function snippet($$payload) {
}
export default function Bind_component_snippet($$payload) {
$$payload.child(($$payload) => {
let value = '';
const _snippet = snippet;
let $$settled = true;
let $$inner_payload;
let value = '';
const _snippet = snippet;
let $$settled = true;
let $$inner_payload;
function $$render_inner($$payload) {
TextInput($$payload, {
get value() {
return value;
},
function $$render_inner($$payload) {
TextInput($$payload, {
get value() {
return value;
},
set value($$value) {
value = $$value;
$$settled = false;
}
});
set value($$value) {
value = $$value;
$$settled = false;
}
});
$$payload.push(`<!----> value: ${$.escape(value)}`);
}
$$payload.push(`<!----> value: ${$.escape(value)}`);
}
do {
$$settled = true;
$$inner_payload = $$payload.copy();
$$render_inner($$inner_payload);
} while (!$$settled);
do {
$$settled = true;
$$inner_payload = $$payload.copy();
$$render_inner($$inner_payload);
} while (!$$settled);
$$payload.subsume($$inner_payload);
});
$$payload.subsume($$inner_payload);
}

@ -1,7 +1,5 @@
import * as $ from 'svelte/internal/server';
export default function Bind_this($$payload) {
$$payload.child(($$payload) => {
Foo($$payload, {});
});
Foo($$payload, {});
}

@ -3,38 +3,36 @@ import * as $ from 'svelte/internal/server';
export default function Class_state_field_constructor_assignment($$payload, $$props) {
$.push();
$$payload.child(($$payload) => {
class Foo {
a = 0;
#b;
#foo = $.derived(() => ({ bar: this.a * 2 }));
get foo() {
return this.#foo();
}
set foo($$value) {
return this.#foo($$value);
}
#bar = $.derived(() => ({ baz: this.foo }));
get bar() {
return this.#bar();
}
set bar($$value) {
return this.#bar($$value);
}
constructor() {
this.a = 1;
this.#b = 2;
this.foo.bar = 3;
this.bar = 4;
}
class Foo {
a = 0;
#b;
#foo = $.derived(() => ({ bar: this.a * 2 }));
get foo() {
return this.#foo();
}
set foo($$value) {
return this.#foo($$value);
}
#bar = $.derived(() => ({ baz: this.foo }));
get bar() {
return this.#bar();
}
set bar($$value) {
return this.#bar($$value);
}
constructor() {
this.a = 1;
this.#b = 2;
this.foo.bar = 3;
this.bar = 4;
}
});
}
$.pop();
}

@ -1,15 +1,13 @@
import * as $ from 'svelte/internal/server';
export default function Delegated_locally_declared_shadowed($$payload) {
$$payload.child(($$payload) => {
const each_array = $.ensure_array_like({ length: 1 });
const each_array = $.ensure_array_like({ length: 1 });
$$payload.push(`<!--[-->`);
$$payload.push(`<!--[-->`);
for (let index = 0, $$length = each_array.length; index < $$length; index++) {
$$payload.push(`<button type="button"${$.attr('data-index', index)}>B</button>`);
}
for (let index = 0, $$length = each_array.length; index < $$length; index++) {
$$payload.push(`<button type="button"${$.attr('data-index', index)}>B</button>`);
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
}

@ -1,10 +1,10 @@
import * as $ from 'svelte/internal/server';
export default function Main($$payload) {
$$payload.child(($$payload) => {
let x = 'test';
let y = () => 'test';
// needs to be a snapshot test because jsdom does auto-correct the attribute casing
let x = 'test';
$$payload.push(`<div${$.attr('foobar', x)}></div> <svg${$.attr('viewBox', x)}></svg> <custom-element${$.attr('foobar', x)}></custom-element> <div${$.attr('foobar', y())}></div> <svg${$.attr('viewBox', y())}></svg> <custom-element${$.attr('foobar', y())}></custom-element>`);
});
let y = () => 'test';
$$payload.push(`<div${$.attr('foobar', x)}></div> <svg${$.attr('viewBox', x)}></svg> <custom-element${$.attr('foobar', x)}></custom-element> <div${$.attr('foobar', y())}></div> <svg${$.attr('viewBox', y())}></svg> <custom-element${$.attr('foobar', y())}></custom-element>`);
}

@ -1,15 +1,13 @@
import * as $ from 'svelte/internal/server';
export default function Each_index_non_null($$payload) {
$$payload.child(($$payload) => {
const each_array = $.ensure_array_like(Array(10));
const each_array = $.ensure_array_like(Array(10));
$$payload.push(`<!--[-->`);
$$payload.push(`<!--[-->`);
for (let i = 0, $$length = each_array.length; i < $$length; i++) {
$$payload.push(`<p>index: ${$.escape(i)}</p>`);
}
for (let i = 0, $$length = each_array.length; i < $$length; i++) {
$$payload.push(`<p>index: ${$.escape(i)}</p>`);
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
}

@ -1,17 +1,15 @@
import * as $ from 'svelte/internal/server';
export default function Each_string_template($$payload) {
$$payload.child(($$payload) => {
const each_array = $.ensure_array_like(['foo', 'bar', 'baz']);
const each_array = $.ensure_array_like(['foo', 'bar', 'baz']);
$$payload.push(`<!--[-->`);
$$payload.push(`<!--[-->`);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let thing = each_array[$$index];
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let thing = each_array[$$index];
$$payload.push(`<!---->${$.escape(thing)}, `);
}
$$payload.push(`<!---->${$.escape(thing)}, `);
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
}

@ -1,27 +1,25 @@
import * as $ from 'svelte/internal/server';
export default function Function_prop_no_getter($$payload) {
$$payload.child(($$payload) => {
let count = 0;
let count = 0;
function onmouseup() {
count += 2;
}
function onmouseup() {
count += 2;
}
const plusOne = (num) => num + 1;
const plusOne = (num) => num + 1;
Button($$payload, {
onmousedown: () => count += 1,
onmouseup,
onmouseenter: () => count = plusOne(count),
Button($$payload, {
onmousedown: () => count += 1,
onmouseup,
onmouseenter: () => count = plusOne(count),
children: ($$payload) => {
$$payload.child(($$payload) => {
$$payload.push(`<!---->clicks: ${$.escape(count)}`);
});
},
children: ($$payload) => {
$$payload.child(($$payload) => {
$$payload.push(`<!---->clicks: ${$.escape(count)}`);
});
},
$$slots: { default: true }
});
$$slots: { default: true }
});
}

@ -1,7 +1,5 @@
import * as $ from 'svelte/internal/server';
export default function Functional_templating($$payload) {
$$payload.child(($$payload) => {
$$payload.push(`<h1>hello</h1> <div class="potato"><p>child element</p> <p>another child element</p></div>`);
});
$$payload.push(`<h1>hello</h1> <div class="potato"><p>child element</p> <p>another child element</p></div>`);
}

@ -1,7 +1,5 @@
import * as $ from 'svelte/internal/server';
export default function Hello_world($$payload) {
$$payload.child(($$payload) => {
$$payload.push(`<h1>hello world</h1>`);
});
$$payload.push(`<h1>hello world</h1>`);
}

@ -1,7 +1,5 @@
import * as $ from 'svelte/internal/server';
export default function Hmr($$payload) {
$$payload.child(($$payload) => {
$$payload.push(`<h1>hello world</h1>`);
});
$$payload.push(`<h1>hello world</h1>`);
}

@ -1,6 +1,4 @@
import * as $ from 'svelte/internal/server';
import { random } from './module.svelte';
export default function Imports_in_modules($$payload) {
$$payload.child(($$payload) => {});
}
export default function Imports_in_modules($$payload) {}

@ -1,10 +1,8 @@
import * as $ from 'svelte/internal/server';
export default function Nullish_coallescence_omittance($$payload) {
$$payload.child(($$payload) => {
let name = 'world';
let count = 0;
let name = 'world';
let count = 0;
$$payload.push(`<h1>Hello, world!</h1> <b>123</b> <button>Count is ${$.escape(count)}</button> <h1>Hello, world</h1>`);
});
$$payload.push(`<h1>Hello, world!</h1> <b>123</b> <button>Count is ${$.escape(count)}</button> <h1>Hello, world</h1>`);
}

@ -3,17 +3,14 @@ import * as $ from 'svelte/internal/server';
export default function Props_identifier($$payload, $$props) {
$.push();
$$payload.child(($$payload) => {
let { $$slots, $$events, ...props } = $$props;
props.a;
props[a];
props.a.b;
props.a.b = true;
props.a = true;
props[a] = true;
props;
});
let { $$slots, $$events, ...props } = $$props;
props.a;
props[a];
props.a.b;
props.a.b = true;
props.a = true;
props[a] = true;
props;
$.pop();
}

@ -1,9 +1,7 @@
import * as $ from 'svelte/internal/server';
export default function Purity($$payload) {
$$payload.child(($$payload) => {
$$payload.push(`<p>0</p> <p>${$.escape(location.href)}</p> `);
Child($$payload, { prop: encodeURIComponent('hello') });
$$payload.push(`<!---->`);
});
$$payload.push(`<p>0</p> <p>${$.escape(location.href)}</p> `);
Child($$payload, { prop: encodeURIComponent('hello') });
$$payload.push(`<!---->`);
}

@ -1,9 +1,7 @@
import * as $ from 'svelte/internal/server';
export default function Skip_static_subtree($$payload, $$props) {
$$payload.child(($$payload) => {
let { title, content } = $$props;
let { title, content } = $$props;
$$payload.push(`<header><nav><a href="/">Home</a> <a href="/away">Away</a></nav></header> <main><h1>${$.escape(title)}</h1> <div class="static"><p>we don't need to traverse these nodes</p></div> <p>or</p> <p>these</p> <p>ones</p> ${$.html(content)} <p>these</p> <p>trailing</p> <p>nodes</p> <p>can</p> <p>be</p> <p>completely</p> <p>ignored</p></main> <cant-skip><custom-elements with="attributes"></custom-elements></cant-skip> <div><input autofocus/></div> <div><source muted/></div> <select><option value="a"${$.maybe_selected($$payload, 'a')}>a</option></select> <img src="..." alt="" loading="lazy"/> <div><img src="..." alt="" loading="lazy"/></div>`);
});
$$payload.push(`<header><nav><a href="/">Home</a> <a href="/away">Away</a></nav></header> <main><h1>${$.escape(title)}</h1> <div class="static"><p>we don't need to traverse these nodes</p></div> <p>or</p> <p>these</p> <p>ones</p> ${$.html(content)} <p>these</p> <p>trailing</p> <p>nodes</p> <p>can</p> <p>be</p> <p>completely</p> <p>ignored</p></main> <cant-skip><custom-elements with="attributes"></custom-elements></cant-skip> <div><input autofocus/></div> <div><source muted/></div> <select><option value="a"${$.maybe_selected($$payload, 'a')}>a</option></select> <img src="..." alt="" loading="lazy"/> <div><img src="..." alt="" loading="lazy"/></div>`);
}

@ -1,17 +1,15 @@
import * as $ from 'svelte/internal/server';
export default function State_proxy_literal($$payload) {
$$payload.child(($$payload) => {
let str = '';
let tpl = ``;
let str = '';
let tpl = ``;
function reset() {
str = '';
str = ``;
tpl = '';
tpl = ``;
}
function reset() {
str = '';
str = ``;
tpl = '';
tpl = ``;
}
$$payload.push(`<input${$.attr('value', str)}/> <input${$.attr('value', tpl)}/> <button>reset</button>`);
});
$$payload.push(`<input${$.attr('value', str)}/> <input${$.attr('value', tpl)}/> <button>reset</button>`);
}

@ -1,9 +1,7 @@
import * as $ from 'svelte/internal/server';
export default function Svelte_element($$payload, $$props) {
$$payload.child(($$payload) => {
let { tag = 'hr' } = $$props;
let { tag = 'hr' } = $$props;
$.element($$payload, tag);
});
$.element($$payload, tag);
}

@ -1,18 +1,16 @@
import * as $ from 'svelte/internal/server';
export default function Text_nodes_deriveds($$payload) {
$$payload.child(($$payload) => {
let count1 = 0;
let count2 = 0;
let count1 = 0;
let count2 = 0;
function text1() {
return count1;
}
function text1() {
return count1;
}
function text2() {
return count2;
}
function text2() {
return count2;
}
$$payload.push(`<p>${$.escape(text1())}${$.escape(text2())}</p>`);
});
$$payload.push(`<p>${$.escape(text1())}${$.escape(text2())}</p>`);
}
Loading…
Cancel
Save