@@ -18,7 +18,6 @@ import {
1818 get_prototype_of ,
1919 is_array ,
2020 is_frozen ,
21- object_keys ,
2221 object_prototype
2322} from './utils.js' ;
2423
@@ -33,28 +32,29 @@ export const READONLY_SYMBOL = Symbol('readonly');
3332 */
3433export function proxy ( value , immutable = true ) {
3534 if ( typeof value === 'object' && value != null && ! is_frozen ( value ) ) {
35+ // If we have an existing proxy, return it...
3636 if ( STATE_SYMBOL in value ) {
3737 const metadata = /** @type {import('./types.js').ProxyMetadata<T> } */ ( value [ STATE_SYMBOL ] ) ;
38- // Check that the incoming value is the same proxy that this state symbol was created for:
39- // If someone copies over the state symbol to a new object (using Reflect.ownKeys) the referenced
40- // proxy could be stale and we should not return it.
38+ // ...unless the proxy belonged to a different object, because
39+ // someone copied the state symbol using `Reflect.ownKeys(...)`
4140 if ( metadata . t === value || metadata . p === value ) return metadata . p ;
4241 }
4342
4443 const prototype = get_prototype_of ( value ) ;
4544
4645 // TODO handle Map and Set as well
4746 if ( prototype === object_prototype || prototype === array_prototype ) {
48- const proxy = new Proxy (
49- value ,
50- /** @type {ProxyHandler<import('./types.js').ProxyStateObject<T>> } */ ( state_proxy_handler )
51- ) ;
47+ const proxy = new Proxy ( value , state_proxy_handler ) ;
48+
5249 define_property ( value , STATE_SYMBOL , {
53- value : init (
54- /** @type {import('./types.js').ProxyStateObject<T> } */ ( value ) ,
55- /** @type {import('./types.js').ProxyStateObject<T> } */ ( proxy ) ,
56- immutable
57- ) ,
50+ value : /** @type {import('./types.js').ProxyMetadata } */ ( {
51+ s : new Map ( ) ,
52+ v : source ( 0 ) ,
53+ a : is_array ( value ) ,
54+ i : immutable ,
55+ p : proxy ,
56+ t : value
57+ } ) ,
5858 writable : true ,
5959 enumerable : false
6060 } ) ;
@@ -72,12 +72,13 @@ export function proxy(value, immutable = true) {
7272 * @param {Map<T, Record<string | symbol, any>> } already_unwrapped
7373 * @returns {Record<string | symbol, any> }
7474 */
75- function unwrap ( value , already_unwrapped = new Map ( ) ) {
75+ function unwrap ( value , already_unwrapped ) {
7676 if ( typeof value === 'object' && value != null && STATE_SYMBOL in value ) {
7777 const unwrapped = already_unwrapped . get ( value ) ;
7878 if ( unwrapped !== undefined ) {
7979 return unwrapped ;
8080 }
81+
8182 if ( is_array ( value ) ) {
8283 /** @type {Record<string | symbol, any> } */
8384 const array = [ ] ;
@@ -92,6 +93,7 @@ function unwrap(value, already_unwrapped = new Map()) {
9293 const keys = Reflect . ownKeys ( value ) ;
9394 const descriptors = get_descriptors ( value ) ;
9495 already_unwrapped . set ( value , obj ) ;
96+
9597 for ( const key of keys ) {
9698 if ( key === STATE_SYMBOL || ( DEV && key === READONLY_SYMBOL ) ) continue ;
9799 if ( descriptors [ key ] . get ) {
@@ -102,6 +104,7 @@ function unwrap(value, already_unwrapped = new Map()) {
102104 obj [ key ] = unwrap ( property , already_unwrapped ) ;
103105 }
104106 }
107+
105108 return obj ;
106109 }
107110 }
@@ -115,27 +118,12 @@ function unwrap(value, already_unwrapped = new Map()) {
115118 * @returns {T }
116119 */
117120export function unstate ( value ) {
118- return /** @type {T } */ ( unwrap ( /** @type {import('./types.js').ProxyStateObject } */ ( value ) ) ) ;
119- }
120-
121- /**
122- * @param {import('./types.js').ProxyStateObject } value
123- * @param {import('./types.js').ProxyStateObject } proxy
124- * @param {boolean } immutable
125- * @returns {import('./types.js').ProxyMetadata }
126- */
127- function init ( value , proxy , immutable ) {
128- return {
129- s : new Map ( ) ,
130- v : source ( 0 ) ,
131- a : is_array ( value ) ,
132- i : immutable ,
133- p : proxy ,
134- t : value
135- } ;
121+ return /** @type {T } */ (
122+ unwrap ( /** @type {import('./types.js').ProxyStateObject } */ ( value ) , new Map ( ) )
123+ ) ;
136124}
137125
138- /** @type {ProxyHandler<import('./types.js').ProxyStateObject> } */
126+ /** @type {ProxyHandler<import('./types.js').ProxyStateObject<any> > } */
139127const state_proxy_handler = {
140128 defineProperty ( target , prop , descriptor ) {
141129 if ( descriptor . value ) {
0 commit comments