Skip to content

Commit bd0fa14

Browse files
committed
Merge branch 'main' into css_style_declaration
2 parents a2e0fd2 + d262f01 commit bd0fa14

File tree

3 files changed

+190
-27
lines changed

3 files changed

+190
-27
lines changed

src/browser/html/elements.zig

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,52 @@ pub const HTMLImageElement = struct {
568568
pub const Self = parser.Image;
569569
pub const prototype = *HTMLElement;
570570
pub const subtype = .node;
571+
pub const js_name = "Image";
572+
573+
pub fn constructor(width: ?u32, height: ?u32, state: *const SessionState) !*parser.Image {
574+
const element = try parser.documentCreateElement(parser.documentHTMLToDocument(state.window.document), "img");
575+
const image: *parser.Image = @ptrCast(element);
576+
if (width) |width_| try parser.imageSetWidth(image, width_);
577+
if (height) |height_| try parser.imageSetHeight(image, height_);
578+
return image;
579+
}
580+
581+
pub fn get_alt(self: *parser.Image) ![]const u8 {
582+
return try parser.imageGetAlt(self);
583+
}
584+
pub fn set_alt(self: *parser.Image, alt: []const u8) !void {
585+
try parser.imageSetAlt(self, alt);
586+
}
587+
pub fn get_src(self: *parser.Image) ![]const u8 {
588+
return try parser.imageGetSrc(self);
589+
}
590+
pub fn set_src(self: *parser.Image, src: []const u8) !void {
591+
try parser.imageSetSrc(self, src);
592+
}
593+
pub fn get_useMap(self: *parser.Image) ![]const u8 {
594+
return try parser.imageGetUseMap(self);
595+
}
596+
pub fn set_useMap(self: *parser.Image, use_map: []const u8) !void {
597+
try parser.imageSetUseMap(self, use_map);
598+
}
599+
pub fn get_height(self: *parser.Image) !u32 {
600+
return try parser.imageGetHeight(self);
601+
}
602+
pub fn set_height(self: *parser.Image, height: u32) !void {
603+
try parser.imageSetHeight(self, height);
604+
}
605+
pub fn get_width(self: *parser.Image) !u32 {
606+
return try parser.imageGetWidth(self);
607+
}
608+
pub fn set_width(self: *parser.Image, width: u32) !void {
609+
try parser.imageSetWidth(self, width);
610+
}
611+
pub fn get_isMap(self: *parser.Image) !bool {
612+
return try parser.imageGetIsMap(self);
613+
}
614+
pub fn set_isMap(self: *parser.Image, is_map: bool) !void {
615+
try parser.imageSetIsMap(self, is_map);
616+
}
571617
};
572618

573619
pub const HTMLInputElement = struct {
@@ -1074,4 +1120,30 @@ test "Browser.HTML.Element" {
10741120
.{ "style.length", "4" },
10751121
}, .{});
10761122

1123+
// Image
1124+
try runner.testCases(&.{
1125+
// Testing constructors
1126+
.{ "(new Image).width", "0" },
1127+
.{ "(new Image).height", "0" },
1128+
.{ "(new Image(4)).width", "4" },
1129+
.{ "(new Image(4, 6)).height", "6" },
1130+
1131+
// Testing ulong property
1132+
.{ "let fruit = new Image", null },
1133+
.{ "fruit.width", "0" },
1134+
.{ "fruit.width = 5", "5" },
1135+
.{ "fruit.width", "5" },
1136+
.{ "fruit.width = '15'", "15" },
1137+
.{ "fruit.width", "15" },
1138+
.{ "fruit.width = 'apple'", "apple" },
1139+
.{ "fruit.width;", "0" },
1140+
1141+
// Testing string property
1142+
.{ "let lyric = new Image", null },
1143+
.{ "lyric.src", "" },
1144+
.{ "lyric.src = 'okay'", "okay" },
1145+
.{ "lyric.src", "okay" },
1146+
.{ "lyric.src = 15", "15" },
1147+
.{ "lyric.src", "15" },
1148+
}, .{});
10771149
}

