Skip to content

fix(scanner): make esprima2 string/template scanning linear - #15

Merged
itamarga merged 1 commit into
mainfrom
fix/esprima-quadratic-string-scan
Aug 27, 2026
Merged

fix(scanner): make esprima2 string/template scanning linear#15
itamarga merged 1 commit into
mainfrom
fix/esprima-quadratic-string-scan

Conversation

@itamarga

Copy link
Copy Markdown
Collaborator

esprima2 builds string and template literal values with value += ch inside a while loop with manual indexing (Scanner.scanStringLiteral / Scanner.scanTemplate). In CPython that loop shape misses the in-place string-concat optimization, so each append copies the whole buffer, making the scan O(n^2) in the length of a single literal. Source that is one large string literal (e.g. a multi-megabyte base64 blob) takes ~70s to parse.

Add pyjsclear/esprima_patch.py, applied at import of pyjsclear.parser: it replaces both methods with faithful list-append + join reimplementations (character-for-character identical logic, linear accumulation). Version-gated to the esprima2 releases whose scanner source was verified against these ports (5.0.1, 5.0.2, 6.0.0 — identical on Python 3, where 5.x's uchr is chr); any other version leaves esprima untouched.

Parse of a 3.13MB single-literal file drops from ~70s to ~0.4s.

esprima2 builds string and template literal values with `value += ch` in a
while loop (Scanner.scanStringLiteral / scanTemplate). In CPython that misses
the in-place string-concat optimization, so each append copies the whole
buffer and scanning a single literal is O(n^2). Source that is one large
string literal (e.g. a multi-megabyte base64 blob) takes ~70s to parse.

Add pyjsclear/esprima_patch.py, applied at import of pyjsclear.parser. It
takes the installed scanner method source and applies the two-line fix
proposed upstream (s0md3v/esprima2#10): accumulate into a list and join once
at the end. Deriving from the live source keeps it faithful to whatever
esprima2 is installed; gated to verified versions (5.0.1, 5.0.2, 6.0.0), and
it bails (leaving esprima untouched) if the source or version is unexpected.

Parse of a 3.13MB single-literal file drops from ~70s to ~0.4s.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@itamarga
itamarga force-pushed the fix/esprima-quadratic-string-scan branch from 340bd1b to eeab684 Compare August 26, 2026 13:45
@itamarga
itamarga merged commit 72ced00 into main Aug 27, 2026
11 checks passed
@itamarga
itamarga deleted the fix/esprima-quadratic-string-scan branch August 27, 2026 07:02
@itamarga itamarga mentioned this pull request Aug 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants