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 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 35x 35x 35x 35x 35x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 15x 52x 52x 52x 52x 52x 52x 52x 52x 52x 52x 3x 3x 52x 52x 52x 52x 52x 40x 51x 12x 12x 52x | /** @import { BlockStatement, Expression, Identifier, Pattern, Statement } from 'estree' */ /** @import { AST } from '#compiler' */ /** @import { ComponentContext } from '../types' */ import { dev } from '../../../../state.js'; import { extract_paths } from '../../../../utils/ast.js'; import * as b from '../../../../utils/builders.js'; import { get_value } from './shared/declarations.js'; /** * @param {AST.SnippetBlock} node * @param {ComponentContext} context */ export function SnippetBlock(node, context) { // TODO hoist where possible /** @type {Pattern[]} */ const args = [b.id('$$anchor')]; /** @type {BlockStatement} */ let body; /** @type {Statement[]} */ const declarations = []; const transform = { ...context.state.transform }; const child_state = { ...context.state, transform }; for (let i = 0; i < node.parameters.length; i++) { const argument = node.parameters[i]; if (!argument) continue; if (argument.type === 'Identifier') { args.push({ type: 'AssignmentPattern', left: argument, right: b.id('$.noop') }); transform[argument.name] = { read: b.call }; continue; } let arg_alias = `$$arg${i}`; args.push(b.id(arg_alias)); const paths = extract_paths(argument); for (const path of paths) { const name = /** @type {Identifier} */ (path.node).name; const needs_derived = path.has_default_value; // to ensure that default value is only called once const fn = b.thunk( /** @type {Expression} */ (context.visit(path.expression?.(b.maybe_call(b.id(arg_alias))))) ); declarations.push(b.let(path.node, needs_derived ? b.call('$.derived_safe_equal', fn) : fn)); transform[name] = { read: needs_derived ? get_value : b.call }; // we need to eagerly evaluate the expression in order to hit any // 'Cannot access x before initialization' errors if (dev) { declarations.push(b.stmt(transform[name].read(b.id(name)))); } } } body = b.block([ ...declarations, .../** @type {BlockStatement} */ (context.visit(node.body, child_state)).body ]); /** @type {Expression} */ let snippet = b.arrow(args, body); if (dev) { snippet = b.call('$.wrap_snippet', b.id(context.state.analysis.name), snippet); } const declaration = b.const(node.expression, snippet); // Top-level snippets are hoisted so they can be referenced in the `<script>` if (context.path.length === 1 && context.path[0].type === 'Fragment') { context.state.analysis.top_level_snippets.push(declaration); } else { context.state.init.push(declaration); } } |