@@ -1668,10 +1668,10 @@ const createTerserTree = ({ ast, parse }) => {
16681668 const EMPTY = [ ] ;
16691669 // Kept across calls, as a worker minifies one asset after another: every
16701670 // read is at an offset this source set, so what an earlier one left is inert.
1671- let byStart = new Int32Array ( 0 ) ;
1672- let byEnd = new Int32Array ( 0 ) ;
1673- // Each token's offsets and kind, by index: a source holds fewer tokens
1674- // than characters, so these grow with the two above .
1671+ let startIndexBuffer = new Int32Array ( 0 ) ;
1672+ let endIndexBuffer = new Int32Array ( 0 ) ;
1673+ // Each token's offsets and kind grow with the token count, not source size:
1674+ // comments and long identifiers or strings need no extra token slots .
16751675 let startBuffer = new Int32Array ( 0 ) ;
16761676 let endBuffer = new Int32Array ( 0 ) ;
16771677 let kindBuffer = new Int8Array ( 0 ) ;
@@ -1690,18 +1690,47 @@ const createTerserTree = ({ ast, parse }) => {
16901690 let inTemplateText = false ;
16911691 /** @type {boolean[] } */
16921692 const braces = [ ] ;
1693- if ( byStart . length <= source . length ) {
1694- byStart = new Int32Array ( source . length + 1 ) ;
1695- byEnd = new Int32Array ( source . length + 1 ) ;
1696- startBuffer = new Int32Array ( source . length + 1 ) ;
1697- endBuffer = new Int32Array ( source . length + 1 ) ;
1698- kindBuffer = new Int8Array ( source . length + 1 ) ;
1693+ if ( startIndexBuffer . length <= source . length ) {
1694+ startIndexBuffer = new Int32Array ( source . length + 1 ) ;
1695+ endIndexBuffer = new Int32Array ( source . length + 1 ) ;
16991696 }
1700- const starts = startBuffer ;
1701- const ends = endBuffer ;
1702- const kinds = kindBuffer ;
1703- const tokenStart = byStart ;
1704- const tokenEnd = byEnd ;
1697+ let starts = startBuffer ;
1698+ let ends = endBuffer ;
1699+ let kinds = kindBuffer ;
1700+ const byStart = startIndexBuffer ;
1701+ const byEnd = endIndexBuffer ;
1702+ // Keep this call's indices alive through conversion, but do not cache a
1703+ // large source's buffers, even if parsing or conversion declines it.
1704+ if ( source . length > 1 << 23 ) {
1705+ startIndexBuffer = new Int32Array ( 0 ) ;
1706+ endIndexBuffer = new Int32Array ( 0 ) ;
1707+ startBuffer = new Int32Array ( 0 ) ;
1708+ endBuffer = new Int32Array ( 0 ) ;
1709+ kindBuffer = new Int8Array ( 0 ) ;
1710+ }
1711+ /**
1712+ * @returns {void } grow the token tables without retaining oversized inputs
1713+ */
1714+ const growTokens = ( ) => {
1715+ const capacity = Math . min (
1716+ source . length + 1 ,
1717+ Math . max ( 4096 , starts . length * 2 )
1718+ ) ;
1719+ const nextStarts = new Int32Array ( capacity ) ;
1720+ const nextEnds = new Int32Array ( capacity ) ;
1721+ const nextKinds = new Int8Array ( capacity ) ;
1722+ nextStarts . set ( starts ) ;
1723+ nextEnds . set ( ends ) ;
1724+ nextKinds . set ( kinds ) ;
1725+ starts = nextStarts ;
1726+ ends = nextEnds ;
1727+ kinds = nextKinds ;
1728+ if ( source . length <= 1 << 23 ) {
1729+ startBuffer = starts ;
1730+ endBuffer = ends ;
1731+ kindBuffer = kinds ;
1732+ }
1733+ } ;
17051734 // Whitespace to the spec that terser's tokenizer refuses.
17061735 if ( source . includes ( "\u1680" ) ) return undefined ;
17071736 /** @type {EstreeNode } */
@@ -1739,7 +1768,7 @@ const createTerserTree = ({ ast, parse }) => {
17391768 // `}` closing a substitution, through the next `${` or backtick.
17401769 if ( inTemplateText ) {
17411770 ends [ count - 1 ] = token . end ;
1742- tokenEnd [ token . end ] = count ;
1771+ byEnd [ token . end ] = count ;
17431772 // terser's template token carries the text it holds.
17441773 if ( label === "template" || label === "invalidTemplate" ) {
17451774 values [ count - 1 ] = token . value ;
@@ -1791,13 +1820,14 @@ const createTerserTree = ({ ast, parse }) => {
17911820 // A word after a dot is a property name to terser, even a keyword.
17921821 if ( kind === WORD && previousWasDot ) kind = - WORD ;
17931822 previousWasDot = label === "." || label === "?." ;
1823+ if ( count === starts . length ) growTokens ( ) ;
17941824 starts [ count ] = token . start ;
17951825 ends [ count ] = token . end ;
17961826 kinds [ count ] = kind ;
17971827 values . push ( value ) ;
17981828 count ++ ;
1799- tokenStart [ token . start ] = count ;
1800- tokenEnd [ token . end ] = count ;
1829+ byStart [ token . start ] = count ;
1830+ byEnd [ token . end ] = count ;
18011831 }
18021832 } ) ;
18031833 } catch ( _err ) {
@@ -1841,15 +1871,6 @@ const createTerserTree = ({ ast, parse }) => {
18411871 return low ;
18421872 } ;
18431873
1844- // Too large a source is not kept past this call.
1845- if ( source . length > 1 << 23 ) {
1846- byStart = new Int32Array ( 0 ) ;
1847- byEnd = new Int32Array ( 0 ) ;
1848- startBuffer = new Int32Array ( 0 ) ;
1849- endBuffer = new Int32Array ( 0 ) ;
1850- kindBuffer = new Int8Array ( 0 ) ;
1851- }
1852-
18531874 // The comments in each gap, gap `i` being the one before token `i`.
18541875 // Sized up front: filled out of order, it would otherwise go sparse.
18551876 /** @type {(Token[] | undefined)[] } */
0 commit comments