Skip to content
This repository was archived by the owner on Apr 14, 2021. It is now read-only.

Commit f91377b

Browse files
committed
(bug #231) Simplifications and improvements to createRegexpRestore
1 parent 06012a9 commit f91377b

File tree

1 file changed

+20
-15
lines changed

1 file changed

+20
-15
lines changed

src/util.js

+20-15
Original file line numberDiff line numberDiff line change
@@ -152,8 +152,8 @@ export function createRegExpRestore () {
152152
return function() {
153153
// Now we've snapshotted some properties, escape the lastMatch string
154154
let esc = /[.?*+^$[\]\\(){}|-]/g,
155-
lm = regExpCache.lastMatch.replace(esc, '\\$&'),
156-
reg = new List();
155+
lastMatch = regExpCache.lastMatch.replace(esc, '\\$&'),
156+
exprStr = '';
157157

158158
// If any of the captured strings were non-empty, iterate over them all
159159
if (has) {
@@ -162,33 +162,38 @@ export function createRegExpRestore () {
162162

163163
// If it's empty, add an empty capturing group
164164
if (!m) {
165-
arrPush.call(reg, '(');
166-
lm = ')' + lm;
165+
exprStr += '(';
166+
lastMatch = ')' + lastMatch;
167167
}
168168
// Else find the string in lm and escape & wrap it to capture it
169169
else {
170170
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);
176173
}
177-
178-
179-
180174
}
181175
}
182176

183-
let exprStr = arrJoin.call(reg, '') + lm;
177+
exprStr += lastMatch;
184178

185179
// Shorten the regex by replacing each part of the expression with a match
186180
// for a string of that exact length. This is safe for the type of
187181
// expressions generated above, because the expression matches the whole
188182
// match string, so we know each group and each segment between capturing
189183
// 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) => {
192197
return `[\\s\\S]{${match.replace(/\\(.)/g, '$1').length}}`;
193198
});
194199

0 commit comments

Comments
 (0)