All files / src/compiler/phases/3-transform/client/visitors LabeledStatement.js

100% Statements 66/66
94.44% Branches 17/18
100% Functions 1/1
100% Lines 64/64

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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 652x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 143x 2x 2x 2x 141x 141x 141x 141x 141x 141x 141x 143x 141x 141x 141x 143x 123x 123x 141x 141x 141x 141x 141x 141x 143x 216x 183x 183x 183x 183x 183x 183x 216x 110x 110x 183x 183x 183x 141x 141x 141x 141x 141x 141x 141x 143x 143x 143x 143x 143x 143x 143x 143x  
/** @import { Expression, LabeledStatement, Statement } from 'estree' */
/** @import { ReactiveStatement } from '#compiler' */
/** @import { ComponentContext } from '../types' */
import * as b from '../../../../utils/builders.js';
import { build_getter } from '../utils.js';
 
/**
 * @param {LabeledStatement} node
 * @param {ComponentContext} context
 */
export function LabeledStatement(node, context) {
	if (context.state.analysis.runes || context.path.length > 1 || node.label.name !== '$') {
		context.next();
		return;
	}
 
	// To recreate Svelte 4 behaviour, we track the dependencies
	// the compiler can 'see', but we untrack the effect itself
	const reactive_statement = /** @type {ReactiveStatement} */ (
		context.state.analysis.reactive_statements.get(node)
	);
 
	if (!reactive_statement) return; // not the instance context
 
	let serialized_body = /** @type {Statement} */ (context.visit(node.body));
 
	if (serialized_body.type !== 'BlockStatement') {
		serialized_body = b.block([serialized_body]);
	}
 
	const body = serialized_body.body;
 
	/** @type {Expression[]} */
	const sequence = [];
 
	for (const binding of reactive_statement.dependencies) {
		if (binding.kind === 'normal' && binding.declaration_kind !== 'import') continue;
 
		const name = binding.node.name;
		let serialized = build_getter(b.id(name), context.state);
 
		// If the binding is a prop, we need to deep read it because it could be fine-grained $state
		// from a runes-component, where mutations don't trigger an update on the prop as a whole.
		if (name === '$$props' || name === '$$restProps' || binding.kind === 'bindable_prop') {
			serialized = b.call('$.deep_read_state', serialized);
		}
 
		sequence.push(serialized);
	}
 
	// these statements will be topologically ordered later
	context.state.legacy_reactive_statements.set(
		node,
		b.stmt(
			b.call(
				'$.legacy_pre_effect',
				sequence.length > 0 ? b.thunk(b.sequence(sequence)) : b.thunk(b.block([])),
				b.thunk(b.block(body))
			)
		)
	);
 
	return b.empty;
}