Skip to content

Commit 1906ed6

Browse files
committed
refactor callback tests
1 parent fd88fd2 commit 1906ed6

5 files changed

Lines changed: 19 additions & 76 deletions

File tree

src/c.zig

Lines changed: 3 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,50 +3,10 @@ pub const c = @cImport({
33
@cInclude("node_api.h");
44
});
55

6-
// pub const cc = wrapCLib(c);
7-
8-
// fn wrapCLib(comptime T: type) type {
9-
// const decls = @typeInfo(T).@"struct".decls;
10-
11-
// const N = decls.len;
12-
13-
// var fields: [N]std.builtin.Type.StructField = undefined;
14-
15-
// inline for (decls, 0..) |d, i| {
16-
// const wrapper = opaque {
17-
// pub fn f() NodeApiError!void {}
18-
// }.f;
19-
// const f : std.builtin.Type.Fn = .{
20-
// .
21-
// };
22-
// fields[i] = .{
23-
// .name = d.name,
24-
// .type = d.ty,
25-
// .default_value = null, // keep it simple; you can wire a default if you want
26-
// .is_comptime = false,
27-
// .alignment = @alignOf(d.ty),
28-
// };
29-
// }
30-
31-
// return @Type(.{
32-
// .Struct = .{
33-
// .layout = .Auto,
34-
// .fields = &fields,
35-
// .decls = &.{}, // no nested declarations (constants/functions) added here
36-
// .is_tuple = false,
37-
// },
38-
// });
39-
// }
40-
416
/// Maps a node_api status codes to Zig errors.
427
pub fn statusToError(status: c_uint) NodeApiError!void {
43-
const v: NapiStatusValue = @enumFromInt(status);
44-
45-
if (v == NapiStatusValue.ok) {
46-
return;
47-
}
48-
49-
return switch (v) {
8+
return switch (@as(NapiStatusValue, @enumFromInt(status))) {
9+
NapiStatusValue.ok => return,
5010
NapiStatusValue.invalid_arg => NodeApiError.InvalidArg,
5111
NapiStatusValue.object_expected => NodeApiError.ObjectExpected,
5212
NapiStatusValue.string_expected => NodeApiError.StringExpected,
@@ -132,15 +92,12 @@ pub const NodeApiError = error{
13292

13393
// https://nodejs.org/api/n-api.html#error-handling
13494
pub fn handleError(env: c.napi_env, err: anyerror) void {
135-
std.log.debug("handling error for {any}", .{err});
95+
std.log.debug("handling error '{any}'", .{err});
13696

13797
var err_info: [*c]const c.napi_extended_error_info = undefined;
13898
if (c.napi_get_last_error_info(env, &err_info) != c.napi_ok) {
13999
@panic("failed to call `napi_get_last_error_info`.");
140100
}
141-
// if (err_info != null) {
142-
// std.log.debug("err_infooo {s}", .{err_info.*.error_message});
143-
// }
144101

145102
// In many cases when a Node-API function is called and an exception is already pending, the function will return immediately with a napi_status of napi_pending_exception.
146103
// However, this is not the case for all functions. Node-API allows a subset of the functions to be called to allow for some minimal cleanup before returning to JavaScript.
@@ -154,8 +111,6 @@ pub fn handleError(env: c.napi_env, err: anyerror) void {
154111
pending_exception = true;
155112
}
156113

157-
std.log.debug("pending_expeption {any}", .{pending_exception});
158-
159114
if (pending_exception) {
160115
// the pending exception will be thrown in JS
161116
return;

tests/callbacks.spec.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
import addon from "node-api-test-module";
22
import { describe, it, expect } from "bun:test";
33

4-
describe("defineFunction with callback", () => {
5-
it("should call callback", () => {
4+
describe("callback parameters", () => {
5+
const capturedValue = 3;
6+
7+
it("support closures as expected", () => {
68
expect(
7-
addon.functions.fnCallback((foo) => {
8-
console.log("CALLED FROM ZIG", foo);
9-
return foo * 3;
9+
addon.functions.fnCallback(123, (foo: number) => {
10+
return foo * capturedValue;
1011
})
11-
).toEqual("ok");
12+
).toEqual(369);
1213
});
1314

14-
it("should propagate errors thrown in callback", () => {
15+
it("should propagate thrown errors", () => {
1516
expect(() => {
16-
addon.functions.fnCallback(() => {
17+
addon.functions.fnCallback(123, () => {
1718
throw new Error("Kablooie");
1819
});
1920
}).toThrowError("Kablooie");
2021
});
21-
});
2222

23-
describe("defineAsyncFunction with callback", () => {
24-
it("should call callback", async () => {
23+
it.skip("TODO: should be callable from async functions", async () => {
2524
expect(
2625
await addon.functions.fnCallbackAsync((foo) => {
2726
console.log("CALLED FROM ZIG", foo);

tests/functions.spec.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import addon from "node-api-test-module";
22
import { describe, it, expect } from "bun:test";
33

4-
describe("defineFunction", () => {
5-
it("should define function", () => {
4+
describe("functions", () => {
5+
it("should be defined as function", () => {
66
expect(addon.functions.fnWithSerializedParams).toBeFunction();
77
});
88

9-
it("should fail when called with missing arguments", () => {
9+
it("should throw MissingArguments when called with missing arguments", () => {
1010
expect(() => addon.functions.fnWithSerializedParams(123)).toThrow(
1111
"MissingArguments"
1212
);
1313
});
1414

15-
it("should fail when called with argument of different type", () => {
15+
it("should throw when called with argument of different type", () => {
1616
expect(() => addon.functions.fnWithSerializedParams(123, "foo")).toThrow(
1717
"BooleanExpected"
1818
);
@@ -22,6 +22,7 @@ describe("defineFunction", () => {
2222
it("should unwrap the instance", () => {
2323
const i = new addon.TestClass(123);
2424
expect(addon.functions.fnWithJsNewedNativeInstance(i)).toBe(i);
25+
expect(i.foo).toEqual(124);
2526
});
2627
});
2728

@@ -33,19 +34,6 @@ describe("defineFunction", () => {
3334
});
3435
});
3536

36-
describe("with callback parameter", () => {
37-
const capturedValue = 3;
38-
it("should call callback", () => {
39-
expect(
40-
addon.functions.fnCallback(123, (foo) => {
41-
console.log(this);
42-
console.log("CALLED FROM ZIG", foo);
43-
return foo * capturedValue;
44-
})
45-
).toEqual(369);
46-
});
47-
});
48-
4937
describe("calling with too few arguments", () => {
5038
it("should serialize params and return values", () => {
5139
expect(addon.functions.fnWithAllocatorParam(42)).toEqual(
-432 Bytes
Binary file not shown.

tests/zig/test-module.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ fn fnWithAllocatorParam(allocator: std.mem.Allocator, len: u32) ![]u8 {
9090
}
9191

9292
fn fnWithJsNewedNativeInstance(newed_in_js: *TestClass) !*TestClass {
93+
newed_in_js.foo += 1;
9394
std.log.info("newed_in_js {any}", .{newed_in_js});
9495
return newed_in_js;
9596
}

0 commit comments

Comments
 (0)