mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-03 22:13:46 +00:00
Merge pull request #1433 from lightpanda-io/js_string
Cleanup js -> string
This commit is contained in:
@@ -312,14 +312,14 @@ fn isInErrorSet(err: anyerror, comptime T: type) bool {
|
||||
}
|
||||
|
||||
fn nameToString(self: *const Caller, comptime T: type, name: *const v8.Name) !T {
|
||||
const v8_string = @as(*const v8.String, @ptrCast(name));
|
||||
const handle = @as(*const v8.String, @ptrCast(name));
|
||||
if (T == string.String) {
|
||||
return self.local.jsStringToStringSSO(v8_string, .{});
|
||||
return js.String.toSSO(.{ .local = &self.local, .handle = handle }, false);
|
||||
}
|
||||
if (T == string.Global) {
|
||||
return self.local.jsStringToStringSSO(v8_string, .{ .allocator = self.local.ctx.allocator });
|
||||
return js.String.toSSO(.{ .local = &self.local, .handle = handle }, true);
|
||||
}
|
||||
return try self.local.valueHandleToString(v8_string, .{});
|
||||
return try js.String.toSlice(.{ .local = &self.local, .handle = handle });
|
||||
}
|
||||
|
||||
fn handleError(self: *Caller, comptime T: type, comptime F: type, err: anyerror, info: anytype, comptime opts: CallOpts) void {
|
||||
|
||||
@@ -359,9 +359,13 @@ pub fn module(self: *Context, comptime want_result: bool, local: *const js.Local
|
||||
|
||||
// Some module-loading errors aren't handled by TryCatch. We need to
|
||||
// get the error from the module itself.
|
||||
const message = blk: {
|
||||
const e = mod.getException().toString() catch break :blk "???";
|
||||
break :blk e.toSlice() catch "???";
|
||||
};
|
||||
log.warn(.js, "evaluate module", .{
|
||||
.message = message,
|
||||
.specifier = owned_url,
|
||||
.message = mod.getException().toString(.{}) catch "???",
|
||||
});
|
||||
return error.EvaluationError;
|
||||
};
|
||||
@@ -459,11 +463,11 @@ fn postCompileModule(self: *Context, mod: js.Module, url: [:0]const u8, local: *
|
||||
const request_len = requests.len();
|
||||
const script_manager = self.script_manager.?;
|
||||
for (0..request_len) |i| {
|
||||
const specifier = try local.jsStringToZigZ(requests.get(i).specifier(), .{});
|
||||
const specifier = requests.get(i).specifier(local);
|
||||
const normalized_specifier = try script_manager.resolveSpecifier(
|
||||
self.call_arena,
|
||||
url,
|
||||
specifier,
|
||||
try specifier.toSliceZ(),
|
||||
);
|
||||
const nested_gop = try self.module_cache.getOrPut(self.arena, normalized_specifier);
|
||||
if (!nested_gop.found_existing) {
|
||||
@@ -496,14 +500,14 @@ fn resolveModuleCallback(
|
||||
_ = import_attributes;
|
||||
|
||||
const self = fromC(c_context.?);
|
||||
var local = js.Local{
|
||||
const local = js.Local{
|
||||
.ctx = self,
|
||||
.handle = c_context.?,
|
||||
.isolate = self.isolate,
|
||||
.call_arena = self.call_arena,
|
||||
};
|
||||
|
||||
const specifier = local.jsStringToZigZ(c_specifier.?, .{}) catch |err| {
|
||||
const specifier = js.String.toSliceZ(.{ .local = &local, .handle = c_specifier.? }) catch |err| {
|
||||
log.err(.js, "resolve module", .{ .err = err });
|
||||
return null;
|
||||
};
|
||||
@@ -529,19 +533,19 @@ pub fn dynamicModuleCallback(
|
||||
_ = import_attrs;
|
||||
|
||||
const self = fromC(c_context.?);
|
||||
var local = js.Local{
|
||||
const local = js.Local{
|
||||
.ctx = self,
|
||||
.handle = c_context.?,
|
||||
.call_arena = self.call_arena,
|
||||
.isolate = self.isolate,
|
||||
};
|
||||
|
||||
const resource = local.jsStringToZigZ(resource_name.?, .{}) catch |err| {
|
||||
const resource = js.String.toSliceZ(.{ .local = &local, .handle = resource_name.? }) catch |err| {
|
||||
log.err(.app, "OOM", .{ .err = err, .src = "dynamicModuleCallback1" });
|
||||
return @constCast((local.rejectPromise("Out of memory") catch return null).handle);
|
||||
};
|
||||
|
||||
const specifier = local.jsStringToZigZ(v8_specifier.?, .{}) catch |err| {
|
||||
const specifier = js.String.toSliceZ(.{ .local = &local, .handle = v8_specifier.? }) catch |err| {
|
||||
log.err(.app, "OOM", .{ .err = err, .src = "dynamicModuleCallback2" });
|
||||
return @constCast((local.rejectPromise("Out of memory") catch return null).handle);
|
||||
};
|
||||
|
||||
@@ -335,8 +335,7 @@ fn promiseRejectCallback(message_handle: v8.PromiseRejectMessage) callconv(.c) v
|
||||
|
||||
const value =
|
||||
if (v8.v8__PromiseRejectMessage__GetValue(&message_handle)) |v8_value|
|
||||
// @HandleScope - no reason to create a js.Context here
|
||||
local.valueHandleToString(v8_value, .{}) catch |err| @errorName(err)
|
||||
js.Value.toStringSlice(.{ .local = &local, .handle = v8_value }) catch |err| @errorName(err)
|
||||
else
|
||||
"no value";
|
||||
|
||||
|
||||
@@ -473,10 +473,10 @@ pub fn jsValueToZig(self: *const Local, comptime T: type, js_val: js.Value) !T {
|
||||
if (ptr.child == u8) {
|
||||
if (ptr.sentinel()) |s| {
|
||||
if (comptime s == 0) {
|
||||
return self.valueToStringZ(js_val, .{});
|
||||
return try js_val.toStringSliceZ();
|
||||
}
|
||||
} else {
|
||||
return self.valueToString(js_val, .{});
|
||||
return try js_val.toStringSlice();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,10 +549,8 @@ pub fn jsValueToZig(self: *const Local, comptime T: type, js_val: js.Value) !T {
|
||||
},
|
||||
.@"enum" => |e| {
|
||||
if (@hasDecl(T, "js_enum_from_string")) {
|
||||
if (!js_val.isString()) {
|
||||
return error.InvalidArgument;
|
||||
}
|
||||
return std.meta.stringToEnum(T, try self.valueToString(js_val, .{})) orelse return error.InvalidArgument;
|
||||
const js_str = js_val.isString() orelse return error.InvalidArgument;
|
||||
return std.meta.stringToEnum(T, try js_str.toSlice()) orelse return error.InvalidArgument;
|
||||
}
|
||||
switch (@typeInfo(e.tag_type)) {
|
||||
.int => return std.meta.intToEnum(T, try jsIntToZig(e.tag_type, js_val)),
|
||||
@@ -625,17 +623,12 @@ 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 });
|
||||
const js_str = js_val.isString() orelse return null;
|
||||
return try js_str.toSSO(false);
|
||||
},
|
||||
string.Global => {
|
||||
if (!js_val.isString()) {
|
||||
return null;
|
||||
}
|
||||
// Use arena for persistent strings
|
||||
return .{ .str = try self.valueToStringSSO(js_val, .{ .allocator = self.ctx.arena }) };
|
||||
const js_str = js_val.isString() orelse return null;
|
||||
return try js_str.toSSO(true);
|
||||
},
|
||||
else => {
|
||||
if (!js_val.isObject()) {
|
||||
@@ -883,7 +876,7 @@ fn probeJsValueToZig(self: *const Local, comptime T: type, js_val: js.Value) !Pr
|
||||
}
|
||||
|
||||
if (ptr.child == u8) {
|
||||
if (js_val.isString()) {
|
||||
if (v8.v8__Value__IsString(js_val.handle)) {
|
||||
return .{ .ok = {} };
|
||||
}
|
||||
// anything can be coerced into a string
|
||||
@@ -931,10 +924,11 @@ fn probeJsValueToZig(self: *const Local, comptime T: type, js_val: js.Value) !Pr
|
||||
if (js_arr.len() == arr.len) {
|
||||
return .{ .ok = {} };
|
||||
}
|
||||
} else if (js_val.isString() and arr.child == u8) {
|
||||
const str = try js_val.toString(self.local);
|
||||
if (str.lenUtf8(self.isolate) == arr.len) {
|
||||
return .{ .ok = {} };
|
||||
} else if (arr.child == u8) {
|
||||
if (js_val.isString()) |js_str| {
|
||||
if (js_str.lenUtf8(self.isolate) == arr.len) {
|
||||
return .{ .ok = {} };
|
||||
}
|
||||
}
|
||||
}
|
||||
return .{ .invalid = {} };
|
||||
@@ -947,7 +941,7 @@ 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()) {
|
||||
if (v8.v8__Value__IsString(js_val.handle)) {
|
||||
return .{ .ok = {} };
|
||||
}
|
||||
// Anything can be coerced to a string
|
||||
@@ -1080,14 +1074,15 @@ pub fn stackTrace(self: *const Local) !?[]const u8 {
|
||||
const frame_count = v8.v8__StackTrace__GetFrameCount(stack_trace_handle);
|
||||
|
||||
if (v8.v8__StackTrace__CurrentScriptNameOrSourceURL__STATIC(isolate.handle)) |script| {
|
||||
try writer.print("{s}<{s}>", .{ separator, try self.jsStringToZig(script, .{}) });
|
||||
const stack = js.String{ .local = self, .handle = script };
|
||||
try writer.print("{s}<{f}>", .{ separator, stack });
|
||||
}
|
||||
|
||||
for (0..@intCast(frame_count)) |i| {
|
||||
const frame_handle = v8.v8__StackTrace__GetFrame(stack_trace_handle, isolate.handle, @intCast(i)).?;
|
||||
if (v8.v8__StackFrame__GetFunctionName(frame_handle)) |name| {
|
||||
const script = try self.jsStringToZig(name, .{});
|
||||
try writer.print("{s}{s}:{d}", .{ separator, script, v8.v8__StackFrame__GetLineNumber(frame_handle) });
|
||||
const script = js.String{ .local = self, .handle = name };
|
||||
try writer.print("{s}{f}:{d}", .{ separator, script, v8.v8__StackFrame__GetLineNumber(frame_handle) });
|
||||
} else {
|
||||
try writer.print("{s}<anonymous>:{d}", .{ separator, v8.v8__StackFrame__GetLineNumber(frame_handle) });
|
||||
}
|
||||
@@ -1095,100 +1090,6 @@ pub fn stackTrace(self: *const Local) !?[]const u8 {
|
||||
return buf.items;
|
||||
}
|
||||
|
||||
// == Stringifiers ==
|
||||
const ToStringOpts = struct {
|
||||
allocator: ?Allocator = null,
|
||||
};
|
||||
pub fn valueToString(self: *const Local, js_val: js.Value, opts: ToStringOpts) ![]u8 {
|
||||
return self.valueHandleToString(js_val.handle, opts);
|
||||
}
|
||||
pub fn valueToStringZ(self: *const Local, js_val: js.Value, opts: ToStringOpts) ![:0]u8 {
|
||||
return self.valueHandleToStringZ(js_val.handle, opts);
|
||||
}
|
||||
|
||||
pub fn valueHandleToString(self: *const Local, js_val: *const v8.Value, opts: ToStringOpts) ![]u8 {
|
||||
return self._valueToString(false, js_val, opts);
|
||||
}
|
||||
pub fn valueHandleToStringZ(self: *const Local, js_val: *const v8.Value, opts: ToStringOpts) ![:0]u8 {
|
||||
return self._valueToString(true, js_val, opts);
|
||||
}
|
||||
|
||||
fn _valueToString(self: *const Local, comptime null_terminate: bool, value_handle: *const v8.Value, opts: ToStringOpts) !(if (null_terminate) [:0]u8 else []u8) {
|
||||
var resolved_value_handle = value_handle;
|
||||
if (v8.v8__Value__IsSymbol(value_handle)) {
|
||||
const symbol_handle = v8.v8__Symbol__Description(@ptrCast(value_handle), self.isolate.handle).?;
|
||||
resolved_value_handle = @ptrCast(symbol_handle);
|
||||
}
|
||||
|
||||
const string_handle = v8.v8__Value__ToString(resolved_value_handle, self.handle) orelse {
|
||||
return error.JsException;
|
||||
};
|
||||
|
||||
return self._jsStringToZig(null_terminate, string_handle, opts);
|
||||
}
|
||||
|
||||
pub fn jsStringToZig(self: *const Local, str: anytype, opts: ToStringOpts) ![]u8 {
|
||||
return self._jsStringToZig(false, str, opts);
|
||||
}
|
||||
pub fn jsStringToZigZ(self: *const Local, str: anytype, opts: ToStringOpts) ![:0]u8 {
|
||||
return self._jsStringToZig(true, str, opts);
|
||||
}
|
||||
fn _jsStringToZig(self: *const Local, comptime null_terminate: bool, str: anytype, opts: ToStringOpts) !(if (null_terminate) [:0]u8 else []u8) {
|
||||
const handle = if (@TypeOf(str) == js.String) str.handle else str;
|
||||
|
||||
const len = v8.v8__String__Utf8Length(handle, self.isolate.handle);
|
||||
const allocator = opts.allocator orelse self.call_arena;
|
||||
const buf = try (if (comptime null_terminate) allocator.allocSentinel(u8, @intCast(len), 0) else allocator.alloc(u8, @intCast(len)));
|
||||
const n = v8.v8__String__WriteUtf8(handle, self.isolate.handle, buf.ptr, buf.len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
std.debug.assert(n == len);
|
||||
|
||||
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 = undefined;
|
||||
const n = v8.v8__String__WriteUtf8(handle, self.isolate.handle, &content[0], content.len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(n == len);
|
||||
}
|
||||
// Weird that we do this _after_, but we have to..I've seen weird issues
|
||||
// in ReleaseMode where v8 won't write to content if it starts off zero
|
||||
// initiated
|
||||
@memset(content[len..], 0);
|
||||
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);
|
||||
@@ -1233,18 +1134,16 @@ fn _debugValue(self: *const Local, js_val: js.Value, seen: *std.AutoHashMapUnman
|
||||
|
||||
if (js_val.isSymbol()) {
|
||||
const symbol_handle = v8.v8__Symbol__Description(@ptrCast(js_val.handle), self.isolate.handle).?;
|
||||
const js_sym_str = try self.valueToString(.{ .local = self, .handle = symbol_handle }, .{});
|
||||
return writer.print("{s} (symbol)", .{js_sym_str});
|
||||
return writer.print("{f} (symbol)", .{js.String{ .local = self, .handle = @ptrCast(symbol_handle) }});
|
||||
}
|
||||
const js_type = try self.jsStringToZig(js_val.typeOf(), .{});
|
||||
const js_val_str = try self.valueToString(js_val, .{});
|
||||
const js_val_str = try js_val.toStringSlice();
|
||||
if (js_val_str.len > 2000) {
|
||||
try writer.writeAll(js_val_str[0..2000]);
|
||||
try writer.writeAll(" ... (truncated)");
|
||||
} else {
|
||||
try writer.writeAll(js_val_str);
|
||||
}
|
||||
return writer.print(" ({s})", .{js_type});
|
||||
return writer.print(" ({f})", .{js_val.typeOf()});
|
||||
}
|
||||
|
||||
const js_obj = js_val.toObject();
|
||||
@@ -1266,7 +1165,7 @@ fn _debugValue(self: *const Local, js_val: js.Value, seen: *std.AutoHashMapUnman
|
||||
}
|
||||
const own_len = js_obj.getOwnPropertyNames().len();
|
||||
if (own_len == 0) {
|
||||
const js_val_str = try self.valueToString(js_val, .{});
|
||||
const js_val_str = try js_val.toStringSlice();
|
||||
if (js_val_str.len > 2000) {
|
||||
try writer.writeAll(js_val_str[0..2000]);
|
||||
return writer.writeAll(" ... (truncated)");
|
||||
@@ -1281,10 +1180,11 @@ fn _debugValue(self: *const Local, js_val: js.Value, seen: *std.AutoHashMapUnman
|
||||
try writer.writeByte('\n');
|
||||
}
|
||||
const field_name = try names_arr.get(@intCast(i));
|
||||
const name = try self.valueToString(field_name, .{});
|
||||
const name = try field_name.toStringSlice();
|
||||
try writer.splatByteAll(' ', depth);
|
||||
try writer.writeAll(name);
|
||||
try writer.writeAll(": ");
|
||||
|
||||
const field_val = try js_obj.get(name);
|
||||
try self._debugValue(field_val, seen, depth + 1, writer);
|
||||
if (i != len - 1) {
|
||||
|
||||
@@ -131,7 +131,7 @@ const Requests = struct {
|
||||
const Request = struct {
|
||||
handle: *const v8.ModuleRequest,
|
||||
|
||||
pub fn specifier(self: Request) *const v8.String {
|
||||
return v8.v8__ModuleRequest__GetSpecifier(self.handle).?;
|
||||
pub fn specifier(self: Request, local: *const js.Local) js.String {
|
||||
return .{ .local = local, .handle = v8.v8__ModuleRequest__GetSpecifier(self.handle).? };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -197,8 +197,8 @@ pub const NameIterator = struct {
|
||||
}
|
||||
self.idx += 1;
|
||||
|
||||
const js_val_handle = v8.v8__Object__GetIndex(@ptrCast(self.handle), self.local.handle, idx) orelse return error.JsException;
|
||||
const js_val = js.Value{ .local = self.local, .handle = js_val_handle };
|
||||
return try self.local.valueToString(js_val, .{});
|
||||
const local = self.local;
|
||||
const js_val_handle = v8.v8__Object__GetIndex(@ptrCast(self.handle), local.handle, idx) orelse return error.JsException;
|
||||
return try js.Value.toStringSlice(.{ .local = local, .handle = js_val_handle });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
|
||||
const std = @import("std");
|
||||
const js = @import("js.zig");
|
||||
const SSO = @import("../../string.zig").String;
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const IS_DEBUG = @import("builtin").mode == .Debug;
|
||||
|
||||
const v8 = js.v8;
|
||||
|
||||
@@ -28,26 +30,82 @@ const String = @This();
|
||||
local: *const js.Local,
|
||||
handle: *const v8.String,
|
||||
|
||||
pub const ToZigOpts = struct {
|
||||
allocator: ?Allocator = null,
|
||||
};
|
||||
|
||||
pub fn toZig(self: String, opts: ToZigOpts) ![]u8 {
|
||||
return self._toZig(false, opts);
|
||||
pub fn toSlice(self: String) ![]u8 {
|
||||
return self._toSlice(false, self.local.call_arena);
|
||||
}
|
||||
|
||||
pub fn toZigZ(self: String, opts: ToZigOpts) ![:0]u8 {
|
||||
return self._toZig(true, opts);
|
||||
pub fn toSliceZ(self: String) ![:0]u8 {
|
||||
return self._toSlice(true, self.local.call_arena);
|
||||
}
|
||||
pub fn toSliceWithAlloc(self: String, allocator: Allocator) ![]u8 {
|
||||
return self._toSlice(false, allocator);
|
||||
}
|
||||
fn _toSlice(self: String, comptime null_terminate: bool, allocator: Allocator) !(if (null_terminate) [:0]u8 else []u8) {
|
||||
const local = self.local;
|
||||
const handle = self.handle;
|
||||
const isolate = local.isolate.handle;
|
||||
|
||||
fn _toZig(self: String, comptime null_terminate: bool, opts: ToZigOpts) !(if (null_terminate) [:0]u8 else []u8) {
|
||||
const isolate = self.local.isolate.handle;
|
||||
const allocator = opts.allocator orelse self.local.ctx.call_arena;
|
||||
const len: u32 = @intCast(v8.v8__String__Utf8Length(self.handle, isolate));
|
||||
const buf = if (null_terminate) try allocator.allocSentinel(u8, len, 0) else try allocator.alloc(u8, len);
|
||||
const len = v8.v8__String__Utf8Length(handle, isolate);
|
||||
const buf = try (if (comptime null_terminate) allocator.allocSentinel(u8, @intCast(len), 0) else allocator.alloc(u8, @intCast(len)));
|
||||
const n = v8.v8__String__WriteUtf8(handle, isolate, buf.ptr, buf.len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(n == len);
|
||||
}
|
||||
|
||||
const options = v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8;
|
||||
const n = v8.v8__String__WriteUtf8(self.handle, isolate, buf.ptr, buf.len, options);
|
||||
std.debug.assert(n == len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
pub fn toSSO(self: String, comptime global: bool) !(if (global) SSO.Global else SSO) {
|
||||
if (comptime global) {
|
||||
return .{ .str = try self.toSSOWithAlloc(self.local.ctx.arena) };
|
||||
}
|
||||
return self.toSSOWithAlloc(self.local.call_arena);
|
||||
}
|
||||
pub fn toSSOWithAlloc(self: String, allocator: Allocator) !SSO {
|
||||
const handle = self.handle;
|
||||
const isolate = self.local.isolate.handle;
|
||||
|
||||
const len: usize = @intCast(v8.v8__String__Utf8Length(handle, isolate));
|
||||
|
||||
if (len <= 12) {
|
||||
var content: [12]u8 = undefined;
|
||||
const n = v8.v8__String__WriteUtf8(handle, isolate, &content[0], content.len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(n == len);
|
||||
}
|
||||
// Weird that we do this _after_, but we have to..I've seen weird issues
|
||||
// in ReleaseMode where v8 won't write to content if it starts off zero
|
||||
// initiated
|
||||
@memset(content[len..], 0);
|
||||
return .{ .len = @intCast(len), .payload = .{ .content = content } };
|
||||
}
|
||||
|
||||
const buf = try allocator.alloc(u8, len);
|
||||
const n = v8.v8__String__WriteUtf8(handle, isolate, 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,
|
||||
} },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn format(self: String, writer: *std.Io.Writer) !void {
|
||||
const local = self.local;
|
||||
const handle = self.handle;
|
||||
const isolate = local.isolate.handle;
|
||||
|
||||
var small: [1024]u8 = undefined;
|
||||
const len = v8.v8__String__Utf8Length(handle, isolate);
|
||||
var buf = if (len < 1024) &small else local.call_arena.alloc(u8, @intCast(len)) catch return error.WriteFailed;
|
||||
|
||||
const n = v8.v8__String__WriteUtf8(handle, isolate, buf.ptr, buf.len, v8.NO_NULL_TERMINATION | v8.REPLACE_INVALID_UTF8);
|
||||
return writer.writeAll(buf[0..n]);
|
||||
}
|
||||
|
||||
@@ -46,12 +46,12 @@ pub fn caught(self: TryCatch, allocator: Allocator) ?Caught {
|
||||
|
||||
const exception: ?[]const u8 = blk: {
|
||||
const handle = v8.v8__TryCatch__Exception(&self.handle) orelse break :blk null;
|
||||
break :blk l.valueHandleToString(@ptrCast(handle), .{ .allocator = allocator }) catch |err| @errorName(err);
|
||||
break :blk js.String.toSliceWithAlloc(.{ .local = l, .handle = @ptrCast(handle) }, allocator) catch |err| @errorName(err);
|
||||
};
|
||||
|
||||
const stack: ?[]const u8 = blk: {
|
||||
const handle = v8.v8__TryCatch__StackTrace(&self.handle, l.handle) orelse break :blk null;
|
||||
break :blk l.valueHandleToString(@ptrCast(handle), .{ .allocator = allocator }) catch |err| @errorName(err);
|
||||
break :blk js.String.toSliceWithAlloc(.{ .local = l, .handle = @ptrCast(handle) }, allocator) catch |err| @errorName(err);
|
||||
};
|
||||
|
||||
return .{
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
const std = @import("std");
|
||||
const js = @import("js.zig");
|
||||
const SSO = @import("../../string.zig").String;
|
||||
|
||||
const v8 = js.v8;
|
||||
|
||||
@@ -34,8 +35,12 @@ pub fn isObject(self: Value) bool {
|
||||
return v8.v8__Value__IsObject(self.handle);
|
||||
}
|
||||
|
||||
pub fn isString(self: Value) bool {
|
||||
return v8.v8__Value__IsString(self.handle);
|
||||
pub fn isString(self: Value) ?js.String {
|
||||
const handle = self.handle;
|
||||
if (!v8.v8__Value__IsString(handle)) {
|
||||
return null;
|
||||
}
|
||||
return .{ .local = self.local, .handle = @ptrCast(handle) };
|
||||
}
|
||||
|
||||
pub fn isArray(self: Value) bool {
|
||||
@@ -204,35 +209,40 @@ pub fn toPromise(self: Value) js.Promise {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn toString(self: Value, opts: js.String.ToZigOpts) ![]u8 {
|
||||
return self._toString(false, opts);
|
||||
pub fn toString(self: Value) !js.String {
|
||||
const l = self.local;
|
||||
const value_handle: *const v8.Value = blk: {
|
||||
if (self.isSymbol()) {
|
||||
break :blk @ptrCast(v8.v8__Symbol__Description(@ptrCast(self.handle), l.isolate.handle).?);
|
||||
}
|
||||
break :blk self.handle;
|
||||
};
|
||||
|
||||
const str_handle = v8.v8__Value__ToString(value_handle, l.handle) orelse return error.JsException;
|
||||
return .{ .local = self.local, .handle = str_handle };
|
||||
}
|
||||
pub fn toStringZ(self: Value, opts: js.String.ToZigOpts) ![:0]u8 {
|
||||
return self._toString(true, opts);
|
||||
|
||||
pub fn toSSO(self: Value, comptime global: bool) !(if (global) SSO.Global else SSO) {
|
||||
return (try self.toString()).toSSO(global);
|
||||
}
|
||||
pub fn toSSOWithAlloc(self: Value, allocator: Allocator) !SSO {
|
||||
return (try self.toString()).toSSOWithAlloc(allocator);
|
||||
}
|
||||
|
||||
pub fn toStringSlice(self: Value) ![]u8 {
|
||||
return (try self.toString()).toSlice();
|
||||
}
|
||||
pub fn toStringSliceZ(self: Value) ![:0]u8 {
|
||||
return (try self.toString()).toSliceZ();
|
||||
}
|
||||
pub fn toStringSliceWithAlloc(self: Value, allocator: Allocator) ![]u8 {
|
||||
return (try self.toString()).toSliceWithAlloc(allocator);
|
||||
}
|
||||
|
||||
pub fn toJson(self: Value, allocator: Allocator) ![]u8 {
|
||||
const json_str_handle = v8.v8__JSON__Stringify(self.local.handle, self.handle, null) orelse return error.JsException;
|
||||
return self.local.jsStringToZig(json_str_handle, .{ .allocator = allocator });
|
||||
}
|
||||
|
||||
fn _toString(self: Value, comptime null_terminate: bool, opts: js.String.ToZigOpts) !(if (null_terminate) [:0]u8 else []u8) {
|
||||
const l = self.local;
|
||||
|
||||
if (self.isSymbol()) {
|
||||
const sym_handle = v8.v8__Symbol__Description(@ptrCast(self.handle), l.isolate.handle).?;
|
||||
return _toString(.{ .handle = @ptrCast(sym_handle), .local = l }, null_terminate, opts);
|
||||
}
|
||||
|
||||
const str_handle = v8.v8__Value__ToString(self.handle, l.handle) orelse {
|
||||
return error.JsException;
|
||||
};
|
||||
|
||||
const str = js.String{ .local = l, .handle = str_handle };
|
||||
if (comptime null_terminate) {
|
||||
return js.String.toZigZ(str, opts);
|
||||
}
|
||||
return js.String.toZig(str, opts);
|
||||
const local = self.local;
|
||||
const str_handle = v8.v8__JSON__Stringify(local.handle, self.handle, null) orelse return error.JsException;
|
||||
return js.String.toSliceWithAlloc(.{ .local = local, .handle = str_handle }, allocator);
|
||||
}
|
||||
|
||||
pub fn persist(self: Value) !Global {
|
||||
@@ -296,8 +306,8 @@ pub fn format(self: Value, writer: *std.Io.Writer) !void {
|
||||
if (comptime IS_DEBUG) {
|
||||
return self.local.debugValue(self, writer);
|
||||
}
|
||||
const str = self.toString(.{}) catch return error.WriteFailed;
|
||||
return writer.writeAll(str);
|
||||
const js_str = self.toString() catch return error.WriteFailed;
|
||||
return js_str.format(writer);
|
||||
}
|
||||
|
||||
pub const Temp = G(0);
|
||||
|
||||
@@ -422,7 +422,7 @@ pub fn unknownPropertyCallback(c_name: ?*const v8.Name, handle: ?*const v8.Prope
|
||||
hs.init(local.isolate);
|
||||
defer hs.deinit();
|
||||
|
||||
const property: []const u8 = local.valueHandleToString(@ptrCast(c_name.?), .{}) catch {
|
||||
const property: []const u8 = js.String.toSlice(.{ .local = local, .handle = @ptrCast(c_name.?) }) catch {
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ pub fn throwIfAborted(self: *const AbortSignal, page: *Page) !ThrowIfAborted {
|
||||
if (self._aborted) {
|
||||
const exception = switch (self._reason) {
|
||||
.string => |str| local.throw(str),
|
||||
.js_val => |js_val| local.throw(try local.toLocal(js_val).toString(.{ .allocator = page.call_arena })),
|
||||
.js_val => |js_val| local.throw(try local.toLocal(js_val).toStringSlice()),
|
||||
.undefined => local.throw("AbortError"),
|
||||
};
|
||||
return .{ .exception = exception };
|
||||
|
||||
@@ -146,7 +146,7 @@ const ValueWriter = struct {
|
||||
var buf: [32]u8 = undefined;
|
||||
for (self.values, 0..) |value, i| {
|
||||
const name = try std.fmt.bufPrint(&buf, "param.{d}", .{i});
|
||||
try writer.write(name, try value.toString(.{}));
|
||||
try writer.write(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,9 +73,8 @@ pub fn define(self: *CustomElementRegistry, name: []const u8, constructor: js.Fu
|
||||
var js_arr = observed_attrs.toArray();
|
||||
for (0..js_arr.len()) |i| {
|
||||
const attr_val = js_arr.get(@intCast(i)) catch continue;
|
||||
const attr_name = attr_val.toString(.{ .allocator = page.arena }) catch continue;
|
||||
const owned_attr = page.dupeString(attr_name) catch continue;
|
||||
definition.observed_attributes.put(page.arena, owned_attr, {}) catch continue;
|
||||
const attr_name = attr_val.toStringSliceWithAlloc(page.arena) catch continue;
|
||||
definition.observed_attributes.put(page.arena, attr_name, {}) catch continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,12 +68,11 @@ pub fn fromJsObject(arena: Allocator, js_obj: js.Object, comptime normalizer: ?N
|
||||
|
||||
while (try it.next()) |name| {
|
||||
const js_value = try js_obj.get(name);
|
||||
const value = try js_value.toString(.{});
|
||||
const normalized = if (comptime normalizer) |n| n(name, page) else name;
|
||||
|
||||
list._entries.appendAssumeCapacity(.{
|
||||
.name = try String.init(arena, normalized, .{}),
|
||||
.value = try String.init(arena, value, .{}),
|
||||
.value = try js_value.toSSOWithAlloc(arena),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -277,7 +277,7 @@ pub fn cancelIdleCallback(self: *Window, id: u32) void {
|
||||
pub fn reportError(self: *Window, err: js.Value, page: *Page) !void {
|
||||
const error_event = try ErrorEvent.initTrusted("error", .{
|
||||
.@"error" = try err.persist(),
|
||||
.message = err.toString(.{}) catch "Unknown error",
|
||||
.message = err.toStringSlice() catch "Unknown error",
|
||||
.bubbles = false,
|
||||
.cancelable = true,
|
||||
}, page);
|
||||
|
||||
@@ -49,8 +49,8 @@ pub fn init(opts_: ?InitOpts, page: *Page) !*URLSearchParams {
|
||||
if (js_val.isObject()) {
|
||||
break :blk try KeyValueList.fromJsObject(arena, js_val.toObject(), null, page);
|
||||
}
|
||||
if (js_val.isString()) {
|
||||
break :blk try paramsFromString(arena, try js_val.toString(.{ .allocator = arena }), &page.buf);
|
||||
if (js_val.isString()) |js_str| {
|
||||
break :blk try paramsFromString(arena, try js_str.toSliceWithAlloc(arena), &page.buf);
|
||||
}
|
||||
return error.InvalidArgument;
|
||||
},
|
||||
|
||||
@@ -140,7 +140,7 @@ fn run(
|
||||
return err;
|
||||
};
|
||||
|
||||
return value.toString(.{ .allocator = arena });
|
||||
return value.toStringSliceWithAlloc(arena);
|
||||
}
|
||||
|
||||
const Writer = struct {
|
||||
|
||||
Reference in New Issue
Block a user