Skip to content

Commit c528c79

Browse files
committed
Use a manual loop to scan for line ends
FIX: Use a loop to find line breaks, because the existing regexp search would overrun the end of the searched range and waste a lot of time in minified code. Closes #1083
1 parent 47928a4 commit c528c79

File tree

3 files changed

+17
-14
lines changed

3 files changed

+17
-14
lines changed

acorn/src/locutil.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {lineBreakG} from "./whitespace.js"
1+
import {nextLineBreak} from "./whitespace.js"
22

33
// These are used when `options.locations` is on, for the
44
// `startLoc` and `endLoc` properties.
@@ -30,13 +30,9 @@ export class SourceLocation {
3030

3131
export function getLineInfo(input, offset) {
3232
for (let line = 1, cur = 0;;) {
33-
lineBreakG.lastIndex = cur
34-
let match = lineBreakG.exec(input)
35-
if (match && match.index < offset) {
36-
++line
37-
cur = match.index + match[0].length
38-
} else {
39-
return new Position(line, offset - cur)
40-
}
33+
let nextBreak = nextLineBreak(input, cur, offset)
34+
if (nextBreak < 0) return new Position(line, offset - cur)
35+
++line
36+
cur = nextBreak
4137
}
4238
}

acorn/src/tokenize.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {types as tt, keywords as keywordTypes} from "./tokentype.js"
33
import {Parser} from "./state.js"
44
import {SourceLocation} from "./locutil.js"
55
import {RegExpValidationState} from "./regexp.js"
6-
import {lineBreak, lineBreakG, isNewLine, nonASCIIwhitespace} from "./whitespace.js"
6+
import {lineBreak, nextLineBreak, isNewLine, nonASCIIwhitespace} from "./whitespace.js"
77

88
// Object type used to represent tokens. Note that normally, tokens
99
// simply exist as properties on the parser object. This is only
@@ -100,11 +100,9 @@ pp.skipBlockComment = function() {
100100
if (end === -1) this.raise(this.pos - 2, "Unterminated comment")
101101
this.pos = end + 2
102102
if (this.options.locations) {
103-
lineBreakG.lastIndex = start
104-
let match
105-
while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) {
103+
for (let nextBreak, pos = start; (nextBreak = nextLineBreak(this.input, pos, this.pos)) > -1;) {
106104
++this.curLine
107-
this.lineStart = match.index + match[0].length
105+
pos = this.lineStart = nextBreak
108106
}
109107
}
110108
if (this.options.onComment)

acorn/src/whitespace.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,15 @@ export function isNewLine(code) {
88
return code === 10 || code === 13 || code === 0x2028 || code === 0x2029
99
}
1010

11+
export function nextLineBreak(code, from, end = code.length) {
12+
for (let i = from; i < end; i++) {
13+
let next = code.charCodeAt(i)
14+
if (isNewLine(next))
15+
return i < end - 1 && next === 13 && code.charCodeAt(i + 1) === 10 ? i + 2 : i + 1
16+
}
17+
return -1
18+
}
19+
1120
export const nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/
1221

1322
export const skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g

0 commit comments

Comments
 (0)