@@ -36,6 +36,7 @@ function toASCIILower(str) {
36
36
37
37
const SOLIDUS = '/' ;
38
38
const SEMICOLON = ';' ;
39
+
39
40
function parseTypeAndSubtype ( str ) {
40
41
// Skip only HTTP whitespace from start
41
42
let position = SafeStringPrototypeSearch ( str , END_BEGINNING_WHITESPACE ) ;
@@ -72,12 +73,11 @@ function parseTypeAndSubtype(str) {
72
73
throw new ERR_INVALID_MIME_SYNTAX ( 'subtype' , str , trimmedSubtype ) ;
73
74
}
74
75
const subtype = toASCIILower ( trimmedSubtype ) ;
75
- return {
76
- __proto__ : null ,
76
+ return [
77
77
type ,
78
78
subtype ,
79
- parametersStringIndex : position ,
80
- } ;
79
+ position ,
80
+ ] ;
81
81
}
82
82
83
83
const EQUALS_SEMICOLON_OR_END = / [ ; = ] | $ / ;
@@ -123,12 +123,29 @@ const encode = (value) => {
123
123
124
124
class MIMEParams {
125
125
#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
+ }
126
141
127
142
delete ( name ) {
143
+ this . #parse( ) ;
128
144
this . #data. delete ( name ) ;
129
145
}
130
146
131
147
get ( name ) {
148
+ this . #parse( ) ;
132
149
const data = this . #data;
133
150
if ( data . has ( name ) ) {
134
151
return data . get ( name ) ;
@@ -137,10 +154,12 @@ class MIMEParams {
137
154
}
138
155
139
156
has ( name ) {
157
+ this . #parse( ) ;
140
158
return this . #data. has ( name ) ;
141
159
}
142
160
143
161
set ( name , value ) {
162
+ this . #parse( ) ;
144
163
const data = this . #data;
145
164
name = `${ name } ` ;
146
165
value = `${ value } ` ;
@@ -166,18 +185,22 @@ class MIMEParams {
166
185
}
167
186
168
187
* entries ( ) {
188
+ this . #parse( ) ;
169
189
yield * this . #data. entries ( ) ;
170
190
}
171
191
172
192
* keys ( ) {
193
+ this . #parse( ) ;
173
194
yield * this . #data. keys ( ) ;
174
195
}
175
196
176
197
* values ( ) {
198
+ this . #parse( ) ;
177
199
yield * this . #data. values ( ) ;
178
200
}
179
201
180
202
toString ( ) {
203
+ this . #parse( ) ;
181
204
let ret = '' ;
182
205
for ( const { 0 : key , 1 : value } of this . #data) {
183
206
const encoded = encode ( value ) ;
@@ -190,8 +213,11 @@ class MIMEParams {
190
213
191
214
// Used to act as a friendly class to stringifying stuff
192
215
// 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;
195
221
const endOfSource = SafeStringPrototypeSearch (
196
222
StringPrototypeSlice ( str , position ) ,
197
223
START_ENDING_WHITESPACE ,
@@ -270,13 +296,14 @@ class MIMEParams {
270
296
NOT_HTTP_TOKEN_CODE_POINT ) === - 1 &&
271
297
SafeStringPrototypeSearch ( parameterValue ,
272
298
NOT_HTTP_QUOTED_STRING_CODE_POINT ) === - 1 &&
273
- params . has ( parameterString ) === false
299
+ paramsMap . has ( parameterString ) === false
274
300
) {
275
301
paramsMap . set ( parameterString , parameterValue ) ;
276
302
}
277
303
position ++ ;
278
304
}
279
- return paramsMap ;
305
+ this . #data = paramsMap ;
306
+ this . #processed = true ;
280
307
}
281
308
}
282
309
const MIMEParamsStringify = MIMEParams . prototype . toString ;
@@ -293,8 +320,8 @@ ObjectDefineProperty(MIMEParams.prototype, 'toJSON', {
293
320
writable : true ,
294
321
} ) ;
295
322
296
- const { parseParametersString } = MIMEParams ;
297
- delete MIMEParams . parseParametersString ;
323
+ const { instantiateMimeParams } = MIMEParams ;
324
+ delete MIMEParams . instantiateMimeParams ;
298
325
299
326
class MIMEType {
300
327
#type;
@@ -303,14 +330,9 @@ class MIMEType {
303
330
constructor ( string ) {
304
331
string = `${ string } ` ;
305
332
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 ] ) ) ;
314
336
}
315
337
316
338
get type ( ) {
@@ -362,6 +384,8 @@ ObjectDefineProperty(MIMEType.prototype, 'toJSON', {
362
384
} ) ;
363
385
364
386
module . exports = {
387
+ toASCIILower,
388
+ parseTypeAndSubtype,
365
389
MIMEParams,
366
390
MIMEType,
367
391
} ;
0 commit comments