@@ -12,64 +12,69 @@ import {
12
12
* @param {string } serialized
13
13
*/
14
14
export function parse ( serialized ) {
15
- const values = JSON . parse ( serialized ) ;
15
+ const parsed = JSON . parse ( serialized ) ;
16
16
17
- if ( typeof values === 'number' ) return get_value ( values ) ;
17
+ if ( typeof parsed === 'number' ) return hydrate ( parsed ) ;
18
+
19
+ const values = /** @type {any[] } */ ( parsed ) ;
20
+ const hydrated = Array ( values . length ) ;
18
21
19
22
/** @param {number } index */
20
- function get_value ( index ) {
23
+ function hydrate ( index ) {
21
24
if ( index === UNDEFINED ) return undefined ;
22
25
if ( index === NAN ) return NaN ;
23
26
if ( index === POSITIVE_INFINITY ) return Infinity ;
24
27
if ( index === NEGATIVE_INFINITY ) return - Infinity ;
25
28
if ( index === NEGATIVE_ZERO ) return - 0 ;
26
29
27
- return values [ index ] ;
28
- }
29
-
30
- let i = values . length ;
31
- while ( i -- ) {
32
- const value = values [ i ] ;
30
+ if ( index in hydrated ) return hydrated [ index ] ;
33
31
34
- if ( ! value || typeof value !== 'object' ) continue ;
32
+ const value = values [ index ] ;
35
33
36
- if ( Array . isArray ( value ) ) {
34
+ if ( ! value || typeof value !== 'object' ) {
35
+ hydrated [ index ] = value ;
36
+ } else if ( Array . isArray ( value ) ) {
37
37
if ( typeof value [ 0 ] === 'string' ) {
38
38
const type = value [ 0 ] ;
39
39
40
40
switch ( type ) {
41
41
case 'Date' :
42
- values [ i ] = new Date ( value [ 1 ] ) ;
42
+ hydrated [ index ] = new Date ( value [ 1 ] ) ;
43
43
break ;
44
44
45
45
case 'Set' :
46
46
const set = new Set ( ) ;
47
- values [ i ] = set ;
48
- for ( const n of value [ 1 ] ) set . add ( get_value ( n ) ) ;
47
+ hydrated [ index ] = set ;
48
+ for ( const n of value [ 1 ] ) set . add ( hydrate ( n ) ) ;
49
49
break ;
50
50
51
51
case 'Map' :
52
52
const map = new Map ( ) ;
53
- values [ i ] = map ;
53
+ hydrated [ index ] = map ;
54
54
for ( let i = 0 ; i < value [ 1 ] . length ; i += 2 ) {
55
- map . set ( get_value ( value [ i ] ) , get_value ( value [ i + 1 ] ) ) ;
55
+ map . set ( hydrate ( value [ i ] ) , hydrate ( value [ i + 1 ] ) ) ;
56
56
}
57
57
break ;
58
58
59
59
case 'RegExp' :
60
- values [ i ] = new RegExp ( value [ 1 ] , value [ 2 ] ) ;
60
+ hydrated [ index ] = new RegExp ( value [ 1 ] , value [ 2 ] ) ;
61
61
break ;
62
62
63
63
case 'Object' :
64
- values [ i ] = Object ( value [ 1 ] ) ;
64
+ hydrated [ index ] = Object ( value [ 1 ] ) ;
65
65
break ;
66
66
67
67
case 'BigInt' :
68
- values [ i ] = BigInt ( value [ 1 ] ) ;
68
+ hydrated [ index ] = BigInt ( value [ 1 ] ) ;
69
69
break ;
70
70
71
71
case 'null' :
72
- const object = Object . create ( null ) ;
72
+ const obj = Object . create ( null ) ;
73
+ hydrated [ index ] = obj ;
74
+ for ( let i = 1 ; i < value . length ; i += 2 ) {
75
+ obj [ value [ i ] ] = hydrate ( value [ i + 1 ] ) ;
76
+ }
77
+ break ;
73
78
}
74
79
} else {
75
80
const array = new Array ( value . length ) ;
@@ -78,23 +83,25 @@ export function parse(serialized) {
78
83
const n = value [ i ] ;
79
84
if ( n === HOLE ) continue ;
80
85
81
- array [ i ] = get_value ( n ) ;
86
+ array [ i ] = hydrate ( n ) ;
82
87
}
83
88
84
- values [ i ] = array ;
89
+ hydrated [ index ] = array ;
85
90
}
86
91
} else {
87
92
/** @type {Record<string, any> } */
88
93
const object = { } ;
89
94
90
95
for ( const key in value ) {
91
96
const n = value [ key ] ;
92
- object [ key ] = get_value ( n ) ;
97
+ object [ key ] = hydrate ( n ) ;
93
98
}
94
99
95
- values [ i ] = object ;
100
+ hydrated [ index ] = object ;
96
101
}
102
+
103
+ return hydrated [ index ] ;
97
104
}
98
105
99
- return values [ 0 ] ;
106
+ return hydrate ( 0 ) ;
100
107
}
0 commit comments