11class Headers {
22 constructor ( init = undefined ) {
3- console . log ( 'init' , init )
3+ // TODO: webidl
4+ // this.brand = brand;
45 // @ts -ignore - this is a hack to make the URL object work
6+ this . guard = "none" ;
7+ // @ts -ignore - this is a hack to make the URL object work
8+ this . headerList = [ ] ;
9+ fillHeaders ( this , init ) ;
10+ }
11+
12+ get ( name ) {
13+ // @ts -ignore - this is a hack to make the URL object work
14+ return getHeader ( this . headerList , name ) ;
15+ }
16+ }
17+
18+ function fillHeaders ( headers , object ) {
19+ if ( Array . isArray ( object ) ) {
20+ for ( let i = 0 ; i < object . length ; ++ i ) {
21+ const header = object [ i ] ;
22+ if ( header . length !== 2 ) {
23+ throw new TypeError (
24+ `Invalid header: length must be 2, but is ${ header . length } ` ,
25+ ) ;
26+ }
27+ appendHeader ( headers , header [ 0 ] , header [ 1 ] ) ;
28+ }
29+ } else {
30+ for ( const key in object ) {
31+ if ( ! Object . hasOwn ( object , key ) ) {
32+ continue ;
33+ }
34+ appendHeader ( headers , key , object [ key ] ) ;
35+ }
36+ }
37+ }
38+
39+ /**
40+ * @param {string } s
41+ * @returns {string }
42+ */
43+ function byteLowerCase ( s ) {
44+ // NOTE: correct since all callers convert to ByteString first
45+ // TODO(@AaronO): maybe prefer a ByteString_Lower webidl converter
46+ return s ;
47+ }
48+
49+ // https://fetch.spec.whatwg.org/#concept-headers-append
50+ function appendHeader ( headers , name , value ) {
51+ // 1.
52+ value = normalizeHeaderValue ( value ) ;
53+
54+ // 2.
55+ // if (!checkHeaderNameForHttpTokenCodePoint(name)) {
56+ // throw new TypeError(`Invalid header name: "${name}"`);
57+ // }
58+ // if (!checkForInvalidValueChars(value)) {
59+ // throw new TypeError(`Invalid header value: "${value}"`);
60+ // }
61+
62+ // 3
63+ if ( headers . guard == "immutable" ) {
64+ throw new TypeError ( "Cannot change header: headers are immutable" ) ;
65+ }
66+
67+ // 7.
68+ const list = headers . headerList ;
69+ const lowercaseName = byteLowerCase ( name ) ;
70+ for ( let i = 0 ; i < list . length ; i ++ ) {
71+ if ( byteLowerCase ( list [ i ] [ 0 ] ) === lowercaseName ) {
72+ name = list [ i ] [ 0 ] ;
73+ break ;
74+ }
75+ }
76+ list . push ( [ name , value ] ) ;
77+ }
78+
79+ /**
80+ * @param {string } potentialValue
81+ * @returns {string }
82+ */
83+ function normalizeHeaderValue ( potentialValue ) {
84+ return httpTrim ( potentialValue ) ;
85+ }
86+
87+ // TODO: move to web
88+ function isHttpWhitespace ( char ) {
89+ switch ( char ) {
90+ case "\u0009" :
91+ case "\u000A" :
92+ case "\u000D" :
93+ case "\u0020" :
94+ return true ;
95+ default :
96+ return false ;
97+ }
98+ }
99+
100+ // const HTTP_BETWEEN_WHITESPACE = new SafeRegExp(
101+ // `^[${HTTP_WHITESPACE_MATCHER}]*(.*?)[${HTTP_WHITESPACE_MATCHER}]*$`,
102+ // );
103+ // TODO: move to web
104+ function httpTrim ( s ) {
105+ if ( ! isHttpWhitespace ( s [ 0 ] ) && ! isHttpWhitespace ( s [ s . length - 1 ] ) ) {
106+ return s ;
107+ }
108+ // return String.prototype.match(s, HTTP_BETWEEN_WHITESPACE)?.[1] ?? "";
109+ // TODO: implement to nova RegExp
110+ return s ;
111+ }
112+
113+ // https://fetch.spec.whatwg.org/#concept-header-list-get
114+ function getHeader ( list , name ) {
115+ const lowercaseName = byteLowerCase ( name ) ;
116+ const entries = [ ] ;
117+ for ( let i = 0 ; i < list . length ; i ++ ) {
118+ if ( byteLowerCase ( list [ i ] [ 0 ] ) === lowercaseName ) {
119+ entries . push ( list [ i ] [ 1 ] ) ;
120+ }
121+ }
122+
123+ if ( entries . length === 0 ) {
124+ return null ;
125+ } else {
126+ return entries . join ( entries , "\x2C\x20" ) ;
5127 }
6- }
128+ }
0 commit comments