fix: ensure `$state.snapshot` never errors

Snapshotting can error on un-cloneable objects. It's not practical to error in this case; often there's no way out of this for users, so it makes sense to return the original value in that case, and warn in dev mode about it.

closes #12438
pull/12445/head
Simon Holthausen 2 years ago
parent b27113ddfd
commit f21163a5ae

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: ensure `$state.snapshot` never errors

@ -1,3 +1,7 @@
## dynamic_void_element_content
> `<svelte:element this="%tag%">` is a void element — it cannot have content
## state_snapshot_uncloneable
> An object could not be cloned with $state.snapshot, the original value will be returned

@ -1,4 +1,6 @@
/** @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';
/**
@ -50,5 +52,18 @@ function clone(value, cloned) {
}
}
return /** @type {Snapshot<T>} */ (structuredClone(value));
if (value instanceof EventTarget) {
// can't be cloned
return /** @type {Snapshot<T>} */ (value);
}
try {
return /** @type {Snapshot<T>} */ (structuredClone(value));
} catch (e) {
if (DEV) {
w.state_snapshot_uncloneable();
console.warn(e);
}
return /** @type {Snapshot<T>} */ (value);
}
}

@ -17,3 +17,15 @@ export function dynamic_void_element_content(tag) {
console.warn("dynamic_void_element_content");
}
}
/**
* An object could not be cloned with $state.snapshot, the original value will be returned
*/
export function state_snapshot_uncloneable() {
if (DEV) {
console.warn(`%c[svelte] state_snapshot_uncloneable\n%cAn object could not be cloned with $state.snapshot, the original value will be returned`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("state_snapshot_uncloneable");
}
}
Loading…
Cancel
Save