@@ -36,6 +36,7 @@ function toASCIILower(str) {
3636
3737const SOLIDUS = '/' ;
3838const SEMICOLON = ';' ;
39+
3940function parseTypeAndSubtype ( str ) {
4041 // Skip only HTTP whitespace from start
4142 let position = SafeStringPrototypeSearch ( str , END_BEGINNING_WHITESPACE ) ;
@@ -72,12 +73,11 @@ function parseTypeAndSubtype(str) {
7273 throw new ERR_INVALID_MIME_SYNTAX ( 'subtype' , str , trimmedSubtype ) ;
7374 }
7475 const subtype = toASCIILower ( trimmedSubtype ) ;
75- return {
76- __proto__ : null ,
76+ return [
7777 type ,
7878 subtype ,
79- parametersStringIndex : position ,
80- } ;
79+ position ,
80+ ] ;
8181}
8282
8383const EQUALS_SEMICOLON_OR_END = / [ ; = ] | $ / ;
@@ -123,12 +123,29 @@ const encode = (value) => {
123123
124124class MIMEParams {
125125 #data = new SafeMap ( ) ;
126+ // We set the flag the MIMEParams instance as processed on initialization
127+ // to defer the parsing of a potentially large string.
128+ #processed = true ;
129+ #string = null ;
130+
131+ /**
132+ * Used to instantiate a MIMEParams object within the MIMEType class and
133+ * to allow it to be parsed lazily.
134+ */
135+ static instantiateMimeParams ( str ) {
136+ const instance = new MIMEParams ( ) ;
137+ instance . #string = str ;
138+ instance . #processed = false ;
139+ return instance ;
140+ }
126141
127142 delete ( name ) {
143+ this . #parse( ) ;
128144 this . #data. delete ( name ) ;
129145 }
130146
131147 get ( name ) {
148+ this . #parse( ) ;
132149 const data = this . #data;
133150 if ( data . has ( name ) ) {
134151 return data . get ( name ) ;
@@ -137,10 +154,12 @@ class MIMEParams {
137154 }
138155
139156 has ( name ) {
157+ this . #parse( ) ;
140158 return this . #data. has ( name ) ;
141159 }
142160
143161 set ( name , value ) {
162+ this . #parse( ) ;
144163 const data = this . #data;
145164 name = `${ name } ` ;
146165 value = `${ value } ` ;
@@ -166,18 +185,22 @@ class MIMEParams {
166185 }
167186
168187 * entries ( ) {
188+ this . #parse( ) ;
169189 yield * this . #data. entries ( ) ;
170190 }
171191
172192 * keys ( ) {
193+ this . #parse( ) ;
173194 yield * this . #data. keys ( ) ;
174195 }
175196
176197 * values ( ) {
198+ this . #parse( ) ;
177199 yield * this . #data. values ( ) ;
178200 }
179201
180202 toString ( ) {
203+ this . #parse( ) ;
181204 let ret = '' ;
182205 for ( const { 0 : key , 1 : value } of this . #data) {
183206 const encoded = encode ( value ) ;
@@ -190,8 +213,11 @@ class MIMEParams {
190213
191214 // Used to act as a friendly class to stringifying stuff
192215 // not meant to be exposed to users, could inject invalid values
193- static parseParametersString ( str , position , params ) {
194- const paramsMap = params . #data;
216+ #parse( ) {
217+ if ( this . #processed) return ; // already parsed
218+ const paramsMap = this . #data;
219+ let position = 0 ;
220+ const str = this . #string;
195221 const endOfSource = SafeStringPrototypeSearch (
196222 StringPrototypeSlice ( str , position ) ,
197223 START_ENDING_WHITESPACE ,
@@ -270,13 +296,14 @@ class MIMEParams {
270296 NOT_HTTP_TOKEN_CODE_POINT ) === - 1 &&
271297 SafeStringPrototypeSearch ( parameterValue ,
272298 NOT_HTTP_QUOTED_STRING_CODE_POINT ) === - 1 &&
273- params . has ( parameterString ) === false
299+ paramsMap . has ( parameterString ) === false
274300 ) {
275301 paramsMap . set ( parameterString , parameterValue ) ;
276302 }
277303 position ++ ;
278304 }
279- return paramsMap ;
305+ this . #data = paramsMap ;
306+ this . #processed = true ;
280307 }
281308}
282309const MIMEParamsStringify = MIMEParams . prototype . toString ;
@@ -293,8 +320,8 @@ ObjectDefineProperty(MIMEParams.prototype, 'toJSON', {
293320 writable : true ,
294321} ) ;
295322
296- const { parseParametersString } = MIMEParams ;
297- delete MIMEParams . parseParametersString ;
323+ const { instantiateMimeParams } = MIMEParams ;
324+ delete MIMEParams . instantiateMimeParams ;
298325
299326class MIMEType {
300327 #type;
@@ -303,14 +330,9 @@ class MIMEType {
303330 constructor ( string ) {
304331 string = `${ string } ` ;
305332 const data = parseTypeAndSubtype ( string ) ;
306- this . #type = data . type ;
307- this . #subtype = data . subtype ;
308- this . #parameters = new MIMEParams ( ) ;
309- parseParametersString (
310- string ,
311- data . parametersStringIndex ,
312- this . #parameters,
313- ) ;
333+ this . #type = data [ 0 ] ;
334+ this . #subtype = data [ 1 ] ;
335+ this . #parameters = instantiateMimeParams ( StringPrototypeSlice ( string , data [ 2 ] ) ) ;
314336 }
315337
316338 get type ( ) {
@@ -362,6 +384,8 @@ ObjectDefineProperty(MIMEType.prototype, 'toJSON', {
362384} ) ;
363385
364386module . exports = {
387+ toASCIILower,
388+ parseTypeAndSubtype,
365389 MIMEParams,
366390 MIMEType,
367391} ;
0 commit comments