small tidy up (#10400)

Co-authored-by: Rich Harris <rich.harris@vercel.com>
pull/10402/head
Rich Harris 9 months ago committed by GitHub
parent 1381d1937c
commit 8ebc472ef5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -18,7 +18,6 @@ import {
get_prototype_of, get_prototype_of,
is_array, is_array,
is_frozen, is_frozen,
object_keys,
object_prototype object_prototype
} from './utils.js'; } from './utils.js';
@ -33,11 +32,11 @@ export const READONLY_SYMBOL = Symbol('readonly');
*/ */
export function proxy(value, immutable = true) { export function proxy(value, immutable = true) {
if (typeof value === 'object' && value != null && !is_frozen(value)) { if (typeof value === 'object' && value != null && !is_frozen(value)) {
// If we have an existing proxy, return it...
if (STATE_SYMBOL in value) { if (STATE_SYMBOL in value) {
const metadata = /** @type {import('./types.js').ProxyMetadata<T>} */ (value[STATE_SYMBOL]); const metadata = /** @type {import('./types.js').ProxyMetadata<T>} */ (value[STATE_SYMBOL]);
// Check that the incoming value is the same proxy that this state symbol was created for: // ...unless the proxy belonged to a different object, because
// If someone copies over the state symbol to a new object (using Reflect.ownKeys) the referenced // someone copied the state symbol using `Reflect.ownKeys(...)`
// proxy could be stale and we should not return it.
if (metadata.t === value || metadata.p === value) return metadata.p; if (metadata.t === value || metadata.p === value) return metadata.p;
} }
@ -45,16 +44,17 @@ export function proxy(value, immutable = true) {
// TODO handle Map and Set as well // TODO handle Map and Set as well
if (prototype === object_prototype || prototype === array_prototype) { if (prototype === object_prototype || prototype === array_prototype) {
const proxy = new Proxy( const proxy = new Proxy(value, state_proxy_handler);
value,
/** @type {ProxyHandler<import('./types.js').ProxyStateObject<T>>} */ (state_proxy_handler)
);
define_property(value, STATE_SYMBOL, { define_property(value, STATE_SYMBOL, {
value: init( value: /** @type {import('./types.js').ProxyMetadata} */ ({
/** @type {import('./types.js').ProxyStateObject<T>} */ (value), s: new Map(),
/** @type {import('./types.js').ProxyStateObject<T>} */ (proxy), v: source(0),
immutable a: is_array(value),
), i: immutable,
p: proxy,
t: value
}),
writable: true, writable: true,
enumerable: false enumerable: false
}); });
@ -72,12 +72,13 @@ export function proxy(value, immutable = true) {
* @param {Map<T, Record<string | symbol, any>>} already_unwrapped * @param {Map<T, Record<string | symbol, any>>} already_unwrapped
* @returns {Record<string | symbol, any>} * @returns {Record<string | symbol, any>}
*/ */
function unwrap(value, already_unwrapped = new Map()) { function unwrap(value, already_unwrapped) {
if (typeof value === 'object' && value != null && STATE_SYMBOL in value) { if (typeof value === 'object' && value != null && STATE_SYMBOL in value) {
const unwrapped = already_unwrapped.get(value); const unwrapped = already_unwrapped.get(value);
if (unwrapped !== undefined) { if (unwrapped !== undefined) {
return unwrapped; return unwrapped;
} }
if (is_array(value)) { if (is_array(value)) {
/** @type {Record<string | symbol, any>} */ /** @type {Record<string | symbol, any>} */
const array = []; const array = [];
@ -92,6 +93,7 @@ function unwrap(value, already_unwrapped = new Map()) {
const keys = Reflect.ownKeys(value); const keys = Reflect.ownKeys(value);
const descriptors = get_descriptors(value); const descriptors = get_descriptors(value);
already_unwrapped.set(value, obj); already_unwrapped.set(value, obj);
for (const key of keys) { for (const key of keys) {
if (key === STATE_SYMBOL || (DEV && key === READONLY_SYMBOL)) continue; if (key === STATE_SYMBOL || (DEV && key === READONLY_SYMBOL)) continue;
if (descriptors[key].get) { if (descriptors[key].get) {
@ -102,6 +104,7 @@ function unwrap(value, already_unwrapped = new Map()) {
obj[key] = unwrap(property, already_unwrapped); obj[key] = unwrap(property, already_unwrapped);
} }
} }
return obj; return obj;
} }
} }
@ -115,27 +118,12 @@ function unwrap(value, already_unwrapped = new Map()) {
* @returns {T} * @returns {T}
*/ */
export function unstate(value) { export function unstate(value) {
return /** @type {T} */ (unwrap(/** @type {import('./types.js').ProxyStateObject} */ (value))); return /** @type {T} */ (
} unwrap(/** @type {import('./types.js').ProxyStateObject} */ (value), new Map())
);
/**
* @param {import('./types.js').ProxyStateObject} value
* @param {import('./types.js').ProxyStateObject} proxy
* @param {boolean} immutable
* @returns {import('./types.js').ProxyMetadata}
*/
function init(value, proxy, immutable) {
return {
s: new Map(),
v: source(0),
a: is_array(value),
i: immutable,
p: proxy,
t: value
};
} }
/** @type {ProxyHandler<import('./types.js').ProxyStateObject>} */ /** @type {ProxyHandler<import('./types.js').ProxyStateObject<any>>} */
const state_proxy_handler = { const state_proxy_handler = {
defineProperty(target, prop, descriptor) { defineProperty(target, prop, descriptor) {
if (descriptor.value) { if (descriptor.value) {

Loading…
Cancel
Save