1717// along with this program. If not, see <https://www.gnu.org/licenses/>.
1818
1919const std = @import ("std" );
20+ const log = @import ("../../log.zig" );
2021const URL = @import ("../../url.zig" ).URL ;
2122const Page = @import ("../page.zig" ).Page ;
2223
24+ const iterator = @import ("../iterator/iterator.zig" );
25+
2326const v8 = @import ("v8" );
2427const Env = @import ("../env.zig" ).Env ;
2528
@@ -108,7 +111,8 @@ pub fn constructor(_init: ?HeadersInit, page: *Page) !Headers {
108111}
109112
110113pub fn append (self : * Headers , name : []const u8 , value : []const u8 , allocator : std.mem.Allocator ) ! void {
111- const gop = try self .headers .getOrPut (allocator , name );
114+ const key = try allocator .dupe (u8 , name );
115+ const gop = try self .headers .getOrPut (allocator , key );
112116
113117 if (gop .found_existing ) {
114118 // If we found it, append the value.
@@ -129,13 +133,13 @@ pub fn _delete(self: *Headers, name: []const u8) void {
129133 _ = self .headers .remove (name );
130134}
131135
132- pub const HeaderEntryIterator = struct {
136+ pub const HeadersEntryIterator = struct {
133137 slot : [2 ][]const u8 ,
134138 iter : HeaderHashMap.Iterator ,
135139
136140 // TODO: these SHOULD be in lexigraphical order but I'm not sure how actually
137141 // important that is.
138- pub fn _next (self : * HeaderEntryIterator ) ? [2 ][]const u8 {
142+ pub fn _next (self : * HeadersEntryIterator ) ? [2 ][]const u8 {
139143 if (self .iter .next ()) | entry | {
140144 self .slot [0 ] = entry .key_ptr .* ;
141145 self .slot [1 ] = entry .value_ptr .* ;
@@ -146,10 +150,12 @@ pub const HeaderEntryIterator = struct {
146150 }
147151};
148152
149- pub fn _entries (self : * const Headers ) HeaderEntryIterator {
153+ pub fn _entries (self : * const Headers ) HeadersEntryIterable {
150154 return .{
151- .slot = undefined ,
152- .iter = self .headers .iterator (),
155+ .inner = .{
156+ .slot = undefined ,
157+ .iter = self .headers .iterator (),
158+ },
153159 };
154160}
155161
@@ -171,10 +177,10 @@ pub fn _has(self: *const Headers, name: []const u8) bool {
171177 return self .headers .contains (name );
172178}
173179
174- pub const HeaderKeyIterator = struct {
180+ pub const HeadersKeyIterator = struct {
175181 iter : HeaderHashMap.KeyIterator ,
176182
177- pub fn _next (self : * HeaderKeyIterator ) ? []const u8 {
183+ pub fn _next (self : * HeadersKeyIterator ) ? []const u8 {
178184 if (self .iter .next ()) | key | {
179185 return key .* ;
180186 } else {
@@ -183,21 +189,22 @@ pub const HeaderKeyIterator = struct {
183189 }
184190};
185191
186- pub fn _keys (self : * const Headers ) HeaderKeyIterator {
187- return .{ .iter = self .headers .keyIterator () };
192+ pub fn _keys (self : * const Headers ) HeadersKeyIterable {
193+ return .{ .inner = .{ . iter = self .headers .keyIterator () } };
188194}
189195
190196pub fn _set (self : * Headers , name : []const u8 , value : []const u8 , page : * Page ) ! void {
191197 const arena = page .arena ;
192198
193- const gop = try self .headers .getOrPut (arena , name );
199+ const key = try arena .dupe (u8 , name );
200+ const gop = try self .headers .getOrPut (arena , key );
194201 gop .value_ptr .* = try arena .dupe (u8 , value );
195202}
196203
197- pub const HeaderValueIterator = struct {
204+ pub const HeadersValueIterator = struct {
198205 iter : HeaderHashMap.ValueIterator ,
199206
200- pub fn _next (self : * HeaderValueIterator ) ? []const u8 {
207+ pub fn _next (self : * HeadersValueIterator ) ? []const u8 {
201208 if (self .iter .next ()) | value | {
202209 return value .* ;
203210 } else {
@@ -206,53 +213,15 @@ pub const HeaderValueIterator = struct {
206213 }
207214};
208215
209- pub fn _values (self : * const Headers ) HeaderValueIterator {
210- return .{ .iter = self .headers .valueIterator () };
216+ pub fn _values (self : * const Headers ) HeadersValueIterable {
217+ return .{ .inner = .{ . iter = self .headers .valueIterator () } };
211218}
212219
220+ pub const HeadersKeyIterable = iterator .Iterable (HeadersKeyIterator , "HeadersKeyIterator" );
221+ pub const HeadersValueIterable = iterator .Iterable (HeadersValueIterator , "HeadersValueIterator" );
222+ pub const HeadersEntryIterable = iterator .Iterable (HeadersEntryIterator , "HeadersEntryIterator" );
223+
213224const testing = @import ("../../testing.zig" );
214- test "fetch: headers" {
215- var runner = try testing .jsRunner (testing .tracking_allocator , .{ .url = "https://lightpanda.io" });
216- defer runner .deinit ();
217-
218- try runner .testCases (&.{
219- .{ "let emptyHeaders = new Headers()" , "undefined" },
220- }, .{});
221-
222- try runner .testCases (&.{
223- .{ "let headers = new Headers({'Set-Cookie': 'name=world'})" , "undefined" },
224- .{ "headers.get('set-cookie')" , "name=world" },
225- }, .{});
226-
227- // adapted from the mdn examples
228- try runner .testCases (&.{
229- .{ "const myHeaders = new Headers();" , "undefined" },
230- .{ "myHeaders.append('Content-Type', 'image/jpeg')" , "undefined" },
231- .{ "myHeaders.has('Picture-Type')" , "false" },
232- .{ "myHeaders.get('Content-Type')" , "image/jpeg" },
233- .{ "myHeaders.append('Content-Type', 'image/png')" , "undefined" },
234- .{ "myHeaders.get('Content-Type')" , "image/jpeg, image/png" },
235- .{ "myHeaders.delete('Content-Type')" , "undefined" },
236- .{ "myHeaders.get('Content-Type')" , "null" },
237- .{ "myHeaders.set('Picture-Type', 'image/svg')" , "undefined" },
238- .{ "myHeaders.get('Picture-Type')" , "image/svg" },
239- .{ "myHeaders.has('Picture-Type')" , "true" },
240- }, .{});
241-
242- try runner .testCases (&.{
243- .{ "const originalHeaders = new Headers([['Content-Type', 'application/json'], ['Authorization', 'Bearer token123']])" , "undefined" },
244- .{ "originalHeaders.get('Content-Type')" , "application/json" },
245- .{ "originalHeaders.get('Authorization')" , "Bearer token123" },
246- .{ "const newHeaders = new Headers(originalHeaders)" , "undefined" },
247- .{ "newHeaders.get('Content-Type')" , "application/json" },
248- .{ "newHeaders.get('Authorization')" , "Bearer token123" },
249- .{ "newHeaders.has('Content-Type')" , "true" },
250- .{ "newHeaders.has('Authorization')" , "true" },
251- .{ "newHeaders.has('X-Custom')" , "false" },
252- // Verify that modifying the new headers doesn't affect the original
253- .{ "newHeaders.set('X-Custom', 'test-value')" , "undefined" },
254- .{ "newHeaders.get('X-Custom')" , "test-value" },
255- .{ "originalHeaders.get('X-Custom')" , "null" },
256- .{ "originalHeaders.has('X-Custom')" , "false" },
257- }, .{});
225+ test "fetch: Headers" {
226+ try testing .htmlRunner ("fetch/headers.html" );
258227}
0 commit comments