src/browser/netsurf.zig

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2509,3 +2509,84 @@ pub fn htmlCollectionItem(collection: *HTMLCollection, index: u32) !*Node {
25092509
try DOMErr(err);
25102510
return @ptrCast(node.?);
25112511
}
2512+
2513+
const ulongNegativeOne = 4294967295;
2514+
2515+
// Image
2516+
// Image.name is deprecated
2517+
// Image.align is deprecated
2518+
// Image.border is deprecated
2519+
// Image.longDesc is deprecated
2520+
// Image.hspace is deprecated
2521+
// Image.vspace is deprecated
2522+
2523+
pub fn imageGetAlt(image: *Image) ![]const u8 {
2524+
var s_: ?*String = null;
2525+
const err = c.dom_html_image_element_get_alt(image, &s_);
2526+
try DOMErr(err);
2527+
const s = s_ orelse return "";
2528+
return strToData(s);
2529+
}
2530+
pub fn imageSetAlt(image: *Image, alt: []const u8) !void {
2531+
const err = c.dom_html_image_element_set_alt(image, try strFromData(alt));
2532+
try DOMErr(err);
2533+
}
2534+
2535+
pub fn imageGetSrc(image: *Image) ![]const u8 {
2536+
var s_: ?*String = null;
2537+
const err = c.dom_html_image_element_get_src(image, &s_);
2538+
try DOMErr(err);
2539+
const s = s_ orelse return "";
2540+
return strToData(s);
2541+
}
2542+
pub fn imageSetSrc(image: *Image, src: []const u8) !void {
2543+
const err = c.dom_html_image_element_set_src(image, try strFromData(src));
2544+
try DOMErr(err);
2545+
}
2546+
2547+
pub fn imageGetUseMap(image: *Image) ![]const u8 {
2548+
var s_: ?*String = null;
2549+
const err = c.dom_html_image_element_get_use_map(image, &s_);
2550+
try DOMErr(err);
2551+
const s = s_ orelse return "";
2552+
return strToData(s);
2553+
}
2554+
pub fn imageSetUseMap(image: *Image, use_map: []const u8) !void {
2555+
const err = c.dom_html_image_element_set_use_map(image, try strFromData(use_map));
2556+
try DOMErr(err);
2557+
}
2558+
2559+
pub fn imageGetHeight(image: *Image) !u32 {
2560+
var height: u32 = 0;
2561+
const err = c.dom_html_image_element_get_height(image, &height);
2562+
try DOMErr(err);
2563+
if (height == ulongNegativeOne) return 0;
2564+
return height;
2565+
}
2566+
pub fn imageSetHeight(image: *Image, height: u32) !void {
2567+
const err = c.dom_html_image_element_set_height(image, height);
2568+
try DOMErr(err);
2569+
}
2570+
2571+
pub fn imageGetWidth(image: *Image) !u32 {
2572+
var width: u32 = 0;
2573+
const err = c.dom_html_image_element_get_width(image, &width);
2574+
try DOMErr(err);
2575+
if (width == ulongNegativeOne) return 0;
2576+
return width;
2577+
}
2578+
pub fn imageSetWidth(image: *Image, width: u32) !void {
2579+
const err = c.dom_html_image_element_set_width(image, width);
2580+
try DOMErr(err);
2581+
}
2582+
2583+
pub fn imageGetIsMap(image: *Image) !bool {
2584+
var is_map: bool = false;
2585+
const err = c.dom_html_image_element_get_is_map(image, &is_map);
2586+
try DOMErr(err);
2587+
return is_map;
2588+
}
2589+
pub fn imageSetIsMap(image: *Image, is_map: bool) !void {
2590+
const err = c.dom_html_image_element_set_is_map(image, is_map);
2591+
try DOMErr(err);
2592+
}

