11// Symbol used as placeholders for objects and arrays
2- const IS_ARRAY = Symbol ( "IS_ARRAY" ) ;
3- const IS_OBJECT = Symbol ( "IS_OBJECT" ) ;
2+ const IS_ARRAY_START = Symbol ( "IS_ARRAY_START" ) ;
3+ const IS_ARRAY_END = Symbol ( "IS_ARRAY_END" ) ;
4+ const IS_OBJECT_START = Symbol ( "IS_OBJECT_START" ) ;
5+ const IS_OBJECT_END = Symbol ( "IS_OBJECT_END" ) ;
46
57let ASYNC_BATCH_COUNT = 3000 ;
68let TRACK_PERF = false ;
@@ -10,8 +12,7 @@ export const tweak = (batchCount, trackPerf) => {
1012 TRACK_PERF = Boolean ( trackPerf ) ;
1113} ;
1214
13- const next =
14- ( typeof window !== "undefined" && window . requestAnimationFrame ) || setTimeout ;
15+ const next = ( typeof window !== 'undefined' && window . requestAnimationFrame ) || setTimeout ;
1516
1617/*
1718 This function takes a value which results in a Map of
@@ -21,24 +22,23 @@ const next =
2122*/
2223function getPaths ( value , paths , replacer , currentPath = [ ] ) {
2324 const replacedValue = replacer ? replacer ( currentPath , value ) : value ;
24- if (
25- typeof replacedValue === "function" ||
26- typeof replacedValue === "symbol"
27- ) {
25+ if ( typeof replacedValue === "function" || typeof replacedValue === "symbol" || replacedValue === undefined ) {
2826 } else if ( Array . isArray ( replacedValue ) ) {
29- paths . set ( currentPath . slice ( ) , IS_ARRAY ) ;
27+ paths . set ( currentPath . slice ( ) , IS_ARRAY_START ) ;
3028 for ( let key in replacedValue ) {
3129 currentPath . push ( key ) ;
32- getPaths ( replacedValue [ key ] , paths , replacer , currentPath ) ;
30+ getPaths ( replacedValue [ key ] , paths , replacer ? replacer . bind ( replacedValue ) : replacer , currentPath ) ;
3331 currentPath . pop ( ) ;
3432 }
33+ paths . set ( currentPath . slice ( ) , IS_ARRAY_END ) ;
3534 } else if ( replacedValue !== null && typeof replacedValue === "object" ) {
36- paths . set ( currentPath . slice ( ) , IS_OBJECT ) ;
35+ paths . set ( currentPath . slice ( ) , IS_OBJECT_START ) ;
3736 for ( let key in replacedValue ) {
3837 currentPath . push ( key ) ;
39- getPaths ( replacedValue [ key ] , paths , replacer , currentPath ) ;
38+ getPaths ( replacedValue [ key ] , paths , replacer ? replacer . bind ( replacedValue ) : replacer , currentPath ) ;
4039 currentPath . pop ( ) ;
4140 }
41+ paths . set ( currentPath . slice ( ) , IS_OBJECT_END ) ;
4242 } else {
4343 paths . set ( currentPath . slice ( ) , replacedValue ) ;
4444 }
@@ -64,25 +64,27 @@ function isRef(ref) {
6464 Then it iterates these paths and produces the JSON string
6565*/
6666export function stringify ( value , replacer ?) {
67- return new Promise ( resolve => {
67+ return new Promise < string > ( resolve => {
6868 next ( async ( ) => {
69- const paths = getPaths ( value , new Map ( ) , replacer ) ;
69+ const paths = getPaths ( value , new Map ( ) , replacer ? replacer . bind ( global || window ) : replacer ) ;
7070 const structs = [ ] ;
7171 let prevKey = [ ] ;
72+ let prevValue = null
7273 let string = "" ;
7374 let x = 0 ;
74- let start ;
75+ let start
76+
7577 if ( TRACK_PERF ) {
76- start = performance . now ( ) ;
78+ start = performance . now ( )
7779 }
80+
7881 for ( let [ key , value ] of paths ) {
7982 if ( x % ASYNC_BATCH_COUNT === 0 ) {
8083 if ( TRACK_PERF ) {
81- const end = performance . now ( ) ;
82- console . log ( "PERF stringify " , end - start ) ;
83- start = end ;
84+ const end = performance . now ( )
85+ console . log ( "PERF - " , end - start )
86+ start = end
8487 }
85-
8688 await new Promise ( resolve => next ( resolve ) ) ;
8789 }
8890
@@ -92,59 +94,49 @@ export function stringify(value, replacer?) {
9294
9395 prevKey = key ;
9496
95- if (
96- // If we are moving back up the tree, previous has to have been
97- // an object or array
98- ( key . length && currentKey . length > key . length ) ||
99- // Or we stay at the same nested level, but previous was
100- // an object or key
101- ( currentKey . length === key . length &&
102- ( paths . get ( currentKey ) === IS_OBJECT ||
103- paths . get ( currentKey ) === IS_ARRAY ) )
104- ) {
105- string += structs . pop ( ) === IS_OBJECT ? "}" : "]" ;
97+ if ( value === IS_OBJECT_END ) {
98+ structs . pop ( )
99+ string += '}'
100+ continue
106101 }
102+ if ( value === IS_ARRAY_END ) {
103+ structs . pop ( )
104+ string += ']'
105+ continue
106+ }
107+
108+
109+ prevValue = value
107110
108111 if ( key . length && key . length <= currentKey . length ) {
109112 string += "," ;
110113 }
111114
112- if ( value === IS_OBJECT ) {
113- const currentStruct = structs [ structs . length - 1 ] ;
115+ let currentStruct = structs [ structs . length - 1 ] ;
116+
117+ if ( value === IS_OBJECT_START ) {
114118 structs . push ( value ) ;
115- string +=
116- key . length && currentStruct === IS_OBJECT
117- ? `"${ key [ key . length - 1 ] } ":{`
118- : "{" ;
119+ string += key . length && currentStruct === IS_OBJECT_START ? `"${ key [ key . length - 1 ] } ":{` : "{" ;
119120 continue ;
120121 }
121122
122- if ( value === IS_ARRAY ) {
123- const currentStruct = structs [ structs . length - 1 ] ;
123+ if ( value === IS_ARRAY_START ) {
124124 structs . push ( value ) ;
125- string +=
126- key . length && currentStruct === IS_OBJECT
127- ? `"${ key [ key . length - 1 ] } ":[`
128- : "[" ;
125+ string += key . length && currentStruct === IS_OBJECT_START ? `"${ key [ key . length - 1 ] } ":[` : "[" ;
129126 continue ;
130127 }
131128
132- const currentStruct = structs [ structs . length - 1 ] ;
133- if ( currentStruct === IS_OBJECT ) {
129+ currentStruct = structs [ structs . length - 1 ] ;
130+ if ( currentStruct === IS_OBJECT_START ) {
134131 string += `"${ key [ key . length - 1 ] } ":${ JSON . stringify ( value ) } ` ;
135132 continue ;
136133 }
137- if ( currentStruct === IS_ARRAY ) {
134+ if ( currentStruct === IS_ARRAY_START ) {
138135 string += JSON . stringify ( value ) ;
139136 continue ;
140137 }
141138 }
142139
143- while ( structs . length ) {
144- const struct = structs . pop ( ) ;
145- string += struct === IS_OBJECT ? "}" : "]" ;
146- }
147-
148140 resolve ( string ) ;
149141 } ) ;
150142 } ) ;
@@ -163,16 +155,18 @@ export async function parse(value) {
163155 const openingArrayBrackets = [ ] ;
164156
165157 let isInString = false ;
166- let start ;
158+ let start
159+
167160 if ( TRACK_PERF ) {
168- start = performance . now ( ) ;
161+ start = performance . now ( )
169162 }
163+
170164 for ( let charIndex = 0 ; charIndex < value . length ; charIndex ++ ) {
171165 if ( charIndex % ASYNC_BATCH_COUNT === 0 ) {
172166 if ( TRACK_PERF ) {
173- const end = performance . now ( ) ;
174- console . log ( "PERF parse " , end - start ) ;
175- start = end ;
167+ const end = performance . now ( )
168+ console . log ( "PERF - " , end - start )
169+ start = end
176170 }
177171 await new Promise ( resolve => next ( resolve ) ) ;
178172 }
0 commit comments