Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 79x 79x 79x 79x 79x 79x 1x 1x 79x 2x 2x 2x 2x 2x 2x 2x 2x 2x 79x 79x 79x 2x 2x 2x 2x 2x 2x 2x 2x 2x 339x 339x 154x 154x 149x 154x 85x 85x 85x 85x 199x 199x 85x 85x 85x 64x 154x 43x 43x 43x 43x 43x 52x 52x 52x 43x 43x 43x 21x 154x 2x 2x 19x 154x 9x 9x 9x 9x 9x 9x 9x 154x 195x 339x 195x 195x 195x 339x 113x 113x 113x 113x 113x 113x 339x | /** @import { Snapshot } from './types' */ import { DEV } from 'esm-env'; import * as w from './warnings.js'; import { get_prototype_of, is_array, object_prototype } from './utils.js'; /** * In dev, we keep track of which properties could not be cloned. In prod * we don't bother, but we keep a dummy array around so that the * signature stays the same * @type {string[]} */ const empty = []; /** * @template T * @param {T} value * @param {boolean} [skip_warning] * @returns {Snapshot<T>} */ export function snapshot(value, skip_warning = false) { if (DEV) { /** @type {string[]} */ const paths = []; const copy = clone(value, new Map(), '', paths); if (paths.length === 1 && paths[0] === '' && !skip_warning) { // value could not be cloned w.state_snapshot_uncloneable(); } else if (paths.length > 0 && !skip_warning) { // some properties could not be cloned const slice = paths.length > 10 ? paths.slice(0, 7) : paths.slice(0, 10); const excess = paths.length - slice.length; let uncloned = slice.map((path) => `- <value>${path}`).join('\n'); if (excess > 0) uncloned += `\n- ...and ${excess} more`; w.state_snapshot_uncloneable(uncloned); } return copy; } return clone(value, new Map(), '', empty); } /** * @template T * @param {T} value * @param {Map<T, Snapshot<T>>} cloned * @param {string} path * @param {string[]} paths * @returns {Snapshot<T>} */ function clone(value, cloned, path, paths) { if (typeof value === 'object' && value !== null) { const unwrapped = cloned.get(value); if (unwrapped !== undefined) return unwrapped; if (is_array(value)) { const copy = /** @type {Snapshot<any>} */ ([]); cloned.set(value, copy); for (let i = 0; i < value.length; i += 1) { copy.push(clone(value[i], cloned, DEV ? `${path}[${i}]` : path, paths)); } return copy; } if (get_prototype_of(value) === object_prototype) { /** @type {Snapshot<any>} */ const copy = {}; cloned.set(value, copy); for (var key in value) { // @ts-expect-error copy[key] = clone(value[key], cloned, DEV ? `${path}.${key}` : path, paths); } return copy; } if (value instanceof Date) { return /** @type {Snapshot<T>} */ (structuredClone(value)); } if (typeof (/** @type {T & { toJSON?: any } } */ (value).toJSON) === 'function') { return clone( /** @type {T & { toJSON(): any } } */ (value).toJSON(), cloned, DEV ? `${path}.toJSON()` : path, paths ); } } if (value instanceof EventTarget) { // can't be cloned return /** @type {Snapshot<T>} */ (value); } try { return /** @type {Snapshot<T>} */ (structuredClone(value)); } catch (e) { if (DEV) { paths.push(path); } return /** @type {Snapshot<T>} */ (value); } } |