remove symbol and class support

pull/9776/head
Dominic Gannaway 3 years ago
parent 183b1fb87f
commit fb732760fb

@ -21,7 +21,6 @@ import { READONLY_SYMBOL } from './readonly.js';
/** @typedef {Record<string | symbol, any> & { [STATE_SYMBOL]: Metadata }} StateObject */
export const STATE_SYMBOL = Symbol('$state');
export const UNSTATE_SYMBOL = Symbol('unstate');
const object_prototype = Object.prototype;
const array_prototype = Array.prototype;
@ -56,43 +55,35 @@ export function proxy(value) {
* @returns {Record<string | symbol, any>}
*/
function unwrap(value, already_unwrapped = new Map()) {
if (typeof value === 'object' && value != null && !is_frozen(value)) {
if (typeof value === 'object' && value != null && !is_frozen(value) && STATE_SYMBOL in value) {
const unwrapped = already_unwrapped.get(value);
if (unwrapped !== undefined) {
return unwrapped;
}
if (STATE_SYMBOL in value) {
if (is_array(value)) {
/** @type {Record<string | symbol, any>} */
const array = [];
already_unwrapped.set(value, array);
for (const element of value) {
array.push(unwrap(element, already_unwrapped));
}
return array;
} else {
/** @type {Record<string | symbol, any>} */
const obj = {};
const keys = object_keys(value);
const descriptors = get_descriptors(value);
already_unwrapped.set(value, obj);
for (const key of keys) {
if (descriptors[key].get) {
define_property(obj, key, descriptors[key]);
} else {
/** @type {T} */
const property = value[key];
obj[key] = unwrap(property, already_unwrapped);
}
if (is_array(value)) {
/** @type {Record<string | symbol, any>} */
const array = [];
already_unwrapped.set(value, array);
for (const element of value) {
array.push(unwrap(element, already_unwrapped));
}
return array;
} else {
/** @type {Record<string | symbol, any>} */
const obj = {};
const keys = object_keys(value);
const descriptors = get_descriptors(value);
already_unwrapped.set(value, obj);
for (const key of keys) {
if (descriptors[key].get) {
define_property(obj, key, descriptors[key]);
} else {
/** @type {T} */
const property = value[key];
obj[key] = unwrap(property, already_unwrapped);
}
return obj;
}
}
const unstate_fn = /** @type {undefined | ((this: StateObject) => T)} */ (
value[UNSTATE_SYMBOL]
);
if (typeof unstate_fn === 'function') {
return unstate_fn.call(value);
return obj;
}
}
return value;

@ -45,7 +45,7 @@ export * from './client/each.js';
export * from './client/render.js';
export * from './client/validate.js';
export { raf } from './client/timing.js';
export { proxy, readonly, unstate, UNSTATE_SYMBOL } from './client/proxy/proxy.js';
export { proxy, readonly, unstate } from './client/proxy/proxy.js';
export { create_custom_element } from './client/custom-element.js';

@ -262,6 +262,5 @@ export {
tick,
untrack,
unstate,
onDestroy,
UNSTATE_SYMBOL
onDestroy
} from '../internal/index.js';

@ -1,12 +0,0 @@
import { test } from '../../test';
export default test({
html: `<button>[{"data":{"a":0}}]</button>`,
async test({ assert, target }) {
const btn = target.querySelector('button');
await btn?.click();
assert.htmlEqual(target.innerHTML, `<button>[{"data":{"a":0}},{"data":{"a":1}}]</button>`);
}
});

@ -1,22 +0,0 @@
<script>
import { unstate, UNSTATE_SYMBOL } from 'svelte';
class Item {
data = $state()
constructor(a) {
this.data = { a };
}
[UNSTATE_SYMBOL]() {
debugger
return {
data: unstate(this.data)
};
}
}
let items = $state([new Item(0)]);
</script>
<button on:click={() => items.push(new Item(items.length))}>{JSON.stringify(structuredClone(unstate(items)))}</button>

@ -42,31 +42,4 @@ To remove reactivity from objects and arrays created with `$state`, use `unstate
This is handy when you want to pass some state to an external library or API that doesn't expect a reactive object such as `structuredClone`.
For classes that might contain `$state`, the `UNSTATE_SYMBOL` can be imported and applied as a class method to enable deep unwrapped of reactive state
through class components:
```svelte
<script>
import { unstate, UNSTATE_SYMBOL } from 'svelte';
class Collection {
#items = $state([]);
add(item) {
this.#items.push(item);
}
[UNSTATE_SYMBOL]() {
return { items: unstate(this.#items) };
}
}
const collection = new Collection();
collection.add('Hello world');
// Will log { items: ['Hello world'] }
console.log(unstate(collection));
</script>
```
> Note that `unstate` will return a new object from the input when removing reactivity. If the object passed isn't reactive, it will be returned as is.

Loading…
Cancel
Save