Skip to content

Commit 7bdea1b

Browse files
committed
Support binding JS strings to [:0]const u8
Some APIs need a null-terminated string. Currently, they have to ask for a `[]const u8` and then convert it to a `[:0]const u8`. This is 2 allocations: 1 for jsruntime to get the `[]const u8` from v8, and then one to get the [:0]. By supporting `[:0]const u8` directly, this is now a single allocation.
1 parent 66ec087 commit 7bdea1b

File tree

3 files changed

+36
-35
lines changed

3 files changed

+36
-35
lines changed

src/browser/dom/implementation.zig

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,20 @@ pub const DOMImplementation = struct {
3131

3232
pub fn _createDocumentType(
3333
_: *DOMImplementation,
34-
qname: []const u8,
35-
publicId: []const u8,
36-
systemId: []const u8,
37-
state: *SessionState,
34+
qname: [:0]const u8,
35+
publicId: [:0]const u8,
36+
systemId: [:0]const u8,
3837
) !*parser.DocumentType {
39-
const allocator = state.arena;
40-
const cqname = try allocator.dupeZ(u8, qname);
41-
defer allocator.free(cqname);
42-
43-
const cpublicId = try allocator.dupeZ(u8, publicId);
44-
defer allocator.free(cpublicId);
45-
46-
const csystemId = try allocator.dupeZ(u8, systemId);
47-
defer allocator.free(csystemId);
48-
49-
return try parser.domImplementationCreateDocumentType(cqname, cpublicId, csystemId);
38+
return try parser.domImplementationCreateDocumentType(qname, publicId, systemId);
5039
}
5140

5241
pub fn _createDocument(
5342
_: *DOMImplementation,
54-
namespace: ?[]const u8,
55-
qname: ?[]const u8,
43+
namespace: ?[:0]const u8,
44+
qname: ?[:0]const u8,
5645
doctype: ?*parser.DocumentType,
57-
state: *SessionState,
5846
) !*parser.Document {
59-
const allocator = state.arena;
60-
var cnamespace: ?[:0]const u8 = null;
61-
if (namespace) |ns| {
62-
cnamespace = try allocator.dupeZ(u8, ns);
63-
}
64-
defer if (cnamespace) |v| allocator.free(v);
65-
66-
var cqname: ?[:0]const u8 = null;
67-
if (qname) |qn| {
68-
cqname = try allocator.dupeZ(u8, qn);
69-
}
70-
defer if (cqname) |v| allocator.free(v);
71-
72-
return try parser.domImplementationCreateDocument(cnamespace, cqname, doctype);
47+
return try parser.domImplementationCreateDocument(namespace, qname, doctype);
7348
}
7449

7550
pub fn _createHTMLDocument(_: *DOMImplementation, title: ?[]const u8) !*parser.DocumentHTML {
@@ -79,8 +54,6 @@ pub const DOMImplementation = struct {
7954
pub fn _hasFeature(_: *DOMImplementation) bool {
8055
return true;
8156
}
82-
83-
pub fn deinit(_: *DOMImplementation, _: std.mem.Allocator) void {}
8457
};
8558

8659
// Tests

src/runtime/js.zig

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1862,7 +1862,13 @@ fn Caller(comptime E: type) type {
18621862
},
18631863
.slice => {
18641864
if (ptr.child == u8) {
1865-
return valueToString(self.call_allocator, js_value, self.isolate, self.context);
1865+
if (ptr.sentinel()) |s| {
1866+
if (comptime s == 0) {
1867+
return valueToStringZ(self.call_allocator, js_value, self.isolate, self.context);
1868+
}
1869+
} else {
1870+
return valueToString(self.call_allocator, js_value, self.isolate, self.context);
1871+
}
18661872
}
18671873

18681874
// TODO: TypedArray
@@ -2241,6 +2247,16 @@ fn valueToString(allocator: Allocator, value: v8.Value, isolate: v8.Isolate, con
22412247
return buf;
22422248
}
22432249

2250+
fn valueToStringZ(allocator: Allocator, value: v8.Value, isolate: v8.Isolate, context: v8.Context) ![:0]u8 {
2251+
const str = try value.toString(context);
2252+
const len = str.lenUtf8(isolate);
2253+
const buf = try allocator.alloc(u8, len + 1);
2254+
const n = str.writeUtf8(isolate, buf[0..len]);
2255+
std.debug.assert(n == len);
2256+
buf[len] = 0;
2257+
return buf[0..len :0];
2258+
}
2259+
22442260
const NoopInspector = struct {
22452261
pub fn onInspectorResponse(_: *anyopaque, _: u32, _: []const u8) void {}
22462262
pub fn onInspectorEvent(_: *anyopaque, _: []const u8) void {}

src/runtime/test_primitive_types.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ const Primitives = struct {
9696
pub fn _checkOptionalReturnString(_: *const Primitives) ?[]const u8 {
9797
return "ok";
9898
}
99+
100+
pub fn _echoString(_: *const Primitives, a: []const u8) []const u8 {
101+
return a;
102+
}
103+
104+
pub fn _echoStringZ(_: *const Primitives, a: [:0]const u8) []const u8 {
105+
return a;
106+
}
99107
};
100108

101109
const testing = @import("testing.zig");
@@ -172,5 +180,9 @@ test "JS: primitive types" {
172180
.{ "p.checkOptionalReturn() === true;", "true" },
173181
.{ "p.checkOptionalReturnNull() === null;", "true" },
174182
.{ "p.checkOptionalReturnString() === 'ok';", "true" },
183+
184+
// strings
185+
.{ "p.echoString('over 9000!');", "over 9000!" },
186+
.{ "p.echoStringZ('Teg');", "Teg" },
175187
}, .{});
176188
}

0 commit comments

Comments
 (0)