Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions examples/js_dsl/mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,35 @@ describe("mixed DSL + N-API", () => {
expect(obj).toEqual({ x: 10 });
});

it("reports the active Node version", () => {
expect(mod.nodeVersion()).toEqual(process.versions.node);
expect(mod.nodeRelease()).toEqual(process.release.name);
});

it("returns a TypedArray's backing ArrayBuffer and range", () => {
const backing = new ArrayBuffer(16);
const view = new Uint16Array(backing, 4, 3);

expect(mod.typedArrayInfoMatches(view, backing, 3, 4)).toBe(true);
});

it("rejects unsupported TypedArray element types", () => {
const Float16ArrayCtor = Reflect.get(globalThis, "Float16Array");
if (typeof Float16ArrayCtor !== "function") return;
const view = Reflect.construct(Float16ArrayCtor, [3]) as Uint16Array;

expect(() =>
mod.typedArrayInfoMatches(view, view.buffer, 3, 0),
).toThrow("UnsupportedTypedarrayType");
});

it("returns a DataView's backing ArrayBuffer and range", () => {
const backing = new ArrayBuffer(16);
const view = new DataView(backing, 4, 6);

expect(mod.dataViewInfoMatches(view, backing, 6, 4)).toBe(true);
});

it("randomBytes16 uses js.io() to produce a Uint8Array", () => {
const bytes = mod.randomBytes16();
expect(bytes).toBeInstanceOf(Uint8Array);
Expand Down
46 changes: 46 additions & 0 deletions examples/js_dsl/mod.zig
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,52 @@ pub fn makeObject(key: String, value: Number) !Value {
return .{ .val = obj };
}

pub fn nodeVersion() !String {
const semantic_version = (try js.env().getNodeVersion()).toSemanticVersion();
var buffer: [64]u8 = undefined;
const version = std.fmt.bufPrint(
&buffer,
"{d}.{d}.{d}",
.{ semantic_version.major, semantic_version.minor, semantic_version.patch },
) catch return error.FormatError;
return String.from(version);
}

pub fn nodeRelease() !String {
const release = (try js.env().getNodeVersion()).getRelease();
return String.from(std.mem.span(release));
}

pub fn typedArrayInfoMatches(
value: Value,
expected_arraybuffer: Value,
expected_length: Number,
expected_byte_offset: Number,
) !Boolean {
const info = try value.toValue().getTypedarrayInfo();
const length: usize = @intCast(expected_length.assertU32());
const byte_offset: usize = @intCast(expected_byte_offset.assertU32());
if (info.length != length) return Boolean.from(false);
if (info.byte_offset != byte_offset) return Boolean.from(false);
if (info.data.len != length * info.array_type.elementSize()) return Boolean.from(false);
return Boolean.from(try info.arraybuffer.strictEquals(expected_arraybuffer.toValue()));
}

pub fn dataViewInfoMatches(
value: Value,
expected_arraybuffer: Value,
expected_byte_length: Number,
expected_byte_offset: Number,
) !Boolean {
const info = try value.toValue().getDataviewInfo();
const byte_length: usize = @intCast(expected_byte_length.assertU32());
const byte_offset: usize = @intCast(expected_byte_offset.assertU32());
if (info.byte_length != byte_length) return Boolean.from(false);
if (info.byte_offset != byte_offset) return Boolean.from(false);
if (info.data.len != byte_length) return Boolean.from(false);
return Boolean.from(try info.arraybuffer.strictEquals(expected_arraybuffer.toValue()));
}

/// Generate 16 random bytes using the DSL-managed shared std.Io instance.
pub fn randomBytes16() Uint8Array {
var bytes: [16]u8 = undefined;
Expand Down
6 changes: 3 additions & 3 deletions src/Env.zig
Original file line number Diff line number Diff line change
Expand Up @@ -889,11 +889,11 @@ pub fn asyncInit(self: Env, async_resource: Value, async_resource_name: Value) N

/// https://nodejs.org/api/n-api.html#napi_get_node_version
pub fn getNodeVersion(self: Env) NapiError!NodeVersion {
var version: c.napi_node_version = undefined;
var version: [*c]const c.napi_node_version = undefined;
try status.check(
c.napi_get_node_version(self.env, @ptrCast(&version)),
c.napi_get_node_version(self.env, &version),
);
return NodeVersion{ .version = version };
return NodeVersion{ .version = version.* };
}

/// https://nodejs.org/api/n-api.html#napi_get_version
Expand Down
66 changes: 54 additions & 12 deletions src/Value.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const std = @import("std");
const c = @import("c.zig").c;
const status = @import("status.zig");
const NapiError = @import("status.zig").NapiError;
Expand Down Expand Up @@ -142,15 +143,40 @@ pub const TypedarrayInfo = struct {
byte_offset: usize,
};

pub const TypedarrayInfoError = NapiError || error{
UnsupportedTypedarrayType,
};

/// https://nodejs.org/api/n-api.html#napi_get_typedarray_info
pub fn getTypedarrayInfo(self: Value) NapiError!TypedarrayInfo {
var info: TypedarrayInfo = undefined;
pub fn getTypedarrayInfo(self: Value) TypedarrayInfoError!TypedarrayInfo {
var array_type_raw: c.napi_typedarray_type = undefined;
var length: usize = undefined;
var data: [*]u8 = undefined;
try status.check(
c.napi_get_typedarray_info(self.env, self.value, @ptrCast(&info.array_type), &info.length, @ptrCast(&data), @ptrCast(&info.arraybuffer), &info.byte_offset),
);
info.data = data[0 .. info.length * info.array_type.elementSize()];
return info;
var arraybuffer: c.napi_value = undefined;
var byte_offset: usize = undefined;
try status.check(
c.napi_get_typedarray_info(
self.env,
self.value,
&array_type_raw,
&length,
@ptrCast(&data),
&arraybuffer,
&byte_offset,
),
);
const array_type = std.enums.fromInt(TypedarrayType, array_type_raw) orelse
return error.UnsupportedTypedarrayType;
return .{
.array_type = array_type,
.length = length,
.data = data[0 .. length * array_type.elementSize()],
.arraybuffer = .{
.env = self.env,
.value = arraybuffer,
},
.byte_offset = byte_offset,
};
}

pub const DataViewInfo = struct {
Expand All @@ -162,13 +188,29 @@ pub const DataViewInfo = struct {

/// https://nodejs.org/api/n-api.html#napi_get_dataview_info
pub fn getDataviewInfo(self: Value) NapiError!DataViewInfo {
var info: DataViewInfo = undefined;
var byte_length: usize = undefined;
var data: [*]u8 = undefined;
try status.check(
c.napi_get_dataview_info(self.env, self.value, &info.byte_length, @ptrCast(&data), @ptrCast(&info.arraybuffer), &info.byte_offset),
var arraybuffer: c.napi_value = undefined;
var byte_offset: usize = undefined;
try status.check(
c.napi_get_dataview_info(
self.env,
self.value,
&byte_length,
@ptrCast(&data),
&arraybuffer,
&byte_offset,
),
);
info.data = data[0..info.byte_length];
return info;
return .{
.byte_length = byte_length,
.data = data[0..byte_length],
.arraybuffer = .{
.env = self.env,
.value = arraybuffer,
},
.byte_offset = byte_offset,
};
}

/// https://nodejs.org/api/n-api.html#napi_get_date_value
Expand Down
Loading