src/http/client.zig

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ pub const Client = struct {
4949
http_proxy: ?Uri,
5050
root_ca: tls.config.CertBundle,
5151
tls_verify_host: bool = true,
52-
idle_connections: IdleConnections,
53-
connection_pool: std.heap.MemoryPool(Connection),
52+
connection_manager: ConnectionManager,
5453

5554
const Opts = struct {
5655
tls_verify_host: bool = true,
@@ -65,17 +64,16 @@ pub const Client = struct {
6564
const state_pool = try StatePool.init(allocator, max_concurrent);
6665
errdefer state_pool.deinit(allocator);
6766

68-
const idle_connections = IdleConnections.init(allocator, opts.max_idle_connection);
69-
errdefer idle_connections.deinit();
67+
const connection_manager = ConnectionManager.init(allocator, opts.max_idle_connection);
68+
errdefer connection_manager.deinit();
7069

7170
return .{
7271
.root_ca = root_ca,
7372
.allocator = allocator,
7473
.state_pool = state_pool,
7574
.http_proxy = opts.http_proxy,
76-
.idle_connections = idle_connections,
7775
.tls_verify_host = opts.tls_verify_host,
78-
.connection_pool = std.heap.MemoryPool(Connection).init(allocator),
76+
.connection_manager = connection_manager,
7977
};
8078
}
8179

@@ -85,8 +83,7 @@ pub const Client = struct {
8583
self.root_ca.deinit(allocator);
8684
}
8785
self.state_pool.deinit(allocator);
88-
self.idle_connections.deinit();
89-
self.connection_pool.deinit();
86+
self.connection_manager.deinit();
9087
}
9188

9289
pub fn request(self: *Client, method: Request.Method, uri: *const Uri) !Request {
@@ -307,36 +304,33 @@ pub const Request = struct {
307304
self._connection = null;
308305

309306
if (self._keepalive == false) {
310-
self.destroyConnection(connection);
307+
self._client.connection_manager.destroy(connection);
311308
return;
312309
}
313310

314-
self._client.idle_connections.put(connection) catch |err| {
311+
self._client.connection_manager.keepIdle(connection) catch |err| {
315312
self.destroyConnection(connection);
316313
log.err("failed to release connection to pool: {}", .{err});
317314
};
318315
}
319316

320317
fn createConnection(self: *Request, socket: posix.socket_t, blocking: bool) !*Connection {
321318
const client = self._client;
322-
const connection = try client.connection_pool.create();
323-
errdefer client.connection_pool.destroy(connection);
319+
const connection, const owned_host = try client.connection_manager.create(self._connect_host);
324320

325321
connection.* = .{
326322
.tls = null,
327323
.socket = socket,
328324
.blocking = blocking,
325+
.host = owned_host,
329326
.port = self._connect_port,
330-
.host = try client.allocator.dupe(u8, self._connect_host),
331327
};
332328

333329
return connection;
334330
}
335331

336332
fn destroyConnection(self: *Request, connection: *Connection) void {
337-
const client = self._client;
338-
connection.deinit(client.allocator);
339-
client.connection_pool.destroy(connection);
333+
self._client.connection_manager.destroy(connection);
340334
}
341335

342336
const AddHeaderOpts = struct {
@@ -403,9 +397,10 @@ pub const Request = struct {
403397
posix.close(socket);
404398
return err;
405399
};
400+
self._connection = connection;
406401

407402
if (self._secure) {
408-
connection.tls = .{
403+
self._connection.?.tls = .{
409404
.blocking = try tls.client(std.net.Stream{ .handle = socket }, .{
410405
.host = self._connect_host,
411406
.root_ca = self._client.root_ca,
@@ -415,7 +410,6 @@ pub const Request = struct {
415410
};
416411
}
417412

418-
self._connection = connection;
419413
self._connection_from_keepalive = false;
420414
}
421415

@@ -605,7 +599,7 @@ pub const Request = struct {
605599
return null;
606600
}
607601

608-
return self._client.idle_connections.get(self._secure, self._connect_host, self._connect_port, blocking);
602+
return self._client.connection_manager.get(self._secure, self._connect_host, self._connect_port, blocking);
609603
}
610604

611605
fn createSocket(self: *Request, blocking: bool) !struct { posix.socket_t, std.net.Address } {
@@ -2219,29 +2213,31 @@ const StatePool = struct {
22192213
// always re-use the connection (just toggle the socket's blocking status), but
22202214
// for TLS, we'd need to see if the two different TLS objects (blocking and non
22212215
// blocking) can be converted from each other.
2222-
const IdleConnections = struct {
2216+
const ConnectionManager = struct {
22232217
max: usize,
22242218
idle: List,
22252219
count: usize,
22262220
mutex: Thread.Mutex,
22272221
allocator: Allocator,
22282222
node_pool: std.heap.MemoryPool(Node),
2223+
connection_pool: std.heap.MemoryPool(Connection),
22292224

22302225
const List = std.DoublyLinkedList(*Connection);
22312226
const Node = List.Node;
22322227

2233-
fn init(allocator: Allocator, max: usize) IdleConnections {
2228+
fn init(allocator: Allocator, max: usize) ConnectionManager {
22342229
return .{
22352230
.max = max,
22362231
.count = 0,
22372232
.idle = .{},
22382233
.mutex = .{},
22392234
.allocator = allocator,
22402235
.node_pool = std.heap.MemoryPool(Node).init(allocator),
2236+
.connection_pool = std.heap.MemoryPool(Connection).init(allocator),
22412237
};
22422238
}
22432239

2244-
fn deinit(self: *IdleConnections) void {
2240+
fn deinit(self: *ConnectionManager) void {
22452241
const allocator = self.allocator;
22462242

22472243
self.mutex.lock();
@@ -2253,9 +2249,10 @@ const IdleConnections = struct {
22532249
node = next;
22542250
}
22552251
self.node_pool.deinit();
2252+
self.connection_pool.deinit();
22562253
}
22572254

2258-
fn get(self: *IdleConnections, secure: bool, host: []const u8, port: u16, blocking: bool) ?*Connection {
2255+
fn get(self: *ConnectionManager, secure: bool, host: []const u8, port: u16, blocking: bool) ?*Connection {
22592256
self.mutex.lock();
22602257
defer self.mutex.unlock();
22612258

@@ -2273,28 +2270,41 @@ const IdleConnections = struct {
22732270
return null;
22742271
}
22752272

2276-
fn put(self: *IdleConnections, connection: *Connection) !void {
2273+
fn keepIdle(self: *ConnectionManager, connection: *Connection) !void {
22772274
self.mutex.lock();
22782275
defer self.mutex.unlock();
22792276

22802277
var node: *Node = undefined;
22812278
if (self.count == self.max) {
22822279
const oldest = self.idle.popFirst() orelse {
22832280
std.debug.assert(self.max == 0);
2284-
connection.deinit(self.allocator);
2281+
self.destroy(connection);
22852282
return;
22862283
};
2287-
oldest.data.deinit(self.allocator);
2284+
self.destroy(oldest.data);
22882285
// re-use the node
22892286
node = oldest;
22902287
} else {
2291-
self.count += 1;
22922288
node = try self.node_pool.create();
2289+
self.count += 1;
22932290
}
22942291

22952292
node.data = connection;
22962293
self.idle.append(node);
22972294
}
2295+
2296+
fn create(self: *ConnectionManager, host: []const u8) !struct { *Connection, []const u8 } {
2297+
const connection = try self.connection_pool.create();
2298+
errdefer self.connection_pool.destroy(connection);
2299+
2300+
const owned_host = try self.allocator.dupe(u8, host);
2301+
return .{ connection, owned_host };
2302+
}
2303+
2304+
fn destroy(self: *ConnectionManager, connection: *Connection) void {
2305+
connection.deinit(self.allocator);
2306+
self.connection_pool.destroy(connection);
2307+
}
22982308
};
22992309

23002310
const testing = @import("../testing.zig");

0 commit comments

Comments
 (0)