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 1445x 1445x 1445x 1539x 1539x 1539x 1539x 1539x 319x 1539x 4x 4x 1535x 1535x 1539x 62x 1539x 1x 1x 1534x 1539x 957x 206x 206x 206x 199x 199x 2x 2x 2x 2x 1x 2x 2x 199x 206x 955x 955x 955x 957x 23x 23x 957x 1530x 1539x 239x 239x 1539x 1436x 1436x 1436x 1436x 1436x 1445x 1445x 1445x 1445x 1529x 1529x 1435x 1435x 1435x 1435x 1435x 1435x 1435x 1445x 1867x 7x 7x 7x 1860x 1867x 1867x 1867x 1867x 1867x 1435x 1435x 1435x 1445x 1616x 1616x 1616x 1616x 1616x 1616x 1616x 1616x 1616x 1418x | /** @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); } } |