diff --git a/documentation/docs/07-misc/.generated/browser-support-features.md b/documentation/docs/07-misc/.generated/browser-support-features.md index 1ed6da9e61..369d3fd40e 100644 --- a/documentation/docs/07-misc/.generated/browser-support-features.md +++ b/documentation/docs/07-misc/.generated/browser-support-features.md @@ -1,7 +1,3 @@ -| Feature | Chrome/Edge | Firefox | Safari | -| - | - | - | - | -| [`$state.snapshot`](/docs/svelte/$state#$state.snapshot) | 98 | 94 | 15.4 | -| [`bind:devicePixelContentBoxSize`](/docs/svelte/bind#Dimensions) | — | 93 | not supported | -| [`flip` from `svelte/animate`](/docs/svelte/svelte-animate#flip) | — | 126 | — | +_No features currently require browser versions newer than the runtime floor._ \ No newline at end of file diff --git a/documentation/docs/07-misc/.generated/browser-support.md b/documentation/docs/07-misc/.generated/browser-support.md index 1e8b962856..02f9c05ffa 100644 --- a/documentation/docs/07-misc/.generated/browser-support.md +++ b/documentation/docs/07-misc/.generated/browser-support.md @@ -2,14 +2,12 @@ | Browser | Minimum version | | - | - | -| Chrome/Edge | 87 | -| Firefox | 83 | -| Safari | 14 | -| Opera | 73 | -| Opera (Android) | 62 | -| Samsung Internet | 14.0 | -| Android WebView | 87 | +| Chrome/Edge | 148 | +| Firefox | 151 | +| Safari | 26.5 | +| Opera | 132 | +| Android WebView | 148 | | Internet Explorer | not supported | -> [!NOTE] This equates to a Baseline target of 2020. \ No newline at end of file +> [!NOTE] This equates to a Baseline target of 2026. \ No newline at end of file diff --git a/packages/svelte/src/internal/client/warp.js b/packages/svelte/src/internal/client/warp.js index 930aa64fd9..7b5e8a19b9 100644 --- a/packages/svelte/src/internal/client/warp.js +++ b/packages/svelte/src/internal/client/warp.js @@ -1,6 +1,7 @@ /** @import { WarpKey } from '#shared' */ import { async_mode_flag } from '../flags/index.js'; import * as e from './errors.js'; +import { get_or_insert, get_or_insert_computed } from '../shared/utils.js'; /** * A `Map` whose contents are sent from the server to the client. Values added to it @@ -76,10 +77,7 @@ export class Warp { * @returns {V} */ getOrInsert(key, value) { - const values = this.#values(); - if (values.has(key)) return /** @type {V} */ (values.get(key)); - values.set(key, value); - return value; + return get_or_insert(this.#values(), key, value); } /** @@ -89,11 +87,7 @@ export class Warp { * @returns {V} */ getOrInsertComputed(key, callback) { - const values = this.#values(); - if (values.has(key)) return /** @type {V} */ (values.get(key)); - const value = callback(key); - values.set(key, value); - return value; + return get_or_insert_computed(this.#values(), key, callback); } /** diff --git a/packages/svelte/src/internal/server/warp.js b/packages/svelte/src/internal/server/warp.js index 0f432f4ece..8b5975dbc7 100644 --- a/packages/svelte/src/internal/server/warp.js +++ b/packages/svelte/src/internal/server/warp.js @@ -5,6 +5,7 @@ import { async_mode_flag } from '../flags/index.js'; import { get_render_context } from './render-context.js'; import { get_user_code_location } from './dev.js'; import * as e from './errors.js'; +import { get_or_insert_computed } from '../shared/utils.js'; /** * A `Map` whose contents are sent from the server to the client. Values added to it @@ -71,10 +72,10 @@ export class Warp { const store = get_store(); const values = /** @type {Map} */ (get_values(store, this.#id)); - if (values.has(key)) return /** @type {V} */ (values.get(key)); - - set(store, this.#id, key, value); - return value; + return get_or_insert_computed(values, key, () => { + record(store, this.#id, key, value); + return value; + }); } /** @@ -87,11 +88,11 @@ export class Warp { const store = get_store(); const values = /** @type {Map} */ (get_values(store, this.#id)); - if (values.has(key)) return /** @type {V} */ (values.get(key)); - - const value = callback(key); - set(store, this.#id, key, value); - return value; + return get_or_insert_computed(values, key, (key) => { + const value = callback(key); + record(store, this.#id, key, value); + return value; + }); } /** @@ -174,12 +175,23 @@ function get_values(store, id) { * @param {unknown} value */ function set(store, id, key, value) { + record(store, id, key, value); + get_values(store, id).set(key, value); +} + +/** + * Does everything that needs to happen when a value is added, other than actually adding it. + * Throws if it can't be added, so that `getOrInsertComputed` doesn't add it either + * @param {WarpStore} store + * @param {string} id + * @param {WarpKey} key + * @param {unknown} value + */ +function record(store, id, key, value) { if (store.emitted) { e.warp_set_after_render(id, String(key)); } - get_values(store, id).set(key, value); - if (DEV) { let stacks = store.stacks.get(id); diff --git a/packages/svelte/src/internal/shared/utils.js b/packages/svelte/src/internal/shared/utils.js index 393b51383e..e087c0de76 100644 --- a/packages/svelte/src/internal/shared/utils.js +++ b/packages/svelte/src/internal/shared/utils.js @@ -13,6 +13,9 @@ export var array_prototype = Array.prototype; export var get_prototype_of = Object.getPrototypeOf; export var is_extensible = Object.isExtensible; export var has_own_property = Object.prototype.hasOwnProperty; +// these are new, and not available everywhere yet +var map_get_or_insert = /** @type {any} */ (Map.prototype).getOrInsert; +var map_get_or_insert_computed = /** @type {any} */ (Map.prototype).getOrInsertComputed; /** * @param {any} thing @@ -24,6 +27,40 @@ export function is_function(thing) { export const noop = () => {}; +/** + * `map.getOrInsert(key, value)`, using the native implementation if there is one + * @template K, V + * @param {Map} map + * @param {K} key + * @param {V} value + * @returns {V} + */ +export function get_or_insert(map, key, value) { + if (map_get_or_insert !== undefined) return map_get_or_insert.call(map, key, value); + if (map.has(key)) return /** @type {V} */ (map.get(key)); + map.set(key, value); + return value; +} + +/** + * `map.getOrInsertComputed(key, callback)`, using the native implementation if there is one + * @template K, V + * @param {Map} map + * @param {K} key + * @param {(key: K) => V} callback + * @returns {V} + */ +export function get_or_insert_computed(map, key, callback) { + if (map_get_or_insert_computed !== undefined) { + return map_get_or_insert_computed.call(map, key, callback); + } + + if (map.has(key)) return /** @type {V} */ (map.get(key)); + const value = callback(key); + map.set(key, value); + return value; +} + // Adapted from https://github.com/then/is-promise/blob/master/index.js // Distributed under MIT License https://github.com/then/is-promise/blob/master/LICENSE