diff --git a/packages/svelte/package.json b/packages/svelte/package.json index 56f48a14c2..b682b6cd78 100644 --- a/packages/svelte/package.json +++ b/packages/svelte/package.json @@ -137,7 +137,9 @@ "knip": { "entry": [ "src/*/index.js", - "src/*/public.d.ts" + "src/index-client.ts", + "src/index-server.ts", + "src/index.d.ts" ], "project": [ "src/**" diff --git a/packages/svelte/src/compiler/phases/2-analyze/utils/push_array.js b/packages/svelte/src/compiler/phases/2-analyze/utils/push_array.js deleted file mode 100644 index ee6a9f7c26..0000000000 --- a/packages/svelte/src/compiler/phases/2-analyze/utils/push_array.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Pushes all `items` into `array` using `push`, therefore mutating the array. - * We do this for memory and perf reasons, and because `array.push(...items)` would - * run into a "max call stack size exceeded" error with too many items (~65k). - * @template T - * @param {T[]} array - * @param {T[]} items - */ -export function push_array(array, items) { - for (let i = 0; i < items.length; i++) { - array.push(items[i]); - } -} diff --git a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js index 7f0fab0def..8c88a405f1 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/transform-client.js @@ -275,7 +275,7 @@ export function client_component(source, analysis, options) { const setter = b.set(key, [ b.stmt(b.call(b.id(name), b.id('$$value'))), - b.stmt(b.call('$.flushSync')) + b.stmt(b.call('$.flush_sync')) ]); if (analysis.runes && binding.initial) { diff --git a/packages/svelte/src/compiler/utils/mapped_code.js b/packages/svelte/src/compiler/utils/mapped_code.js index 5fe215e435..a77c094f62 100644 --- a/packages/svelte/src/compiler/utils/mapped_code.js +++ b/packages/svelte/src/compiler/utils/mapped_code.js @@ -412,7 +412,7 @@ export function merge_with_preprocessor_map(result, options, source_name) { * @param {string} from * @param {string} to */ -export function get_relative_path(from, to) { +function get_relative_path(from, to) { // Don't use node's utils here to ensure the compiler is usable in a browser environment const from_parts = from.split(/[/\\]/); const to_parts = to.split(/[/\\]/); diff --git a/packages/svelte/src/constants.js b/packages/svelte/src/constants.js index 0015524532..736c9affb5 100644 --- a/packages/svelte/src/constants.js +++ b/packages/svelte/src/constants.js @@ -95,7 +95,6 @@ export const DOMBooleanAttributes = [ ]; export const namespace_svg = 'http://www.w3.org/2000/svg'; -export const namespace_html = 'http://www.w3.org/1999/xhtml'; // while `input` is also an interactive element, it is never moved by the browser, so we don't need to check for it export const interactive_elements = new Set([ diff --git a/packages/svelte/src/index-client.js b/packages/svelte/src/index-client.js index f7399d8685..2b22037457 100644 --- a/packages/svelte/src/index-client.js +++ b/packages/svelte/src/index-client.js @@ -1,4 +1,4 @@ -import { current_component_context, untrack } from './internal/client/runtime.js'; +import { current_component_context, flush_sync, untrack } from './internal/client/runtime.js'; import { is_array } from './internal/client/utils.js'; import { user_effect } from './internal/client/index.js'; @@ -167,19 +167,24 @@ function init_update_callbacks(context) { return (context.u ??= { a: [], b: [], m: [] }); } -// TODO bring implementations in here -// (except probably untrack — do we want to expose that, if there's also a rune?) +/** + * Synchronously flushes any pending state changes and those that result from it. + * @param {() => void} [fn] + * @returns {void} + */ +export function flushSync(fn) { + flush_sync(fn); +} + +export { unstate } from './internal/client/proxy.js'; + +export { hydrate, mount, unmount } from './internal/client/render.js'; + export { - flushSync, - mount, - hydrate, - tick, - unmount, - untrack, - unstate, - createRoot, - hasContext, getContext, getAllContexts, - setContext -} from './internal/client/index.js'; + hasContext, + setContext, + tick, + untrack +} from './internal/client/runtime.js'; diff --git a/packages/svelte/src/index-server.js b/packages/svelte/src/index-server.js index 836c4bb9bb..1baf3207ce 100644 --- a/packages/svelte/src/index-server.js +++ b/packages/svelte/src/index-server.js @@ -11,8 +11,7 @@ export { setContext, tick, unmount, - untrack, - createRoot + untrack } from './index-client.js'; /** @returns {void} */ diff --git a/packages/svelte/src/internal/client/dev/ownership.js b/packages/svelte/src/internal/client/dev/ownership.js index da5d2fac5b..358b56df22 100644 --- a/packages/svelte/src/internal/client/dev/ownership.js +++ b/packages/svelte/src/internal/client/dev/ownership.js @@ -9,7 +9,7 @@ const boundaries = {}; const chrome_pattern = /at (?:.+ \()?(.+):(\d+):(\d+)\)?$/; const firefox_pattern = /@(.+):(\d+):(\d+)$/; -export function get_stack() { +function get_stack() { const stack = new Error().stack; if (!stack) return null; diff --git a/packages/svelte/src/internal/client/dom/blocks/await.js b/packages/svelte/src/internal/client/dom/blocks/await.js index fb7fadc647..2aa5eb401a 100644 --- a/packages/svelte/src/internal/client/dom/blocks/await.js +++ b/packages/svelte/src/internal/client/dom/blocks/await.js @@ -1,7 +1,7 @@ import { is_promise } from '../../../common.js'; import { current_component_context, - flushSync, + flush_sync, set_current_component_context, set_current_effect, set_current_reaction @@ -48,7 +48,7 @@ export function await_block(anchor, get_input, pending_fn, then_fn, catch_fn) { // without this, the DOM does not update until two ticks after the promise, // resolves which is unexpected behaviour (and somewhat irksome to test) - flushSync(); + flush_sync(); return e; } diff --git a/packages/svelte/src/internal/client/dom/elements/attributes.js b/packages/svelte/src/internal/client/dom/elements/attributes.js index 3a0a5ca791..8501756b24 100644 --- a/packages/svelte/src/internal/client/dom/elements/attributes.js +++ b/packages/svelte/src/internal/client/dom/elements/attributes.js @@ -273,7 +273,7 @@ function split_srcset(srcset) { * @param {string | undefined | null} srcset * @returns {boolean} */ -export function srcset_url_equal(element, srcset) { +function srcset_url_equal(element, srcset) { var element_urls = split_srcset(element.srcset); var urls = split_srcset(srcset ?? ''); diff --git a/packages/svelte/src/internal/client/dom/elements/custom-element.js b/packages/svelte/src/internal/client/dom/elements/custom-element.js index c5b45d03c6..5ea42a9628 100644 --- a/packages/svelte/src/internal/client/dom/elements/custom-element.js +++ b/packages/svelte/src/internal/client/dom/elements/custom-element.js @@ -1,7 +1,7 @@ import { createClassComponent } from '../../../../legacy/legacy-client.js'; import { destroy_effect, render_effect } from '../../reactivity/effects.js'; import { append } from '../template.js'; -import { define_property } from '../../utils.js'; +import { define_property, object_keys } from '../../utils.js'; /** * @typedef {Object} CustomElementPropDefinition @@ -145,7 +145,7 @@ if (typeof HTMLElement === 'function') { // Reflect component props as attributes this.$$me = render_effect(() => { this.$$r = true; - for (const key of Object.keys(this.$$c)) { + for (const key of object_keys(this.$$c)) { if (!this.$$p_d[key]?.reflect) continue; this.$$d[key] = this.$$c[key]; const attribute_value = get_custom_element_value( @@ -205,7 +205,7 @@ if (typeof HTMLElement === 'function') { */ $$g_p(attribute_name) { return ( - Object.keys(this.$$p_d).find( + object_keys(this.$$p_d).find( (key) => this.$$p_d[key].attribute === attribute_name || (!this.$$p_d[key].attribute && key.toLowerCase() === attribute_name) @@ -290,12 +290,12 @@ export function create_custom_element( this.$$p_d = props_definition; } static get observedAttributes() { - return Object.keys(props_definition).map((key) => + return object_keys(props_definition).map((key) => (props_definition[key].attribute || key).toLowerCase() ); } }; - Object.keys(props_definition).forEach((prop) => { + object_keys(props_definition).forEach((prop) => { define_property(Class.prototype, prop, { get() { return this.$$c && prop in this.$$c ? this.$$c[prop] : this.$$d[prop]; diff --git a/packages/svelte/src/internal/client/dom/task.js b/packages/svelte/src/internal/client/dom/task.js index a14344fd26..e2f3082e90 100644 --- a/packages/svelte/src/internal/client/dom/task.js +++ b/packages/svelte/src/internal/client/dom/task.js @@ -22,18 +22,6 @@ function process_raf_task() { run_all(tasks); } -/** - * @param {() => void} fn - * @returns {void} - */ -export function schedule_raf_task(fn) { - if (!is_raf_queued) { - is_raf_queued = true; - requestAnimationFrame(process_raf_task); - } - current_raf_tasks.push(fn); -} - /** * Synchronously run any queued tasks. */ diff --git a/packages/svelte/src/internal/client/index.js b/packages/svelte/src/internal/client/index.js index 5d45144072..d03b719ca2 100644 --- a/packages/svelte/src/internal/client/index.js +++ b/packages/svelte/src/internal/client/index.js @@ -1,7 +1,106 @@ +export { add_owner, mark_module_start, mark_module_end } from './dev/ownership.js'; +export { await_block as await } from './dom/blocks/await.js'; +export { if_block as if } from './dom/blocks/if.js'; +export { key_block as key } from './dom/blocks/key.js'; +export { css_props } from './dom/blocks/css-props.js'; +export { each_keyed, each_indexed } from './dom/blocks/each.js'; +export { html } from './dom/blocks/html.js'; +export { snippet } from './dom/blocks/snippet.js'; +export { component } from './dom/blocks/svelte-component.js'; +export { element } from './dom/blocks/svelte-element.js'; +export { head } from './dom/blocks/svelte-head.js'; +export { action } from './dom/elements/actions.js'; +export { + remove_input_attr_defaults, + set_attribute, + set_attributes, + set_custom_element_data, + set_dynamic_element_attributes, + set_xlink_attribute +} from './dom/elements/attributes.js'; +export { set_class, set_svg_class, toggle_class } from './dom/elements/class.js'; +export { event, delegate } from './dom/elements/events.js'; +export { autofocus, remove_textarea_child } from './dom/elements/misc.js'; +export { set_style } from './dom/elements/style.js'; +export { animation, transition } from './dom/elements/transitions.js'; +export { bind_checked, bind_files, bind_group, bind_value } from './dom/elements/bindings/input.js'; +export { + bind_buffered, + bind_current_time, + bind_ended, + bind_muted, + bind_paused, + bind_playback_rate, + bind_played, + bind_ready_state, + bind_seekable, + bind_seeking, + bind_volume +} from './dom/elements/bindings/media.js'; +export { bind_online } from './dom/elements/bindings/navigator.js'; +export { bind_prop } from './dom/elements/bindings/props.js'; +export { bind_select_value, init_select, select_option } from './dom/elements/bindings/select.js'; +export { bind_element_size, bind_resize_observer } from './dom/elements/bindings/size.js'; +export { bind_this } from './dom/elements/bindings/this.js'; +export { bind_content_editable, bind_property } from './dom/elements/bindings/universal.js'; +export { bind_window_scroll, bind_window_size } from './dom/elements/bindings/window.js'; +export { + once, + preventDefault, + self, + stopImmediatePropagation, + stopPropagation, + trusted +} from './dom/legacy/event-modifiers.js'; +export { init } from './dom/legacy/lifecycle.js'; +export { + add_legacy_event_listener, + bubble_event, + reactive_import, + update_legacy_props +} from './dom/legacy/misc.js'; +export { + append, + comment, + svg_template, + svg_template_with_script, + template, + template_with_script, + text +} from './dom/template.js'; +export { derived, derived_safe_equal } from './reactivity/deriveds.js'; +export { + effect_active, + effect_root, + legacy_pre_effect, + legacy_pre_effect_reset, + render_effect, + user_effect, + user_pre_effect +} from './reactivity/effects.js'; +export { mutable_source, mutate, source, set } from './reactivity/sources.js'; +export { + prop, + rest_props, + spread_props, + update_pre_prop, + update_prop +} from './reactivity/props.js'; +export { + invalidate_store, + mutate_store, + store_get, + store_set, + store_unsub, + unsubscribe_on_destroy, + update_pre_store, + update_store +} from './reactivity/store.js'; +export { append_styles, sanitize_slots, set_text, slot, stringify } from './render.js'; export { get, invalidate_inner_signals, - flushSync, + flush_sync, tick, untrack, update, @@ -20,45 +119,17 @@ export { setContext, hasContext } from './runtime.js'; -export * from './dev/ownership.js'; -export { await_block as await } from './dom/blocks/await.js'; -export { if_block as if } from './dom/blocks/if.js'; -export { key_block as key } from './dom/blocks/key.js'; -export * from './dom/blocks/css-props.js'; -export * from './dom/blocks/each.js'; -export * from './dom/blocks/html.js'; -export * from './dom/blocks/snippet.js'; -export * from './dom/blocks/svelte-component.js'; -export * from './dom/blocks/svelte-element.js'; -export * from './dom/blocks/svelte-head.js'; -export * from './dom/elements/actions.js'; -export * from './dom/elements/attributes.js'; -export * from './dom/elements/class.js'; -export * from './dom/elements/events.js'; -export * from './dom/elements/misc.js'; -export * from './dom/elements/style.js'; -export * from './dom/elements/transitions.js'; -export * from './dom/elements/bindings/input.js'; -export * from './dom/elements/bindings/media.js'; -export * from './dom/elements/bindings/navigator.js'; -export * from './dom/elements/bindings/props.js'; -export * from './dom/elements/bindings/select.js'; -export * from './dom/elements/bindings/size.js'; -export * from './dom/elements/bindings/this.js'; -export * from './dom/elements/bindings/universal.js'; -export * from './dom/elements/bindings/window.js'; -export * from './dom/legacy/event-modifiers.js'; -export * from './dom/legacy/lifecycle.js'; -export * from './dom/legacy/misc.js'; -export * from './dom/template.js'; -export * from './reactivity/deriveds.js'; -export * from './reactivity/effects.js'; -export * from './reactivity/sources.js'; -export * from './reactivity/equality.js'; -export * from './reactivity/props.js'; -export * from './reactivity/store.js'; -export * from './render.js'; -export * from './validate.js'; +export { + add_snippet_symbol, + validate_component, + validate_dynamic_component, + validate_dynamic_element_tag, + validate_each_keys, + validate_prop_bindings, + validate_snippet, + validate_store, + validate_void_dynamic_element +} from './validate.js'; export { raf } from './timing.js'; export { proxy, unstate } from './proxy.js'; export { create_custom_element } from './dom/elements/custom-element.js'; diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index 20d4870825..4fd6fcad8a 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -9,7 +9,7 @@ import { get_descriptor, is_function } from '../utils.js'; import { mutable_source, set } from './sources.js'; import { derived } from './deriveds.js'; import { get, inspect_fn, is_signals_recorded, untrack } from '../runtime.js'; -import { safe_equals, safe_not_equal } from './equality.js'; +import { safe_equals } from './equality.js'; /** * @param {((value?: number) => number)} fn diff --git a/packages/svelte/src/internal/client/reactivity/sources.js b/packages/svelte/src/internal/client/reactivity/sources.js index 1f1c1814e8..db82edd740 100644 --- a/packages/svelte/src/internal/client/reactivity/sources.js +++ b/packages/svelte/src/internal/client/reactivity/sources.js @@ -6,7 +6,7 @@ import { current_effect, current_untracked_writes, current_untracking, - flushSync, + flush_sync, get, is_batching_effect, is_runes, @@ -62,16 +62,6 @@ export function mutable_source(initial_value) { return s; } -/** - * @template V - * @param {import('#client').Source} signal - * @param {V} value - * @returns {void} - */ -export function set_sync(signal, value) { - flushSync(() => set(signal, value)); -} - /** * @template V * @param {import('#client').Value} source diff --git a/packages/svelte/src/internal/client/render.js b/packages/svelte/src/internal/client/render.js index d7b07fa24d..aa2c0b4d55 100644 --- a/packages/svelte/src/internal/client/render.js +++ b/packages/svelte/src/internal/client/render.js @@ -81,16 +81,6 @@ export function stringify(value) { return typeof value === 'string' ? value : value == null ? '' : value + ''; } -// TODO 5.0 remove this -/** - * @deprecated Use `mount` or `hydrate` instead - */ -export function createRoot() { - throw new Error( - '`createRoot` has been removed. Use `mount` or `hydrate` instead. See the updated docs for more info: https://svelte-5-preview.vercel.app/docs/breaking-changes#components-are-no-longer-classes' - ); -} - /** * Mounts a component to the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component * diff --git a/packages/svelte/src/internal/client/runtime.js b/packages/svelte/src/internal/client/runtime.js index c1a61e0a75..8f8a57c676 100644 --- a/packages/svelte/src/internal/client/runtime.js +++ b/packages/svelte/src/internal/client/runtime.js @@ -628,15 +628,6 @@ export function flush_local_render_effects(effect) { flush_queued_effects(render_effects); } -/** - * Synchronously flushes any pending state changes and those that result from it. - * @param {() => void} [fn] - * @returns {void} - */ -export function flushSync(fn) { - flush_sync(fn); -} - /** * Internal version of `flushSync` with the option to not flush previous effects. * Returns the result of the passed function, if given. @@ -683,9 +674,9 @@ export function flush_sync(fn, flush_previous = true) { */ export async function tick() { await Promise.resolve(); - // By calling flushSync we guarantee that any pending state changes are applied after one tick. + // By calling flush_sync we guarantee that any pending state changes are applied after one tick. // TODO look into whether we can make flushing subsequent updates synchronously in the future. - flushSync(); + flush_sync(); } /** diff --git a/packages/svelte/src/internal/client/utils.js b/packages/svelte/src/internal/client/utils.js index 65a32cdd2b..6c6b9cc546 100644 --- a/packages/svelte/src/internal/client/utils.js +++ b/packages/svelte/src/internal/client/utils.js @@ -17,7 +17,6 @@ export var get_prototype_of = Object.getPrototypeOf; var map_prototype = Map.prototype; var map_set_method = map_prototype.set; var map_get_method = map_prototype.get; -var map_delete_method = map_prototype.delete; /** * @template K @@ -30,16 +29,6 @@ export function map_set(map, key, value) { map_set_method.call(map, key, value); } -/** - * @template K - * @template V - * @param {Map} map - * @param {K} key - */ -export function map_delete(map, key) { - map_delete_method.call(map, key); -} - /** * @template K * @template V diff --git a/packages/svelte/src/legacy/legacy-client.js b/packages/svelte/src/legacy/legacy-client.js index f3ba3ed204..7cdccb4737 100644 --- a/packages/svelte/src/legacy/legacy-client.js +++ b/packages/svelte/src/legacy/legacy-client.js @@ -1,5 +1,6 @@ +import { proxy } from '../internal/client/proxy.js'; +import { hydrate, mount, unmount } from '../internal/client/render.js'; import { define_property } from '../internal/client/utils.js'; -import * as $ from '../internal/client/index.js'; /** * Takes the same options as a Svelte 4 component and the component function and returns a Svelte 4 compatible component. @@ -69,8 +70,8 @@ class Svelte4Component { // Using proxy state here isn't completely mirroring the Svelte 4 behavior, because mutations to a property // cause fine-grained updates to only the places where that property is used, and not the entire property. // Reactive statements and actions (the things where this matters) are handling this properly regardless, so it should be fine in practise. - const props = $.proxy({ ...(options.props || {}), $$events: this.#events }, false); - this.#instance = (options.hydrate ? $.hydrate : $.mount)(options.component, { + const props = proxy({ ...(options.props || {}), $$events: this.#events }, false); + this.#instance = (options.hydrate ? hydrate : mount)(options.component, { target: options.target, props, context: options.context, @@ -96,7 +97,7 @@ class Svelte4Component { Object.assign(props, next); }; this.#instance.$destroy = () => { - $.unmount(this.#instance); + unmount(this.#instance); }; } diff --git a/packages/svelte/tests/runtime-legacy/shared.ts b/packages/svelte/tests/runtime-legacy/shared.ts index 6a1f99f69f..a0d00ec1c5 100644 --- a/packages/svelte/tests/runtime-legacy/shared.ts +++ b/packages/svelte/tests/runtime-legacy/shared.ts @@ -3,6 +3,7 @@ import { setImmediate } from 'node:timers/promises'; import glob from 'tiny-glob/sync.js'; import * as $ from 'svelte/internal/client'; import { createClassComponent } from 'svelte/legacy'; +import { flushSync } from 'svelte'; import { render } from 'svelte/server'; import { afterAll, assert, beforeAll } from 'vitest'; import { compile_directory } from '../helpers.js'; @@ -283,7 +284,7 @@ async function run_test_variant( } if (config.html) { - $.flushSync(); + flushSync(); assert_html_equal_with_options(target.innerHTML, config.html, { preserveComments: config.withoutNormalizeHtml === 'only-strip-comments' ? false : undefined, @@ -293,7 +294,7 @@ async function run_test_variant( try { if (config.test) { - $.flushSync(); + flushSync(); await config.test({ // @ts-expect-error TS doesn't get it assert: { diff --git a/packages/svelte/tests/signals/test.ts b/packages/svelte/tests/signals/test.ts index 54399db322..a6efb9aefa 100644 --- a/packages/svelte/tests/signals/test.ts +++ b/packages/svelte/tests/signals/test.ts @@ -1,4 +1,5 @@ import { describe, assert, it } from 'vitest'; +import { flushSync } from '../../src/index-client'; import * as $ from '../../src/internal/client/runtime'; import { effect, @@ -47,8 +48,8 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); - $.flushSync(() => set(count, 2)); + flushSync(() => set(count, 1)); + flushSync(() => set(count, 2)); assert.deepEqual(log, ['0:0', '1:2', '2:4']); }; @@ -68,8 +69,8 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); - $.flushSync(() => set(count, 2)); + flushSync(() => set(count, 1)); + flushSync(() => set(count, 2)); assert.deepEqual(log, ['A:0:0', 'B:0', 'A:1:2', 'B:2', 'A:2:4', 'B:4']); }; @@ -89,8 +90,8 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); - $.flushSync(() => set(count, 2)); + flushSync(() => set(count, 1)); + flushSync(() => set(count, 2)); assert.deepEqual(log, ['A:0', 'B:0:0', 'A:2', 'B:1:2', 'A:4', 'B:2:4']); }; @@ -107,8 +108,8 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); - $.flushSync(() => set(count, 2)); + flushSync(() => set(count, 1)); + flushSync(() => set(count, 2)); assert.deepEqual(log, [0, 2, 4]); }; @@ -126,8 +127,8 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); - $.flushSync(() => set(count, 2)); + flushSync(() => set(count, 1)); + flushSync(() => set(count, 2)); assert.deepEqual(log, [0, 4, 8]); }; @@ -158,18 +159,18 @@ describe('signals', () => { }); return () => { - $.flushSync(); + flushSync(); let i = 2; while (--i) { res.length = 0; set(B, 1); set(A, 1 + i * 2); - $.flushSync(); + flushSync(); set(A, 2 + i * 2); set(B, 2); - $.flushSync(); + flushSync(); assert.equal(res.length, 4); assert.deepEqual(res, [3198, 1601, 3195, 1598]); @@ -191,13 +192,13 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); + flushSync(() => set(count, 1)); // Ensure we're not leaking consumers assert.deepEqual(count.reactions?.length, 1); - $.flushSync(() => set(count, 2)); + flushSync(() => set(count, 2)); // Ensure we're not leaking consumers assert.deepEqual(count.reactions?.length, 1); - $.flushSync(() => set(count, 3)); + flushSync(() => set(count, 3)); // Ensure we're not leaking consumers assert.deepEqual(count.reactions?.length, 1); assert.deepEqual(log, [0, 1, 2, 3]); @@ -220,11 +221,11 @@ describe('signals', () => { $.get(c); - $.flushSync(() => set(a, 1)); + flushSync(() => set(a, 1)); $.get(c); - $.flushSync(() => set(b, 1)); + flushSync(() => set(b, 1)); $.get(c); @@ -255,11 +256,11 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); - $.flushSync(() => set(count, 2)); - $.flushSync(() => set(count, 3)); - $.flushSync(() => set(count, 4)); - $.flushSync(() => set(count, 0)); + flushSync(() => set(count, 1)); + flushSync(() => set(count, 2)); + flushSync(() => set(count, 3)); + flushSync(() => set(count, 4)); + flushSync(() => set(count, 0)); // Ensure we're not leaking consumers assert.deepEqual(count.reactions?.length, 1); assert.deepEqual(log, [0, 2, 'limit', 0]); @@ -285,7 +286,7 @@ describe('signals', () => { }); return () => { - $.flushSync(); + flushSync(); assert.deepEqual(log, [[], []]); }; }); @@ -307,7 +308,7 @@ describe('signals', () => { }); return () => { - $.flushSync(); + flushSync(); assert.deepEqual(log, [[{}], [{}]]); }; }); @@ -324,7 +325,7 @@ describe('signals', () => { return () => { let errored = false; try { - $.flushSync(); + flushSync(); } catch (e: any) { assert.include(e.message, 'ERR_SVELTE_TOO_MANY_UPDATES'); errored = true; @@ -345,7 +346,7 @@ describe('signals', () => { return () => { let errored = false; try { - $.flushSync(); + flushSync(); } catch (e: any) { assert.include(e.message, 'ERR_SVELTE_TOO_MANY_UPDATES'); errored = true; @@ -370,8 +371,8 @@ describe('signals', () => { }); return () => { - $.flushSync(() => set(count, 1)); - $.flushSync(() => set(count, 2)); + flushSync(() => set(count, 1)); + flushSync(() => set(count, 2)); assert.equal(teardown, 1); }; }); diff --git a/packages/svelte/types/index.d.ts b/packages/svelte/types/index.d.ts index 4ac4f995cb..00b318b8fd 100644 --- a/packages/svelte/types/index.d.ts +++ b/packages/svelte/types/index.d.ts @@ -287,12 +287,13 @@ declare module 'svelte' { * @deprecated Use `$effect` instead — see https://svelte-5-preview.vercel.app/docs/deprecations#beforeupdate-and-afterupdate * */ export function afterUpdate(fn: () => void): void; + /** + * Synchronously flushes any pending state changes and those that result from it. + * */ + export function flushSync(fn?: (() => void) | undefined): void; /** Anything except a function */ type NotFunction = T extends Function ? never : T; - /** - * @deprecated Use `mount` or `hydrate` instead - */ - export function createRoot(): void; + export function unstate(value: T): T; /** * Mounts a component to the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component * @@ -320,10 +321,6 @@ declare module 'svelte' { * Unmounts a component that was previously mounted using `mount` or `hydrate`. * */ export function unmount(component: Record): void; - /** - * Synchronously flushes any pending state changes and those that result from it. - * */ - export function flushSync(fn?: (() => void) | undefined): void; /** * Returns a promise that resolves once any pending state changes have been applied. * */ @@ -366,7 +363,6 @@ declare module 'svelte' { * https://svelte.dev/docs/svelte#getallcontexts * */ export function getAllContexts = Map>(): T; - export function unstate(value: T): T; } declare module 'svelte/action' {