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

100% Statements 43/43
100% Branches 9/9
100% Functions 1/1
100% Lines 42/42

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 432x 2x 2x 2x 2x 2x 2x 2x 2x 1305x 1305x 1305x 1305x 1305x 1305x 429x 374x 374x 374x 429x 1305x 1305x 169x 169x 169x 169x 1x 1x 169x 1305x 1305x 181x 181x 181x 181x 181x 181x 181x 181x 1124x 1124x 1124x  
/** @import { ArrowFunctionExpression, FunctionExpression, Node } from 'estree' */
/** @import { ComponentContext } from '../../types' */
import { build_hoisted_params } from '../../utils.js';
 
/**
 * @param {ArrowFunctionExpression | FunctionExpression} node
 * @param {ComponentContext} context
 */
export const visit_function = (node, context) => {
	const metadata = node.metadata;
 
	let state = { ...context.state, getters: { ...context.state.getters }, in_constructor: false };
 
	// TODO do this in the `_` visitor?
	for (const [name, binding] of state.scope.declarations) {
		if (binding.declaration_kind === 'param') {
			// TODO this should be unnecessary, EachBlock should declare its own scope
			state.getters[name] = binding.node;
		}
	}
 
	if (node.type === 'FunctionExpression') {
		const parent = /** @type {Node} */ (context.path.at(-1));
		state.in_constructor = parent.type === 'MethodDefinition' && parent.kind === 'constructor';
 
		if (node.id) {
			state.getters[node.id.name] = node.id;
		}
	}
 
	if (metadata?.hoisted === true) {
		const params = build_hoisted_params(node, context);
 
		return /** @type {FunctionExpression} */ ({
			...node,
			params,
			body: context.visit(node.body, state)
		});
	}
 
	context.next(state);
};