1
1
import { parse as parser } from 'fast-querystring'
2
2
3
+ const BAD_KEYS = new Set ( [
4
+ 'length' ,
5
+ ...Object . getOwnPropertyNames ( Object . prototype ) ,
6
+ ] )
7
+
3
8
const isPosInt = ( str ) => {
4
9
const n = Number ( str )
5
10
return Number . isInteger ( n ) && n >= 0
@@ -8,67 +13,67 @@ const isPosInt = (str) => {
8
13
const resolvePath = ( o , path , v = null , d ) => {
9
14
let next = path
10
15
let cur = o
11
- let l , r , k
12
- for ( ; d > 0 || ! next ; d -- ) {
16
+ for ( let l , r , k ; d > 0 || ! next ; d -- ) {
13
17
l = next . indexOf ( '[' )
14
18
r = next . indexOf ( ']' )
15
19
if ( l === - 1 || r === - 1 || l > r ) return { [ next ] : v }
16
20
k = next . slice ( l + 1 , r ) || cur ?. length || 0
17
21
next = next . slice ( r + 1 )
18
22
if ( isPosInt ( k ) ) {
19
- let i = Number ( k )
20
- if ( ! cur ) cur = [ ]
21
- if ( ! o ) o = cur
22
- if ( ! Array . isArray ( cur ) ) {
23
- if ( ! k && ! i ) i = Object . keys ( cur ) . length
24
- cur = cur [ i ] = { }
23
+ if ( ! cur ) {
24
+ cur = [ ]
25
+ o = cur
26
+ }
27
+ if ( ! ( cur instanceof Array ) ) {
28
+ if ( ! k ) k = Object . keys ( cur ) . length
29
+ cur = cur [ k ] = { }
25
30
continue
26
31
}
27
- const extend = i - cur . length + 1
32
+ k = Number ( k )
33
+ const extend = k - cur . length + 1
28
34
if ( extend > 0 ) {
29
35
cur . push . apply ( cur , Array ( extend ) )
30
36
}
31
- if ( next === '[]' && typeof v !== 'string' ) {
32
- cur [ i ] = [ ...cur [ i ] ?? [ ] , ...v ]
33
- return o
34
- } else if ( next ) {
35
- if ( next . startsWith ( '[]' ) ) {
36
- cur = cur [ k ] ??= [ ]
37
- } else {
38
- if ( ! cur [ i ] ) cur [ i ] = { }
39
- else if ( Array . isArray ( cur [ i ] ) )
40
- cur [ i ] = { ...cur [ i ] }
41
- cur = cur [ i ]
37
+ if ( ! next ) {
38
+ if ( typeof v !== 'string' ) { // join array
39
+ cur . splice ( k , 1 )
40
+ cur . push . apply ( cur , v )
41
+ } else { // set index
42
+ cur [ k ] = v
42
43
}
43
- } else {
44
- cur [ i ] = v
45
44
return o
46
45
}
47
- } else if ( ! { } [ k ] ) {
48
- if ( ! cur ) cur = { }
49
- if ( ! o ) o = cur
50
- if ( next ) {
51
- if ( next . startsWith ( '[]' ) ) {
52
- cur = cur [ k ] ??= [ ]
53
- } else {
54
- if ( ! cur [ k ] ) cur [ k ] = { }
55
- else if ( Array . isArray ( cur [ k ] ) )
56
- cur [ k ] = { ...cur [ k ] }
57
- cur = cur [ k ]
58
- }
59
- } else {
46
+ } else if ( ! BAD_KEYS . has ( k ) ) {
47
+ if ( ! cur ) {
48
+ cur = { }
49
+ o = cur
50
+ }
51
+ if ( typeof cur === 'string' ) {
52
+ break
53
+ }
54
+ if ( ! next ) {
60
55
cur [ k ] = v
61
56
return o
62
57
}
63
58
} else {
64
59
break
65
60
}
61
+ // resolve next cursor
62
+ if ( next . startsWith ( '[]' ) ) {
63
+ cur = cur [ k ] ??= [ ]
64
+ } else {
65
+ cur [ k ] ??= { }
66
+ if ( cur [ k ] instanceof Array )
67
+ cur [ k ] = { ...cur [ k ] }
68
+ cur = cur [ k ]
69
+ }
66
70
}
67
- if ( Array . isArray ( cur ) ) {
68
- if ( next ) cur . push ( { [ next ] : v } )
69
- else cur . push ( v )
70
- } else if ( typeof cur === 'object' ) {
71
- if ( next ) cur [ next ] = v
71
+ if ( next ) {
72
+ if ( cur instanceof Array ) {
73
+ cur . push ( { [ next ] : v } )
74
+ } else if ( typeof cur === 'object' ) {
75
+ cur [ next ] = v
76
+ }
72
77
}
73
78
return o
74
79
}
@@ -83,9 +88,9 @@ export default (str, depth=5) => {
83
88
if ( l > 0 && k . indexOf ( ']' ) > l ) {
84
89
const key = k . slice ( 0 , l )
85
90
const path = k . slice ( l )
86
- if ( path === '[]' ) {
91
+ if ( path === '[]' ) { // optimize 1d array
87
92
if ( key in o ) {
88
- if ( ! Array . isArray ( o [ key ] ) )
93
+ if ( ! ( o [ key ] instanceof Array ) )
89
94
o [ key ] = [ o [ key ] ]
90
95
o [ key ] = [ ] . concat ( o [ key ] , v )
91
96
} else o [ key ] = v
0 commit comments