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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1580x 1580x 1580x 1612x 1612x 1612x 1612x 1612x 325x 1612x 4x 4x 1608x 1608x 1612x 76x 1612x 1x 1x 1607x 1612x 998x 225x 225x 225x 204x 204x 2x 2x 2x 2x 1x 2x 2x 204x 225x 996x 996x 996x 998x 23x 23x 998x 1603x 1612x 245x 245x 1612x 1571x 1571x 1571x 1571x 1571x 1580x 1580x 1580x 1580x 1602x 1602x 1570x 1570x 1570x 1570x 1570x 1570x 1570x 1580x 2062x 7x 7x 7x 2055x 2062x 2062x 2062x 2062x 2062x 1570x 1570x 1570x 1580x 1787x 1787x 1787x 1787x 1787x 1787x 1787x 1787x 1787x 1553x | /** @import { AST } from '#compiler' */ /** @import { Context } from '../../types' */ import * as e from '../../../../errors.js'; import { get_attribute_expression, is_expression_attribute } from '../../../../utils/ast.js'; import { determine_slot } from '../../../../utils/slot.js'; import { validate_attribute, validate_attribute_name, validate_slot_attribute } from './attribute.js'; import { mark_subtree_dynamic } from './fragment.js'; /** * @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node * @param {Context} context */ export function visit_component(node, context) { mark_subtree_dynamic(context.path); 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; } } // If the component has a slot attribute — `<Foo slot="whatever" .../>` — // then `let:` directives apply to other attributes, instead of just the // top-level contents of the component. Yes, this is very weird. const default_state = determine_slot(node) ? context.state : { ...context.state, scope: node.metadata.scopes.default }; for (const attribute of node.attributes) { context.visit(attribute, attribute.type === 'LetDirective' ? default_state : context.state); } /** @type {AST.Comment[]} */ let comments = []; /** @type {Record<string, AST.Fragment['nodes']>} */ const nodes = { default: [] }; for (const child of node.fragment.nodes) { if (child.type === 'Comment') { comments.push(child); continue; } const slot_name = determine_slot(child) ?? 'default'; (nodes[slot_name] ??= []).push(...comments, child); if (slot_name !== 'default') comments = []; } const component_slots = new Set(); for (const slot_name in nodes) { const state = { ...context.state, scope: node.metadata.scopes[slot_name], parent_element: null, component_slots }; context.visit({ ...node.fragment, nodes: nodes[slot_name] }, state); } } |