ArrayBufferRef(...).Global: consistent, persisted typed arrays

This commit is contained in:
Halil Durak
2026-02-18 21:43:19 +03:00
parent 2426abd17a
commit 95920bf207
4 changed files with 39 additions and 44 deletions

View File

@@ -1048,13 +1048,8 @@ pub const FinalizerCallback = struct {
/// Creates a new typed array. Memory is owned by JS context. /// Creates a new typed array. Memory is owned by JS context.
/// If storing the type in a Zig type is desired, prefer `.global` state to persist. /// If storing the type in a Zig type is desired, prefer `.global` state to persist.
/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Typed_arrays /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Typed_arrays
pub fn createTypedArray( pub fn createTypedArray(self: *const Context, comptime array_type: js.ArrayType, size: usize) js.ArrayBufferRef(array_type) {
self: *const Context, return .init(self.local.?, size);
comptime array_type: js.ArrayType,
comptime state: js.ArrayBufferState,
size: usize,
) js.ArrayBufferRef(array_type, state) {
return .init(self.isolate, size);
} }
// == Profiler == // == Profiler ==

View File

@@ -306,13 +306,13 @@ pub fn zigValueToJs(self: *const Local, value: anytype, comptime opts: CallOpts)
js.Value => return value, js.Value => return value,
js.Exception => return .{ .local = self, .handle = isolate.throwException(value.handle) }, js.Exception => return .{ .local = self, .handle = isolate.throwException(value.handle) },
js.ArrayBufferRef(.int8, .global), js.ArrayBufferRef(.uint8, .global), js.ArrayBufferRef(.int8).Global, js.ArrayBufferRef(.uint8).Global,
js.ArrayBufferRef(.uint8_clamped, .global),js.ArrayBufferRef(.int16, .global), js.ArrayBufferRef(.uint8_clamped).Global, js.ArrayBufferRef(.int16).Global,
js.ArrayBufferRef(.uint16, .global), js.ArrayBufferRef(.int32, .global), js.ArrayBufferRef(.uint16).Global, js.ArrayBufferRef(.int32).Global,
js.ArrayBufferRef(.uint32, .global), js.ArrayBufferRef(.float16, .global), js.ArrayBufferRef(.uint32).Global, js.ArrayBufferRef(.float16).Global,
js.ArrayBufferRef(.float32, .global), js.ArrayBufferRef(.float64, .global), js.ArrayBufferRef(.float32).Global, js.ArrayBufferRef(.float64).Global,
=> { => {
return .{ .local = self, .handle = value.localHandle(self) }; return .{ .local = self, .handle = value.local(self).handle };
}, },
inline inline

View File

@@ -90,13 +90,7 @@ pub const ArrayType = enum(u8) {
float64, float64,
}; };
pub const ArrayBufferState = enum(u1) { local, global }; pub fn ArrayBufferRef(comptime kind: ArrayType) type {
/// If `state` is `global`; a persisted, global typed array is created.
pub fn ArrayBufferRef(
comptime kind: ArrayType,
comptime state: ArrayBufferState,
) type {
return struct { return struct {
const Self = @This(); const Self = @This();
@@ -112,12 +106,25 @@ pub fn ArrayBufferRef(
.float64 => f64, .float64 => f64,
}; };
handle: switch (state) { local: *const Local,
.local => *const v8.Value, handle: *const v8.Value,
.global => v8.Global,
},
pub fn init(isolate: Isolate, size: usize) Self { /// Persisted typed array.
pub const Global = struct {
handle: v8.Global,
pub fn deinit(self: *Global) void {
v8.v8__Global__Reset(&self.handle);
}
pub fn local(self: *const Global, l: *const Local) Self {
return .{ .local = l, .handle = v8.v8__Global__Get(&self.handle, l.isolate.handle).? };
}
};
pub fn init(local: *const Local, size: usize) Self {
const ctx = local.ctx;
const isolate = ctx.isolate;
const bits = switch (@typeInfo(BackingInt)) { const bits = switch (@typeInfo(BackingInt)) {
.int => |n| n.bits, .int => |n| n.bits,
.float => |f| f.bits, .float => |f| f.bits,
@@ -134,7 +141,7 @@ pub fn ArrayBufferRef(
array_buffer = v8.v8__ArrayBuffer__New2(isolate.handle, &backing_store_ptr).?; array_buffer = v8.v8__ArrayBuffer__New2(isolate.handle, &backing_store_ptr).?;
} }
const local_handle: *const v8.Value = switch (comptime kind) { const handle: *const v8.Value = switch (comptime kind) {
.int8 => @ptrCast(v8.v8__Int8Array__New(array_buffer, 0, size).?), .int8 => @ptrCast(v8.v8__Int8Array__New(array_buffer, 0, size).?),
.uint8 => @ptrCast(v8.v8__Uint8Array__New(array_buffer, 0, size).?), .uint8 => @ptrCast(v8.v8__Uint8Array__New(array_buffer, 0, size).?),
.uint8_clamped => @ptrCast(v8.v8__Uint8ClampedArray__New(array_buffer, 0, size).?), .uint8_clamped => @ptrCast(v8.v8__Uint8ClampedArray__New(array_buffer, 0, size).?),
@@ -147,23 +154,16 @@ pub fn ArrayBufferRef(
.float64 => @ptrCast(v8.v8__Float64Array__New(array_buffer, 0, size).?), .float64 => @ptrCast(v8.v8__Float64Array__New(array_buffer, 0, size).?),
}; };
switch (comptime state) { return .{ .local = local, .handle = handle };
.local => return .{ .handle = local_handle },
.global => {
// We need a global handle if state is `global`.
var global_handle: v8.Global = undefined;
v8.v8__Global__New(isolate.handle, local_handle, &global_handle);
return .{ .handle = global_handle };
},
}
} }
/// Returns appropriate local handle. pub fn persist(self: *const Self) !Global {
pub fn localHandle(self: *const Self, scope: *const Local) *const v8.Value { var ctx = self.local.ctx;
return switch (comptime state) { var global: v8.Global = undefined;
.local => return self.handle, v8.v8__Global__New(ctx.isolate.handle, self.handle, &global);
.global => v8.v8__Global__Get(&self.handle, scope.isolate.handle).?, try ctx.global_values.append(ctx.arena, global);
};
return .{ .handle = global };
} }
}; };
} }

View File

@@ -29,7 +29,7 @@ const Page = @import("../Page.zig");
const ImageData = @This(); const ImageData = @This();
_width: u32, _width: u32,
_height: u32, _height: u32,
_data: js.ArrayBufferRef(.uint8_clamped, .global), _data: js.ArrayBufferRef(.uint8_clamped).Global,
pub const ConstructorSettings = struct { pub const ConstructorSettings = struct {
/// Specifies the color space of the image data. /// Specifies the color space of the image data.
@@ -74,7 +74,7 @@ pub fn constructor(
return page._factory.create(ImageData{ return page._factory.create(ImageData{
._width = width, ._width = width,
._height = height, ._height = height,
._data = page.js.createTypedArray(.uint8_clamped, .global, size), ._data = try page.js.createTypedArray(.uint8_clamped, size).persist(),
}); });
} }
@@ -94,7 +94,7 @@ pub fn getColorSpace(_: *const ImageData) String {
return comptime .wrap("srgb"); return comptime .wrap("srgb");
} }
pub fn getData(self: *const ImageData) js.ArrayBufferRef(.uint8_clamped, .global) { pub fn getData(self: *const ImageData) js.ArrayBufferRef(.uint8_clamped).Global {
return self._data; return self._data;
} }