11const assert = require ( 'node:assert' )
2- const { isomorphicDecode } = require ( './util' )
32
43const encoder = new TextEncoder ( )
54
@@ -604,18 +603,7 @@ function isHTTPWhiteSpace (char) {
604603 * @param {boolean } [trailing=true]
605604 */
606605function removeHTTPWhitespace ( str , leading = true , trailing = true ) {
607- let lead = 0
608- let trail = str . length - 1
609-
610- if ( leading ) {
611- while ( lead < str . length && isHTTPWhiteSpace ( str . charCodeAt ( lead ) ) ) lead ++
612- }
613-
614- if ( trailing ) {
615- while ( trail > 0 && isHTTPWhiteSpace ( str . charCodeAt ( trail ) ) ) trail --
616- }
617-
618- return lead === 0 && trail === str . length - 1 ? str : str . slice ( lead , trail + 1 )
606+ return removeChars ( str , leading , trailing , isHTTPWhiteSpace )
619607}
620608
621609/**
@@ -634,20 +622,110 @@ function isASCIIWhitespace (char) {
634622 * @param {boolean } [trailing=true]
635623 */
636624function removeASCIIWhitespace ( str , leading = true , trailing = true ) {
625+ return removeChars ( str , leading , trailing , isASCIIWhitespace )
626+ }
627+
628+ /**
629+ *
630+ * @param {string } str
631+ * @param {boolean } leading
632+ * @param {boolean } trailing
633+ * @param {(charCode: number) => boolean } predicate
634+ * @returns
635+ */
636+ function removeChars ( str , leading , trailing , predicate ) {
637637 let lead = 0
638638 let trail = str . length - 1
639639
640640 if ( leading ) {
641- while ( lead < str . length && isASCIIWhitespace ( str . charCodeAt ( lead ) ) ) lead ++
641+ while ( lead < str . length && predicate ( str . charCodeAt ( lead ) ) ) lead ++
642642 }
643643
644644 if ( trailing ) {
645- while ( trail > 0 && isASCIIWhitespace ( str . charCodeAt ( trail ) ) ) trail --
645+ while ( trail > 0 && predicate ( str . charCodeAt ( trail ) ) ) trail --
646646 }
647647
648648 return lead === 0 && trail === str . length - 1 ? str : str . slice ( lead , trail + 1 )
649649}
650650
651+ /**
652+ * @see https://infra.spec.whatwg.org/#isomorphic-decode
653+ * @param {Uint8Array } input
654+ * @returns {string }
655+ */
656+ function isomorphicDecode ( input ) {
657+ // 1. To isomorphic decode a byte sequence input, return a string whose code point
658+ // length is equal to input’s length and whose code points have the same values
659+ // as the values of input’s bytes, in the same order.
660+ const length = input . length
661+ if ( ( 2 << 15 ) - 1 > length ) {
662+ return String . fromCharCode . apply ( null , input )
663+ }
664+ let result = '' ; let i = 0
665+ let addition = ( 2 << 15 ) - 1
666+ while ( i < length ) {
667+ if ( i + addition > length ) {
668+ addition = length - i
669+ }
670+ result += String . fromCharCode . apply ( null , input . subarray ( i , i += addition ) )
671+ }
672+ return result
673+ }
674+
675+ /**
676+ * @see https://mimesniff.spec.whatwg.org/#minimize-a-supported-mime-type
677+ * @param {Exclude<ReturnType<typeof parseMIMEType>, 'failure'> } mimeType
678+ */
679+ function minimizeSupportedMimeType ( mimeType ) {
680+ switch ( mimeType . essence ) {
681+ case 'application/ecmascript' :
682+ case 'application/javascript' :
683+ case 'application/x-ecmascript' :
684+ case 'application/x-javascript' :
685+ case 'text/ecmascript' :
686+ case 'text/javascript' :
687+ case 'text/javascript1.0' :
688+ case 'text/javascript1.1' :
689+ case 'text/javascript1.2' :
690+ case 'text/javascript1.3' :
691+ case 'text/javascript1.4' :
692+ case 'text/javascript1.5' :
693+ case 'text/jscript' :
694+ case 'text/livescript' :
695+ case 'text/x-ecmascript' :
696+ case 'text/x-javascript' :
697+ // 1. If mimeType is a JavaScript MIME type, then return "text/javascript".
698+ return 'text/javascript'
699+ case 'application/json' :
700+ case 'text/json' :
701+ // 2. If mimeType is a JSON MIME type, then return "application/json".
702+ return 'application/json'
703+ case 'image/svg+xml' :
704+ // 3. If mimeType’s essence is "image/svg+xml", then return "image/svg+xml".
705+ return 'image/svg+xml'
706+ case 'text/xml' :
707+ case 'application/xml' :
708+ // 4. If mimeType is an XML MIME type, then return "application/xml".
709+ return 'application/xml'
710+ }
711+
712+ // 2. If mimeType is a JSON MIME type, then return "application/json".
713+ if ( mimeType . subtype . endsWith ( '+json' ) ) {
714+ return 'application/json'
715+ }
716+
717+ // 4. If mimeType is an XML MIME type, then return "application/xml".
718+ if ( mimeType . subtype . endsWith ( '+xml' ) ) {
719+ return 'application/xml'
720+ }
721+
722+ // 5. If mimeType is supported by the user agent, then return mimeType’s essence.
723+ // Technically, node doesn't support any mimetypes.
724+
725+ // 6. Return the empty string.
726+ return ''
727+ }
728+
651729module . exports = {
652730 dataURLProcessor,
653731 URLSerializer,
@@ -656,5 +734,7 @@ module.exports = {
656734 stringPercentDecode,
657735 parseMIMEType,
658736 collectAnHTTPQuotedString,
659- serializeAMimeType
737+ serializeAMimeType,
738+ removeChars,
739+ minimizeSupportedMimeType
660740}
0 commit comments