feat: shorter each blocks (#10937)

pull/10938/head
Rich Harris 9 months ago committed by GitHub
parent 8cfea9f36c
commit 808cc6fca6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
feat: more efficient each block compiler output

@ -2314,12 +2314,6 @@ export const template_visitors = {
// TODO should use context.visit? // TODO should use context.visit?
const children = create_block(node, 'each_block', node.body.nodes, context); const children = create_block(node, 'each_block', node.body.nodes, context);
const else_block = node.fallback
? b.arrow(
[b.id('$$anchor')],
/** @type {import('estree').BlockStatement} */ (context.visit(node.fallback))
)
: b.literal(null);
const key_function = node.key const key_function = node.key
? b.arrow( ? b.arrow(
[node.context.type === 'Identifier' ? node.context : b.id('$$item'), index], [node.context.type === 'Identifier' ? node.context : b.id('$$item'), index],
@ -2337,6 +2331,11 @@ export const template_visitors = {
declarations.push(b.let(node.index, index)); declarations.push(b.let(node.index, index));
} }
let callee = '$.each_indexed';
/** @type {import('estree').Expression[]} */
const args = [];
if ((each_type & EACH_KEYED) !== 0) { if ((each_type & EACH_KEYED) !== 0) {
if (context.state.options.dev && key_function.type !== 'Literal') { if (context.state.options.dev && key_function.type !== 'Literal') {
context.state.init.push( context.state.init.push(
@ -2344,33 +2343,34 @@ export const template_visitors = {
); );
} }
context.state.after_update.push( callee = '$.each_keyed';
b.stmt(
b.call( args.push(
'$.each_keyed',
context.state.node, context.state.node,
each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection), each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection),
b.literal(each_type), b.literal(each_type),
key_function, key_function,
b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(children))), b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(children)))
else_block
)
)
); );
} else { } else {
context.state.after_update.push( args.push(
b.stmt(
b.call(
'$.each_indexed',
context.state.node, context.state.node,
each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection), each_node_meta.array_name ? each_node_meta.array_name : b.thunk(collection),
b.literal(each_type), b.literal(each_type),
b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(children))), b.arrow([b.id('$$anchor'), item, index], b.block(declarations.concat(children)))
else_block );
) }
if (node.fallback) {
args.push(
b.arrow(
[b.id('$$anchor')],
/** @type {import('estree').BlockStatement} */ (context.visit(node.fallback))
) )
); );
} }
context.state.after_update.push(b.stmt(b.call(callee, ...args)));
}, },
IfBlock(node, context) { IfBlock(node, context) {
context.state.template.push('<!>'); context.state.template.push('<!>');

@ -197,10 +197,10 @@ function each(anchor, get_collection, flags, get_key, render_fn, fallback_fn, re
* @param {number} flags * @param {number} flags
* @param {null | ((item: V) => string)} get_key * @param {null | ((item: V) => string)} get_key
* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn * @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node | null) => void)} fallback_fn * @param {null | ((anchor: Node | null) => void)} [fallback_fn]
* @returns {void} * @returns {void}
*/ */
export function each_keyed(anchor, get_collection, flags, get_key, render_fn, fallback_fn) { export function each_keyed(anchor, get_collection, flags, get_key, render_fn, fallback_fn = null) {
each(anchor, get_collection, flags, get_key, render_fn, fallback_fn, reconcile_tracked_array); each(anchor, get_collection, flags, get_key, render_fn, fallback_fn, reconcile_tracked_array);
} }
@ -210,10 +210,10 @@ export function each_keyed(anchor, get_collection, flags, get_key, render_fn, fa
* @param {() => V[]} get_collection * @param {() => V[]} get_collection
* @param {number} flags * @param {number} flags
* @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn * @param {(anchor: null, item: V, index: import('#client').MaybeSource<number>) => void} render_fn
* @param {null | ((anchor: Node | null) => void)} fallback_fn * @param {null | ((anchor: Node | null) => void)} [fallback_fn]
* @returns {void} * @returns {void}
*/ */
export function each_indexed(anchor, get_collection, flags, render_fn, fallback_fn) { export function each_indexed(anchor, get_collection, flags, render_fn, fallback_fn = null) {
each(anchor, get_collection, flags, null, render_fn, fallback_fn, reconcile_indexed_array); each(anchor, get_collection, flags, null, render_fn, fallback_fn, reconcile_indexed_array);
} }

@ -10,18 +10,12 @@ export default function Each_string_template($$anchor, $$props) {
var fragment = $.comment($$anchor); var fragment = $.comment($$anchor);
var node = $.first_child(fragment); var node = $.first_child(fragment);
$.each_indexed( $.each_indexed(node, () => ['foo', 'bar', 'baz'], 1, ($$anchor, thing, $$index) => {
node,
() => ['foo', 'bar', 'baz'],
1,
($$anchor, thing, $$index) => {
var text = $.space_frag($$anchor); var text = $.space_frag($$anchor);
$.render_effect(() => $.set_text(text, `${$.stringify($.unwrap(thing))}, `)); $.render_effect(() => $.set_text(text, `${$.stringify($.unwrap(thing))}, `));
return $.close($$anchor, text); return $.close($$anchor, text);
}, });
null
);
$.close_frag($$anchor, fragment); $.close_frag($$anchor, fragment);
$.pop(); $.pop();

Loading…
Cancel
Save