11"use strict" ;
22Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
3+ exports . EXPANSION_MAX = void 0 ;
34exports . expand = expand ;
45const balanced_match_1 = require ( "@isaacs/balanced-match" ) ;
56const escSlash = '\0SLASH' + Math . random ( ) + '\0' ;
@@ -17,6 +18,7 @@ const openPattern = /\\{/g;
1718const closePattern = / \\ } / g;
1819const commaPattern = / \\ , / g;
1920const periodPattern = / \\ ./ g;
21+ exports . EXPANSION_MAX = 100_000 ;
2022function numeric ( str ) {
2123 return ! isNaN ( str ) ? parseInt ( str , 10 ) : str . charCodeAt ( 0 ) ;
2224}
@@ -62,10 +64,11 @@ function parseCommaParts(str) {
6264 parts . push . apply ( parts , p ) ;
6365 return parts ;
6466}
65- function expand ( str ) {
67+ function expand ( str , options = { } ) {
6668 if ( ! str ) {
6769 return [ ] ;
6870 }
71+ const { max = exports . EXPANSION_MAX } = options ;
6972 // I don't know why Bash 4.3 does this, but it does.
7073 // Anything starting with {} will have the first two bytes preserved
7174 // but *only* at the top level, so {},a }b will not expand to anything,
@@ -75,7 +78,7 @@ function expand(str) {
7578 if ( str . slice ( 0 , 2 ) === '{}' ) {
7679 str = '\\{\\}' + str . slice ( 2 ) ;
7780 }
78- return expand_ ( escapeBraces ( str ) , true ) . map ( unescapeBraces ) ;
81+ return expand_ ( escapeBraces ( str ) , max , true ) . map ( unescapeBraces ) ;
7982}
8083function embrace ( str ) {
8184 return '{' + str + '}' ;
@@ -89,17 +92,17 @@ function lte(i, y) {
8992function gte ( i , y ) {
9093 return i >= y ;
9194}
92- function expand_ ( str , isTop ) {
95+ function expand_ ( str , max , isTop ) {
9396 /** @type {string[] } */
9497 const expansions = [ ] ;
9598 const m = ( 0 , balanced_match_1 . balanced ) ( '{' , '}' , str ) ;
9699 if ( ! m )
97100 return [ str ] ;
98101 // no need to expand pre, since it is guaranteed to be free of brace-sets
99102 const pre = m . pre ;
100- const post = m . post . length ? expand_ ( m . post , false ) : [ '' ] ;
103+ const post = m . post . length ? expand_ ( m . post , max , false ) : [ '' ] ;
101104 if ( / \$ $ / . test ( m . pre ) ) {
102- for ( let k = 0 ; k < post . length ; k ++ ) {
105+ for ( let k = 0 ; k < post . length && k < max ; k ++ ) {
103106 const expansion = pre + '{' + m . body + '}' + post [ k ] ;
104107 expansions . push ( expansion ) ;
105108 }
@@ -113,7 +116,7 @@ function expand_(str, isTop) {
113116 // {a},b }
114117 if ( m . post . match ( / , (? ! , ) .* \} / ) ) {
115118 str = m . pre + '{' + m . body + escClose + m . post ;
116- return expand_ ( str ) ;
119+ return expand_ ( str , max , true ) ;
117120 }
118121 return [ str ] ;
119122 }
@@ -125,7 +128,7 @@ function expand_(str, isTop) {
125128 n = parseCommaParts ( m . body ) ;
126129 if ( n . length === 1 && n [ 0 ] !== undefined ) {
127130 // x{{a,b}}y ==> x{a}y x{b}y
128- n = expand_ ( n [ 0 ] , false ) . map ( embrace ) ;
131+ n = expand_ ( n [ 0 ] , max , false ) . map ( embrace ) ;
129132 //XXX is this necessary? Can't seem to hit it in tests.
130133 /* c8 ignore start */
131134 if ( n . length === 1 ) {
@@ -179,11 +182,11 @@ function expand_(str, isTop) {
179182 else {
180183 N = [ ] ;
181184 for ( let j = 0 ; j < n . length ; j ++ ) {
182- N . push . apply ( N , expand_ ( n [ j ] , false ) ) ;
185+ N . push . apply ( N , expand_ ( n [ j ] , max , false ) ) ;
183186 }
184187 }
185188 for ( let j = 0 ; j < N . length ; j ++ ) {
186- for ( let k = 0 ; k < post . length ; k ++ ) {
189+ for ( let k = 0 ; k < post . length && expansions . length < max ; k ++ ) {
187190 const expansion = pre + N [ j ] + post [ k ] ;
188191 if ( ! isTop || isSequence || expansion ) {
189192 expansions . push ( expansion ) ;
0 commit comments