Skip to content

Commit e661a53

Browse files
committed
Add optimized version for review
1 parent b7fd473 commit e661a53

File tree

1 file changed

+89
-0
lines changed

1 file changed

+89
-0
lines changed

src/util/toPath.js

+89
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,95 @@
1515
export function toPath(path) {
1616
if (Array.isArray(path)) return path
1717

18+
let parts = []
19+
let inBrackets = false
20+
let partStart = 0
21+
let partEnd = 0
22+
23+
for (let i = 0, len = path.length; i <= len; i++) {
24+
let prev = path[i - 1]
25+
let curr = path[i]
26+
27+
// Tokens:
28+
// [ = lb
29+
// ] = rb
30+
// . = dot if not in brackets
31+
// . = ident if in brackets
32+
// everything else = ident
33+
let prevIsIdent = inBrackets
34+
? prev !== undefined && prev !== '[' && prev !== ']'
35+
: prev !== undefined && prev !== '.' && prev !== '[' && prev !== ']'
36+
37+
let currIsIdent = inBrackets
38+
? curr !== undefined && curr !== '[' && curr !== ']'
39+
: curr !== undefined && curr !== '.' && curr !== '[' && curr !== ']'
40+
41+
// The only valid transitions are:
42+
// start -> dot | lb | ident | end
43+
// dot -> ident
44+
// lb -> rb | ident
45+
// rb -> dot | lb
46+
// ident -> dot | rb | ident | end
47+
// ident -> lb if not in brackets
48+
if (
49+
(prev === undefined && curr === ']') ||
50+
(prev === '.' && !inBrackets && !currIsIdent) ||
51+
(prev === '[' && curr === undefined) ||
52+
(prev === '[' && curr === '[') ||
53+
(prev === ']' && curr === ']') ||
54+
(prev === ']' && currIsIdent) ||
55+
(prevIsIdent && curr === '[' && inBrackets)
56+
) {
57+
throw new Error(`Invalid path: ${path}\n` + `${' '.repeat(14 + i)}^`)
58+
}
59+
60+
// The last thing we looked at was an ident so we ened to keep looking for more
61+
// Later scans will identify the end of the ident
62+
if (prevIsIdent) {
63+
partEnd = i
64+
}
65+
66+
// Whenever we go from an ident to a non-ident we capture the new part
67+
// We also capture:
68+
// - start -> dot for initial empty strings
69+
// - lb -> rb for ocurrences of [] also treated as empty strings
70+
if (
71+
(prev === undefined && curr === '.') ||
72+
(prev === '[' && curr === ']') ||
73+
(prevIsIdent && curr === '.' && !inBrackets) ||
74+
(prevIsIdent && curr === '[' && !inBrackets) ||
75+
(prevIsIdent && curr === ']') ||
76+
(prevIsIdent && curr === undefined)
77+
) {
78+
parts.push(path.slice(partStart, partEnd))
79+
}
80+
81+
// Whenever we go from a non-ident to ident we start capturing a new part
82+
// We also capture start -> lb for initial empty strings generated by `[]`
83+
if (
84+
(prev === undefined && curr === '[') ||
85+
(prev === '.' && !inBrackets && currIsIdent) ||
86+
(prev === '[' && currIsIdent) ||
87+
(prev === ']' && curr === '.')
88+
) {
89+
partStart = partEnd = i
90+
}
91+
92+
// Bracket bookkeeping
93+
if (curr === '[') {
94+
inBrackets = true
95+
} else if (curr === ']') {
96+
inBrackets = false
97+
}
98+
}
99+
100+
return parts
101+
}
102+
103+
// Herre for reference in case one is preferred over the other
104+
function toPathFull(path) {
105+
if (Array.isArray(path)) return path
106+
18107
// The general outline/properties of a path string:
19108

20109
// Tokens:

0 commit comments

Comments
 (0)