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 1553x 1553x 1553x 1600x 1600x 1600x 1600x 1600x 321x 1600x 4x 4x 1596x 1596x 1600x 74x 1600x 1x 1x 1595x 1600x 992x 225x 225x 225x 204x 204x 2x 2x 2x 2x 1x 2x 2x 204x 225x 990x 990x 990x 992x 23x 23x 992x 1591x 1600x 241x 241x 1600x 1544x 1544x 1544x 1544x 1544x 1553x 1553x 1553x 1553x 1590x 1590x 1543x 1543x 1543x 1543x 1543x 1543x 1543x 1553x 2017x 7x 7x 7x 2010x 2017x 2017x 2017x 2017x 2017x 1543x 1543x 1543x 1553x 1745x 1745x 1745x 1745x 1745x 1745x 1745x 1745x 1745x 1526x | /** @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); } } |