perf: use native `Map.prototype.getOrInsert(Computed)` in `Warp` when available

elliott/warp-core
Elliott Johnson 12 hours ago
parent f4a45dcb17
commit 39fe99f992
No known key found for this signature in database

@ -1,7 +1,3 @@
<!-- generated in ../../../../../packages/svelte/scripts/generate-browser-support.ts. do not edit -->
| Feature | Chrome/Edge | Firefox | Safari |
| - | - | - | - |
| [`$state.snapshot`](/docs/svelte/$state#$state.snapshot) | 98 | 94 | 15.4 |
| [`bind:devicePixelContentBoxSize`](/docs/svelte/bind#Dimensions) | <span style="color: var(--sk-fg-4)">—</span> | 93 | not supported |
| [`flip` from `svelte/animate`](/docs/svelte/svelte-animate#flip) | <span style="color: var(--sk-fg-4)">—</span> | 126 | <span style="color: var(--sk-fg-4)">—</span> |
_No features currently require browser versions newer than the runtime floor._

@ -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 <a href="https://web-platform-dx.github.io/baseline/">Baseline</a> target of 2020.
> [!NOTE] This equates to a <a href="https://web-platform-dx.github.io/baseline/">Baseline</a> target of 2026.

@ -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);
}
/**

@ -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<K, V>} */ (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<K, V>} */ (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);

@ -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<K, V>} 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<K, V>} 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

Loading…
Cancel
Save