All files / src/compiler/phases/2-analyze/visitors EachBlock.js

100% Statements 41/41
100% Branches 13/13
100% Functions 1/1
100% Lines 39/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 402x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 978x 978x 978x 978x 978x 978x 978x 1x 1x 1x 977x 978x 219x 219x 219x 219x 977x 977x 977x 977x 977x 977x 977x 977x 977x 978x 974x 978x  
/** @import { EachBlock } from '#compiler' */
/** @import { Context } from '../types' */
/** @import { Scope } from '../../scope' */
import * as e from '../../../errors.js';
import { validate_block_not_empty, validate_opening_tag } from './shared/utils.js';
 
/**
 * @param {EachBlock} node
 * @param {Context} context
 */
export function EachBlock(node, context) {
	validate_opening_tag(node, context.state, '#');
 
	validate_block_not_empty(node.body, context);
	validate_block_not_empty(node.fallback, context);
 
	const id = node.context;
	if (id.type === 'Identifier' && (id.name === '$state' || id.name === '$derived')) {
		// TODO weird that this is necessary
		e.state_invalid_placement(node, id.name);
	}
 
	if (node.key) {
		// treat `{#each items as item, i (i)}` as a normal indexed block, everything else as keyed
		node.metadata.keyed =
			node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index;
	}
 
	// evaluate expression in parent scope
	context.visit(node.expression, {
		...context.state,
		expression: node.metadata.expression,
		scope: /** @type {Scope} */ (context.state.scope.parent)
	});
 
	context.visit(node.body);
	if (node.key) context.visit(node.key);
	if (node.fallback) context.visit(node.fallback);
}