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