mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-04-03 16:10:29 +00:00
Make js.Bridge aware of string.String for input parameters
Avoids having to allocate small strings when going from v8 -> Zig. Also added a discriminatory type, string.Global which uses the arena, rather than the call_arena, if an allocation _is_ necessary. (This is similar to a feature we had before, but was lost in zigdom). Strings from v8 that need to be persisted, can be allocated directly v8 -> arena, rather than v8 -> call_arena -> arena. I think there are a lot of places where we should use string.String - where strings are expected to be short (e.g. attribute names). But started with just document.querySelector and querySelectorAll.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
|
||||
const std = @import("std");
|
||||
const log = @import("../../log.zig");
|
||||
const string = @import("../../string.zig");
|
||||
|
||||
const js = @import("js.zig");
|
||||
const bridge = @import("bridge.zig");
|
||||
@@ -619,6 +620,19 @@ fn jsValueToStruct(self: *const Local, comptime T: type, js_val: js.Value) !?T {
|
||||
};
|
||||
return try promise.persist();
|
||||
},
|
||||
string.String => {
|
||||
if (!js_val.isString()) {
|
||||
return null;
|
||||
}
|
||||
return try self.valueToStringSSO(js_val, .{.allocator = self.ctx.call_arena});
|
||||
},
|
||||
string.Global => {
|
||||
if (!js_val.isString()) {
|
||||
return null;
|
||||
}
|
||||
// Use arena for persistent strings
|
||||
return .{.str = try self.valueToStringSSO(js_val, .{ .allocator = self.ctx.arena }) };
|
||||
},
|
||||
else => {
|
||||
if (!js_val.isObject()) {
|
||||
return null;
|
||||
@@ -927,6 +941,15 @@ fn probeJsValueToZig(self: *const Local, comptime T: type, js_val: js.Value) !Pr
|
||||
}
|
||||
},
|
||||
.@"struct" => {
|
||||
// Handle string.String and string.Global specially
|
||||
if (T == string.String or T == string.Global) {
|
||||
if (js_val.isString()) {
|
||||
return .{ .ok = {} };
|
||||
}
|
||||
// Anything can be coerced to a string
|
||||
return .{ .coerce = {} };
|
||||
}
|
||||
|
||||
// We don't want to duplicate the code for this, so we call
|
||||
// the actual conversion function.
|
||||
const value = (try self.jsValueToStruct(T, js_val)) orelse {
|
||||
@@ -1118,6 +1141,46 @@ fn _jsStringToZig(self: *const Local, comptime null_terminate: bool, str: anytyp
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Convert JS string to string.String with SSO
|
||||
pub fn valueToStringSSO(self: *const Local, js_val: js.Value, opts: ToStringOpts) !string.String {
|
||||
const string_handle = v8.v8__Value__ToString(js_val.handle, self.handle) orelse {
|
||||
return error.JsException;
|
||||
};
|
||||
return self.jsStringToStringSSO(string_handle, opts);
|
||||
}
|
||||
|
||||
pub fn jsStringToStringSSO(self: *const Local, str: anytype, opts: ToStringOpts) !string.String {
|
||||
const handle = if (@TypeOf(str) == js.String) str.handle else str;
|
||||
const len: usize = @intCast(v8.v8__String__Utf8Length(handle, self.isolate.handle));
|
||||
|
||||
if (len <= 12) {
|
||||
var content: [12]u8 = @splat(0);
|
||||
const n = v8.v8__String__WriteUtf8(handle, self.isolate.handle, &content, len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(n == len);
|
||||
}
|
||||
return .{ .len = @intCast(len), .payload = .{ .content = content } };
|
||||
}
|
||||
|
||||
const allocator = opts.allocator orelse self.call_arena;
|
||||
const buf = try allocator.alloc(u8, len);
|
||||
const n = v8.v8__String__WriteUtf8(handle, self.isolate.handle, buf.ptr, buf.len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(n == len);
|
||||
}
|
||||
|
||||
var prefix: [4]u8 = @splat(0);
|
||||
@memcpy(&prefix, buf[0..4]);
|
||||
|
||||
return .{
|
||||
.len = @intCast(len),
|
||||
.payload = .{ .heap = .{
|
||||
.prefix = prefix,
|
||||
.ptr = buf.ptr,
|
||||
} },
|
||||
};
|
||||
}
|
||||
|
||||
// == Promise Helpers ==
|
||||
pub fn rejectPromise(self: *const Local, value: anytype) !js.Promise {
|
||||
var resolver = js.PromiseResolver.init(self);
|
||||
|
||||
Reference in New Issue
Block a user