diff --git a/packages/svelte/scripts/generate-types.js b/packages/svelte/scripts/generate-types.js index c558a2bbf7..f41be07e7e 100644 --- a/packages/svelte/scripts/generate-types.js +++ b/packages/svelte/scripts/generate-types.js @@ -26,7 +26,7 @@ await createBundle({ // so that types/properties with `@internal` (and its dependencies) are removed from the output stripInternal: true, paths: Object.fromEntries( - Object.entries(pkg.imports).map(([key, value]) => { + Object.entries(pkg.imports).map(/** @param {[string,any]} import */([key, value]) => { return [key, [value.types ?? value.default ?? value]]; }) ) diff --git a/packages/svelte/src/compiler/index.js b/packages/svelte/src/compiler/index.js index a378af34ee..fb7b7b2548 100644 --- a/packages/svelte/src/compiler/index.js +++ b/packages/svelte/src/compiler/index.js @@ -82,6 +82,7 @@ export function compileModule(source, options) { * @returns {AST.Root} */ +// TODO 6.0 remove unused `filename` /** * The parse function parses a component, returning only its abstract syntax tree. * @@ -94,7 +95,6 @@ export function compileModule(source, options) { * @returns {Record} */ -// TODO 6.0 remove unused `filename` /** * The parse function parses a component, returning only its abstract syntax tree. * @@ -123,6 +123,8 @@ export function parse(source, { modern, loose } = {}) { * @param {boolean | undefined} modern */ function to_public_ast(source, ast, modern) { + /** @type {AST.Root} */ + const rrrrr = parse('hi', { modern: true }); // ensure that the modern AST is available if (modern) { const clean = (/** @type {any} */ node) => { delete node.metadata; diff --git a/packages/svelte/src/compiler/legacy.js b/packages/svelte/src/compiler/legacy.js index 85345bca4a..96bfbd9f78 100644 --- a/packages/svelte/src/compiler/legacy.js +++ b/packages/svelte/src/compiler/legacy.js @@ -55,7 +55,7 @@ export function convert(source, ast) { // Insert svelte:options back into the root nodes if (/** @type {any} */ (options)?.__raw__) { - let idx = node.fragment.nodes.findIndex((node) => options.end <= node.start); + let idx = node.fragment.nodes.findIndex((node) => /** @type {any} */ (options).end <= node.start); if (idx === -1) { idx = node.fragment.nodes.length; } diff --git a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js index 79e8fbb02c..8a4d8cb350 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js +++ b/packages/svelte/src/compiler/phases/2-analyze/css/css-prune.js @@ -9,8 +9,8 @@ import { import { regex_ends_with_whitespace, regex_starts_with_whitespace } from '../../patterns.js'; import { get_attribute_chunks, is_text_attribute } from '../../../utils/ast.js'; -/** @typedef {NODE_PROBABLY_EXISTS | NODE_DEFINITELY_EXISTS} NodeExistsValue */ -/** @typedef {FORWARD | BACKWARD} Direction */ +/** @typedef {typeof NODE_PROBABLY_EXISTS | typeof NODE_DEFINITELY_EXISTS} NodeExistsValue */ +/** @typedef {typeof FORWARD | typeof BACKWARD} Direction */ const NODE_PROBABLY_EXISTS = 0; const NODE_DEFINITELY_EXISTS = 1; diff --git a/packages/svelte/src/compiler/phases/2-analyze/index.js b/packages/svelte/src/compiler/phases/2-analyze/index.js index d407b44556..f10a8b4a5e 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/index.js @@ -295,7 +295,7 @@ export function analyze_module(source, options) { // TODO the following are not needed for modules, but we have to pass them in order to avoid type error, // and reducing the type would result in a lot of tedious type casts elsewhere - find a good solution one day ast_type: /** @type {any} */ (null), - component_slots: new Set(), + component_slots: /** @type {Set} */ (new Set()), expression: null, function_depth: 0, has_props_rune: false, diff --git a/packages/svelte/src/compiler/phases/2-analyze/utils/check_graph_for_cycles.js b/packages/svelte/src/compiler/phases/2-analyze/utils/check_graph_for_cycles.js index 67201d4825..83959248fe 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/utils/check_graph_for_cycles.js +++ b/packages/svelte/src/compiler/phases/2-analyze/utils/check_graph_for_cycles.js @@ -14,6 +14,7 @@ export default function check_graph_for_cycles(edges) { }, new Map()); const visited = new Set(); + /** @type {Set} */ const on_stack = new Set(); /** @type {Array>} */ const cycles = []; diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js index f45a6c9a80..e2f84290e5 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js @@ -599,7 +599,7 @@ function has_disabled_attribute(attribute_map) { /** * @param {string} tag_name * @param {Map} attribute_map - * @returns {ElementInteractivity[keyof ElementInteractivity]} + * @returns {typeof ElementInteractivity[keyof typeof ElementInteractivity]} */ function element_interactivity(tag_name, attribute_map) { if ( diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/component.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/component.js index aca87fab81..6d09398fb7 100644 --- a/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/component.js +++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/shared/component.js @@ -145,6 +145,7 @@ export function visit_component(node, context) { if (slot_name !== 'default') comments = []; } + /** @type {Set} */ const component_slots = new Set(); for (const slot_name in nodes) { diff --git a/packages/svelte/src/compiler/phases/scope.js b/packages/svelte/src/compiler/phases/scope.js index 700e098e45..7fd2b65399 100644 --- a/packages/svelte/src/compiler/phases/scope.js +++ b/packages/svelte/src/compiler/phases/scope.js @@ -22,7 +22,7 @@ const NUMBER = Symbol('number'); const STRING = Symbol('string'); const FUNCTION = Symbol('string'); -/** @type {Record} */ +/** @type {Record} */ const globals = { BigInt: [NUMBER], 'Math.min': [NUMBER, Math.min], diff --git a/packages/svelte/src/compiler/state.js b/packages/svelte/src/compiler/state.js index 725d03b802..6d9873eb30 100644 --- a/packages/svelte/src/compiler/state.js +++ b/packages/svelte/src/compiler/state.js @@ -87,7 +87,7 @@ export function pop_ignore() { /** * @param {AST.SvelteNode | NodeLike} node - * @param {import('../constants.js').IGNORABLE_RUNTIME_WARNINGS[number]} code + * @param {typeof import('../constants.js').IGNORABLE_RUNTIME_WARNINGS[number]} code * @returns */ export function is_ignored(node, code) { diff --git a/packages/svelte/src/index-client.js b/packages/svelte/src/index-client.js index 397a81c319..85eeab7de9 100644 --- a/packages/svelte/src/index-client.js +++ b/packages/svelte/src/index-client.js @@ -160,10 +160,14 @@ export function createEventDispatcher() { e.lifecycle_outside_component('createEventDispatcher'); } + /** + * @param [detail] + * @param [options] + */ return (type, detail, options) => { const events = /** @type {Record} */ ( active_component_context.s.$$events - )?.[/** @type {any} */ (type)]; + )?.[/** @type {string} */ (type)]; if (events) { const callbacks = is_array(events) ? events.slice() : [events]; diff --git a/packages/svelte/src/internal/client/dev/hmr.js b/packages/svelte/src/internal/client/dev/hmr.js index 27e2643d16..709a1b2722 100644 --- a/packages/svelte/src/internal/client/dev/hmr.js +++ b/packages/svelte/src/internal/client/dev/hmr.js @@ -64,7 +64,7 @@ export function hmr(original, get_source) { // @ts-expect-error wrapper[FILENAME] = original[FILENAME]; - // @ts-expect-error + // @ts-ignore wrapper[HMR] = { // When we accept an update, we set the original source to the new component original, diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js index 4f68db57b1..42df41041e 100644 --- a/packages/svelte/src/internal/client/dom/blocks/await.js +++ b/packages/svelte/src/internal/client/dom/blocks/await.js @@ -28,6 +28,8 @@ const PENDING = 0; const THEN = 1; const CATCH = 2; +/** @typedef {typeof PENDING | typeof THEN | typeof CATCH} AwaitState */ + /** * @template V * @param {TemplateNode} node @@ -67,9 +69,8 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) { : mutable_source(/** @type {V} */ (undefined), false, false); var error_source = runes ? source(undefined) : mutable_source(undefined, false, false); var resolved = false; - /** - * @param {PENDING | THEN | CATCH} state + * @param {AwaitState} state * @param {boolean} restore */ function update(state, restore) { diff --git a/packages/svelte/src/internal/client/dom/blocks/each.js b/packages/svelte/src/internal/client/dom/blocks/each.js index 43c75e2a37..006bf09257 100644 --- a/packages/svelte/src/internal/client/dom/blocks/each.js +++ b/packages/svelte/src/internal/client/dom/blocks/each.js @@ -191,7 +191,7 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f // store a reference to the effect so that we can update the start/end nodes in reconciliation each_effect ??= /** @type {Effect} */ (active_effect); - array = get(each_array); + array = /** @type {V[]} */ (get(each_array)); var length = array.length; if (was_empty && length === 0) { diff --git a/packages/svelte/src/internal/client/dom/blocks/if.js b/packages/svelte/src/internal/client/dom/blocks/if.js index 6ba9ad4936..f418d46538 100644 --- a/packages/svelte/src/internal/client/dom/blocks/if.js +++ b/packages/svelte/src/internal/client/dom/blocks/if.js @@ -36,7 +36,7 @@ export function if_block(node, fn, elseif = false) { /** @type {Effect | null} */ var alternate_effect = null; - /** @type {UNINITIALIZED | boolean | null} */ + /** @type {typeof UNINITIALIZED | boolean | null} */ var condition = UNINITIALIZED; var flags = elseif ? EFFECT_TRANSPARENT : 0; diff --git a/packages/svelte/src/internal/client/dom/elements/bindings/input.js b/packages/svelte/src/internal/client/dom/elements/bindings/input.js index 7c1fccea0f..29ba0e4d4b 100644 --- a/packages/svelte/src/internal/client/dom/elements/bindings/input.js +++ b/packages/svelte/src/internal/client/dom/elements/bindings/input.js @@ -240,6 +240,7 @@ export function bind_checked(input, get, set = get) { * @returns {V[]} */ function get_binding_group_value(group, __value, checked) { + /** @type {Set} */ var value = new Set(); for (var i = 0; i < group.length; i += 1) { diff --git a/packages/svelte/src/internal/client/dom/template.js b/packages/svelte/src/internal/client/dom/template.js index ebbf0039b2..265a52262f 100644 --- a/packages/svelte/src/internal/client/dom/template.js +++ b/packages/svelte/src/internal/client/dom/template.js @@ -156,7 +156,7 @@ export function from_mathml(content, flags) { /** * @param {TemplateStructure[]} structure - * @param {NAMESPACE_SVG | NAMESPACE_MATHML | undefined} [ns] + * @param {typeof NAMESPACE_SVG | typeof NAMESPACE_MATHML | undefined} [ns] */ function fragment_from_tree(structure, ns) { var fragment = create_fragment(); diff --git a/packages/svelte/src/internal/client/reactivity/equality.js b/packages/svelte/src/internal/client/reactivity/equality.js index 1041238573..113781b4cd 100644 --- a/packages/svelte/src/internal/client/reactivity/equality.js +++ b/packages/svelte/src/internal/client/reactivity/equality.js @@ -1,7 +1,7 @@ /** @import { Equals } from '#client' */ /** @type {Equals} */ -export function equals(value) { +export const equals = function(value) { return value === this.v; } @@ -26,6 +26,6 @@ export function not_equal(a, b) { } /** @type {Equals} */ -export function safe_equals(value) { +export const safe_equals = function(value) { return !safe_not_equal(value, this.v); } diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 05b747a1c4..cb50337492 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -184,8 +184,7 @@ export function legacy_rest_props(props, exclude) { * The proxy handler for spread props. Handles the incoming array of props * that looks like `() => { dynamic: props }, { static: prop }, ..` and wraps * them so that the whole thing is passed to the component as the `$$props` argument. - * @template {Record} T - * @type {ProxyHandler<{ props: Array T)> }>}} + * @type {ProxyHandler<{ props: Array | (() => Record)> }>}} */ const spread_props_handler = { get(target, key) { @@ -362,8 +361,7 @@ export function prop(props, key, flags, fallback) { // means we can just call `$$props.foo = value` directly if (setter) { var legacy_parent = props.$$legacy; - - return function (/** @type {any} */ value, /** @type {boolean} */ mutation) { + return /** @type {() => V} */ (function (/** @type {V} */ value, /** @type {boolean} */ mutation) { if (arguments.length > 0) { // We don't want to notify if the value was mutated and the parent is in runes mode. // In that case the state proxy (if it exists) should take care of the notification. @@ -377,7 +375,7 @@ export function prop(props, key, flags, fallback) { } return getter(); - }; + }); } // Either prop is written to, but there's no binding, which means we @@ -399,8 +397,8 @@ export function prop(props, key, flags, fallback) { if (bindable) get(d); var parent_effect = /** @type {Effect} */ (active_effect); - - return function (/** @type {any} */ value, /** @type {boolean} */ mutation) { + + return /** @type {() => V} */(function (/** @type {any} */ value, /** @type {boolean} */ mutation) { if (arguments.length > 0) { const new_value = mutation ? get(d) : runes && bindable ? proxy(value) : value; @@ -424,5 +422,5 @@ export function prop(props, key, flags, fallback) { } return get(d); - }; + }); } diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index f6b14f3360..9bb0ec368f 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -37,6 +37,7 @@ import { Batch, schedule_effect } from './batch.js'; import { proxy } from '../proxy.js'; import { execute_derived } from './deriveds.js'; +/** @type {Set} */ export let inspect_effects = new Set(); /** @type {Map} */ diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index ff6844453d..8cb2b72c81 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -169,6 +169,7 @@ const document_listeners = new Map(); function _mount(Component, { target, anchor, props = {}, events, context, intro = true }) { init_operations(); + /** @type {Set} */ var registered_events = new Set(); /** @param {Array} events */ diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index e86866af2a..3d760e4b9e 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -284,7 +284,8 @@ export function update_reaction(reaction) { try { reaction.f |= REACTION_IS_UPDATING; - var result = /** @type {Function} */ (0, reaction.fn)(); + var fn = /** @type {Function} */ (reaction.fn); + var result = fn(); var deps = reaction.deps; if (new_deps !== null) { diff --git a/packages/svelte/src/internal/server/payload.js b/packages/svelte/src/internal/server/payload.js index 195488e061..341039d46f 100644 --- a/packages/svelte/src/internal/server/payload.js +++ b/packages/svelte/src/internal/server/payload.js @@ -6,7 +6,8 @@ export class HeadPayload { uid = () => ''; title = ''; - constructor(css = new Set(), /** @type {string[]} */ out = [], title = '', uid = () => '') { + constructor(/** @type {Set<{ hash: string; code: string }>} */ css = new Set(), /** @type {string[]} */ out = [], title = '', uid = () => '') { + this.css = css; this.out = out; this.title = title; diff --git a/packages/svelte/src/internal/shared/validate.js b/packages/svelte/src/internal/shared/validate.js index 8f3e2807e7..48e76f0958 100644 --- a/packages/svelte/src/internal/shared/validate.js +++ b/packages/svelte/src/internal/shared/validate.js @@ -35,7 +35,7 @@ export function validate_store(store, name) { } /** - * @template {() => unknown} T + * @template {(...args: any[]) => unknown} T * @param {T} fn */ export function prevent_snippet_stringification(fn) { diff --git a/packages/svelte/src/utils.js b/packages/svelte/src/utils.js index cd79cfc274..f8c39253ac 100644 --- a/packages/svelte/src/utils.js +++ b/packages/svelte/src/utils.js @@ -452,7 +452,7 @@ const RUNES = /** @type {const} */ ([ '$host' ]); -/** @typedef {RUNES[number]} RuneName */ +/** @typedef {typeof RUNES[number]} RuneName */ /** * @param {string} name @@ -462,7 +462,7 @@ export function is_rune(name) { return RUNES.includes(/** @type {RuneName} */ (name)); } -/** @typedef {STATE_CREATION_RUNES[number]} StateCreationRuneName */ +/** @typedef {typeof STATE_CREATION_RUNES[number]} StateCreationRuneName */ /** * @param {string} name @@ -477,7 +477,7 @@ const RAW_TEXT_ELEMENTS = /** @type {const} */ (['textarea', 'script', 'style', /** @param {string} name */ export function is_raw_text_element(name) { - return RAW_TEXT_ELEMENTS.includes(/** @type {RAW_TEXT_ELEMENTS[number]} */ (name)); + return RAW_TEXT_ELEMENTS.includes(/** @type {typeof RAW_TEXT_ELEMENTS[number]} */ (name)); } /** diff --git a/packages/svelte/tests/animation-helpers.js b/packages/svelte/tests/animation-helpers.js index dcbb062923..0452a0d643 100644 --- a/packages/svelte/tests/animation-helpers.js +++ b/packages/svelte/tests/animation-helpers.js @@ -3,7 +3,9 @@ import { raf as svelte_raf } from 'svelte/internal/client'; import { queue_micro_task } from '../src/internal/client/dom/task.js'; export const raf = { + /** @type {Set} */ animations: new Set(), + /** @type {Set<(n: number) => void>} */ ticks: new Set(), tick, time: 0, @@ -54,14 +56,24 @@ class Animation { /** * @param {HTMLElement} target - * @param {Keyframe[]} keyframes - * @param {{ duration: number, delay: number }} options + * @param {Keyframe[] | PropertyIndexedKeyframes | null} keyframes + * @param {number | KeyframeAnimationOptions | undefined} options */ - constructor(target, keyframes, { duration, delay }) { + constructor(target, keyframes, options) { this.target = target; - this.#keyframes = keyframes; - this.#duration = Math.round(duration); - this.#delay = delay ?? 0; + this.#keyframes = Array.isArray(keyframes) ? keyframes : []; + if (typeof options === 'number') { + this.#duration = options; + this.#delay = 0; + } else { + const { duration = 0, delay = 0 } = options ?? {}; + if (typeof duration === 'object') { + this.#duration = 0; + } else { + this.#duration = Math.round(+duration); + } + this.#delay = delay; + } this._update(); } @@ -189,6 +201,7 @@ function interpolate(a, b, p) { * @param {{duration: number, delay: number}} options * @returns {globalThis.Animation} */ +// @ts-ignore HTMLElement.prototype.animate = function (keyframes, options) { const animation = new Animation(this, keyframes, options); raf.animations.add(animation); @@ -196,6 +209,7 @@ HTMLElement.prototype.animate = function (keyframes, options) { return animation; }; +// @ts-ignore HTMLElement.prototype.getAnimations = function () { return Array.from(raf.animations).filter((animation) => animation.target === this); }; diff --git a/packages/svelte/tests/helpers.js b/packages/svelte/tests/helpers.js index 410838829e..7a9640636c 100644 --- a/packages/svelte/tests/helpers.js +++ b/packages/svelte/tests/helpers.js @@ -43,6 +43,7 @@ export function create_deferred() { /** @param {any} [reason] */ let reject = (reason) => {}; + /** @type {Promise} */ const promise = new Promise((f, r) => { resolve = f; reject = r; diff --git a/packages/svelte/tests/runtime-browser/assert.js b/packages/svelte/tests/runtime-browser/assert.js index 48bde01410..e0d0b027f2 100644 --- a/packages/svelte/tests/runtime-browser/assert.js +++ b/packages/svelte/tests/runtime-browser/assert.js @@ -1,6 +1,5 @@ /** @import { assert } from 'vitest' */ -/** @import { CompileOptions, Warning } from '#compiler' */ - +import { parse } from 'svelte/compiler'; import { ELEMENT_NODE } from '#client/constants'; /** @@ -20,6 +19,8 @@ export function deepEqual(a, b, message) { * @returns {boolean} */ function is_equal(a, b) { + const input = '\uFEFF
'; + const actual = parse(input, { modern: true }); if (a && typeof a === 'object') { const is_array = Array.isArray(a); if (Array.isArray(b) !== is_array) return false; @@ -87,15 +88,15 @@ function normalize_html(window, html) { /** @param {any} node */ function normalize_children(node) { // sort attributes - const attributes = Array.from(node.attributes).sort((a, b) => { + const attributes = Array.from(node.attributes).sort((/** @type {any} */ a,/** @type {any} */ b) => { return a.name < b.name ? -1 : 1; }); - attributes.forEach((attr) => { + attributes.forEach((/** @type{any} */ attr) => { node.removeAttribute(attr.name); }); - attributes.forEach((attr) => { + attributes.forEach((/** @type{any} */ attr) => { node.setAttribute(attr.name, attr.value); });