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

100% Statements 71/71
100% Branches 23/23
100% Functions 1/1
100% Lines 68/68

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 65 66 67 68 692x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1420x 1514x 1514x 1514x 1514x 1514x 306x 1514x 4x 4x 1510x 1510x 1514x 60x 1514x 1x 1x 1509x 1514x 949x 200x 200x 200x 193x 193x 2x 2x 2x 2x 1x 2x 2x 193x 200x 947x 947x 947x 949x 23x 23x 949x 1505x 1514x 226x 226x 1514x 1411x 1411x 1411x 1411x 1411x 1411x 1411x  
/** @import { Component, SvelteComponent, SvelteSelf } from '#compiler' */
/** @import { Context } from '../../types' */
import * as e from '../../../../errors.js';
import { get_attribute_expression, is_expression_attribute } from '../../../../utils/ast.js';
import {
	validate_attribute,
	validate_attribute_name,
	validate_slot_attribute
} from './attribute.js';
 
/**
 * @param {Component | SvelteComponent | SvelteSelf} node
 * @param {Context} context
 */
export function visit_component(node, context) {
	for (const attribute of node.attributes) {
		if (
			attribute.type !== 'Attribute' &&
			attribute.type !== 'SpreadAttribute' &&
			attribute.type !== 'LetDirective' &&
			attribute.type !== 'OnDirective' &&
			attribute.type !== 'BindDirective'
		) {
			e.component_invalid_directive(attribute);
		}
 
		if (
			attribute.type === 'OnDirective' &&
			(attribute.modifiers.length > 1 || attribute.modifiers.some((m) => m !== 'once'))
		) {
			e.event_handler_invalid_component_modifier(attribute);
		}
 
		if (attribute.type === 'Attribute') {
			if (context.state.analysis.runes) {
				validate_attribute(attribute, node);
 
				if (is_expression_attribute(attribute)) {
					const expression = get_attribute_expression(attribute);
					if (expression.type === 'SequenceExpression') {
						let i = /** @type {number} */ (expression.start);
						while (--i > 0) {
							const char = context.state.analysis.source[i];
							if (char === '(') break; // parenthesized sequence expressions are ok
							if (char === '{') e.attribute_invalid_sequence_expression(expression);
						}
					}
				}
			}
 
			validate_attribute_name(attribute);
 
			if (attribute.name === 'slot') {
				validate_slot_attribute(context, attribute, true);
			}
		}
 
		if (attribute.type === 'BindDirective' && attribute.name !== 'this') {
			context.state.analysis.uses_component_bindings = true;
		}
	}
 
	context.next({
		...context.state,
		parent_element: null,
		component_slots: new Set()
	});
}