@@ -152,8 +152,8 @@ export function createRegExpRestore () {
152
152
return function ( ) {
153
153
// Now we've snapshotted some properties, escape the lastMatch string
154
154
let esc = / [ . ? * + ^ $ [ \] \\ ( ) { } | - ] / g,
155
- lm = regExpCache . lastMatch . replace ( esc , '\\$&' ) ,
156
- reg = new List ( ) ;
155
+ lastMatch = regExpCache . lastMatch . replace ( esc , '\\$&' ) ,
156
+ exprStr = '' ;
157
157
158
158
// If any of the captured strings were non-empty, iterate over them all
159
159
if ( has ) {
@@ -162,33 +162,38 @@ export function createRegExpRestore () {
162
162
163
163
// If it's empty, add an empty capturing group
164
164
if ( ! m ) {
165
- arrPush . call ( reg , '(' ) ;
166
- lm = ')' + lm ;
165
+ exprStr += '(' ;
166
+ lastMatch = ')' + lastMatch ;
167
167
}
168
168
// Else find the string in lm and escape & wrap it to capture it
169
169
else {
170
170
m = m . replace ( esc , '\\$&' ) ;
171
- let [ left , ...right ] = lm . split ( m ) ;
172
- left += '(' ;
173
- lm = m + ')' + right . join ( '' ) ;
174
- // Push it to the reg and chop lm to make sure further groups come after
175
- arrPush . call ( reg , left ) ;
171
+ exprStr += lastMatch . substring ( 0 , lastMatch . indexOf ( m ) ) + '(' ;
172
+ lastMatch = m + ')' + lastMatch . substring ( lastMatch . indexOf ( m ) + m . length ) ;
176
173
}
177
-
178
-
179
-
180
174
}
181
175
}
182
176
183
- let exprStr = arrJoin . call ( reg , '' ) + lm ;
177
+ exprStr += lastMatch ;
184
178
185
179
// Shorten the regex by replacing each part of the expression with a match
186
180
// for a string of that exact length. This is safe for the type of
187
181
// expressions generated above, because the expression matches the whole
188
182
// match string, so we know each group and each segment between capturing
189
183
// groups can be matched by its length alone.
190
- // exprStr = exprStr.replace(/([^\\]\\\(|[^\\]\\\)|[^()])+/g, (match) => {
191
- exprStr = exprStr . replace ( / ( [ ^ \\ ] ( \\ \\ ) * \\ [ \) \( ] ( ( \\ \\ ) * \\ [ \( \) ] ) * | [ ^ ( ) ] ) + / g, ( match ) => {
184
+ //
185
+ // The purpose of the regex is to match sequences of characters other
186
+ // than unescaped parentheses. This is a more complicated requirement
187
+ // than it seems at first glance, because it's necessary to match a
188
+ // parenthesis which appears immediately after a backslash ("\("), but
189
+ // not a parenthesis which appears immediately after an escaped backslash
190
+ // ("\\("). We can't simply match [^\\]\\(, because the previous
191
+ // backslash could itself have a backslash preceding (and escaping) it.
192
+ //
193
+ // Any attempts to simplify this regex are encouraged! A replacement
194
+ // regex should match the strings "a\\\(\\\)\\" and "a\\\)\\\(" in the
195
+ // test string "a\\\(\\\)\\(a\\\)\\\()".
196
+ exprStr = exprStr . replace ( / ( ( ^ | [ ^ \\ ] ) ( \\ \\ ) * \\ [ ( ) ] ( ( \\ \\ ) * \\ [ ( ) ] ) * | [ ^ ( ) ] ) + / g, ( match ) => {
192
197
return `[\\s\\S]{${ match . replace ( / \\ ( .) / g, '$1' ) . length } }` ;
193
198
} ) ;
194
199
0 commit comments