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 1500x 1500x 1500x 1576x 1576x 1576x 1576x 1576x 321x 1576x 4x 4x 1572x 1572x 1576x 72x 1576x 1x 1x 1571x 1576x 976x 217x 217x 217x 204x 204x 2x 2x 2x 2x 1x 2x 2x 204x 217x 974x 974x 974x 976x 23x 23x 976x 1567x 1576x 241x 241x 1576x 1491x 1491x 1491x 1491x 1491x 1500x 1500x 1500x 1500x 1566x 1566x 1490x 1490x 1490x 1490x 1490x 1490x 1490x 1500x 1924x 7x 7x 7x 1917x 1924x 1924x 1924x 1924x 1924x 1490x 1490x 1490x 1500x 1677x 1677x 1677x 1677x 1677x 1677x 1677x 1677x 1677x 1473x | /** @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); } } |