Skip to content
Merged
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This package is clearly inspired by Go's solution to this problem: https://pkg.g

## Usage

As of May 2024, zjb requires Zig 0.12.0 or greater.
As of March 2025, zjb is only known to work with Zig 0.14.0.

The simple folder provides a good template to start from. You'll need to update to reference to zjb in `build.zig.zon`. There's currently no release schedule for point releases, so you should use the latest available code. Eg, copy the entire `simple` folder into your empty project, then run `zig fetch --save=zjb https://github.com/scottredig/zig-javascript-bridge/archive/<put hash of latest commit to main here>.zip`

Expand Down
2 changes: 1 addition & 1 deletion build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub fn build(b: *std.Build) void {
const generate_js = b.addExecutable(.{
.name = "generate_js",
.root_source_file = b.path("src/generate_js.zig"),
.target = b.host,
.target = b.graph.host,
// Reusing this will occur more often than compiling this, as
// it usually can be cached. So faster execution is worth slower
// initial build.
Expand Down
3 changes: 2 additions & 1 deletion build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.{
.name = "javascript-bridge",
.name = .javascript_bridge,
.version = "0.0.0",
.fingerprint = 0x2cab041a0159e113,
.paths = .{
"build.zig",
"build.zig.zon",
Expand Down
2 changes: 1 addition & 1 deletion example/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});
const dir = std.Build.InstallDir.bin;

const zjb = b.dependency("zjb", .{});
const zjb = b.dependency("javascript_bridge", .{});

const example = b.addExecutable(.{
.name = "example",
Expand Down
5 changes: 3 additions & 2 deletions example/build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.{
.name = "example",
.name = .example,
.version = "0.0.0",
.fingerprint = 0x6eec9b9fe64850bb,
.dependencies = .{
.zjb = .{
.javascript_bridge = .{
.path = "../",
},
},
Expand Down
8 changes: 4 additions & 4 deletions example/src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ export fn main() void {
}

logStr("\n============================= Exporting functions (press a key for a callback) =============================");
zjb.global("document").call("addEventListener", .{ zjb.constString("keydown"), zjb.fnHandle("keydownCallback", keydownCallback) }, void);
zjb.global("document").call("addEventListener", .{ zjb.constString("keydown"), zjb.fnHandle("keydownCallback", &keydownCallback) }, void);

logStr("\n============================= Handle vs ConstHandle =============================");
{
Expand Down Expand Up @@ -180,9 +180,9 @@ fn setTestVar() callconv(.C) f32 {
}

comptime {
zjb.exportFn("incrementAndGet", incrementAndGet);
zjb.exportFn("incrementAndGet", &incrementAndGet);

zjb.exportGlobal("test_var", &test_var);
zjb.exportFn("checkTestVar", checkTestVar);
zjb.exportFn("setTestVar", setTestVar);
zjb.exportFn("checkTestVar", &checkTestVar);
zjb.exportFn("setTestVar", &setTestVar);
}
2 changes: 1 addition & 1 deletion simple/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});
const dir = std.Build.InstallDir.bin;

const zjb = b.dependency("zjb", .{});
const zjb = b.dependency("javascript_bridge", .{});

const simple = b.addExecutable(.{
.name = "simple",
Expand Down
5 changes: 3 additions & 2 deletions simple/build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.{
.name = "simple-example",
.name = .simple_example,
.version = "0.0.0",
.fingerprint = 0x24a585647bbf2e4e,
.dependencies = .{
.zjb = .{
.javascript_bridge = .{
.path = "../",
},
},
Expand Down
18 changes: 15 additions & 3 deletions src/generate_js.zig
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,9 @@ pub fn main() !void {

const name = np.slice;
try writer.writeAll(" {\n");
try writer.writeAll(" const ptr = initialView.getUint32(instance.exports.");
try writer.writeAll(" const ptr = instance.exports.");
try writer.writeAll(global);
try writer.writeAll(".value, true);\n");
try writer.writeAll(".value;\n");

try writer.writeAll(" Object.defineProperty(this.exports, \"");
try writer.writeAll(name);
Expand Down Expand Up @@ -603,7 +603,19 @@ const NameParser = struct {
}

fn mustArgType(self: *NameParser) !ArgType {
if (self.maybe("n")) {
// if (self.maybe("n")) {
// return .number;
// }
if (self.maybe("i32")) {
return .number;
}
if (self.maybe("i64")) {
return .number;
}
if (self.maybe("f32")) {
return .number;
}
if (self.maybe("f64")) {
return .number;
}
if (self.maybe("b")) {
Expand Down
31 changes: 19 additions & 12 deletions src/zjb.zig
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub fn exportGlobal(comptime name: []const u8, comptime value: anytype) void {

pub fn exportFn(comptime name: []const u8, comptime f: anytype) void {
comptime var export_name: []const u8 = "zjb_fn_";
const type_info = @typeInfo(@TypeOf(f)).Fn;
const type_info = @typeInfo(@typeInfo(@TypeOf(f)).pointer.child).@"fn";
validateToJavascriptReturnType(type_info.return_type orelse void);
inline for (type_info.params) |param| {
validateFromJavascriptArgumentType(param.type orelse void);
Expand Down Expand Up @@ -104,10 +104,10 @@ pub fn u8ClampedArrayView(data: []const u8) Handle {

pub fn dataView(data: anytype) Handle {
switch (@typeInfo(@TypeOf(data))) {
.Pointer => |ptr| {
if (ptr.size == .One) {
.pointer => |ptr| {
if (ptr.size == .one) {
return zjb.dataview(data, @sizeOf(ptr.child));
} else if (ptr.size == .Slice) {
} else if (ptr.size == .slice) {
return zjb.dataview(data.ptr, data.len * @sizeOf(ptr.child));
} else {
@compileError("dataview pointers must be single objects or slices, got: " ++ @typeName(@TypeOf(data)));
Expand Down Expand Up @@ -227,7 +227,7 @@ pub const Handle = enum(i32) {

fn invoke(handle: Handle, args: anytype, comptime RetType: type, comptime prefix: []const u8, comptime suffix: []const u8) RetType {
validateFromJavascriptReturnType(RetType);
const fields = comptime @typeInfo(@TypeOf(args)).Struct.fields;
const fields = comptime @typeInfo(@TypeOf(args)).@"struct".fields;
comptime var call_params: [fields.len + 1]std.builtin.Type.Fn.Param = undefined;
comptime var extern_name: []const u8 = prefix;

Expand All @@ -247,7 +247,7 @@ pub const Handle = enum(i32) {
extern_name = extern_name ++ comptime shortTypeName(field.type);
}

const F = @Type(.{ .Fn = .{
const F = @Type(.{ .@"fn" = .{
.calling_convention = .C,
.is_generic = false,
.is_var_args = false,
Expand Down Expand Up @@ -301,17 +301,24 @@ fn shortTypeName(comptime T: type) []const u8 {
Handle, ConstHandle => "o",
void => "v",
bool => "b",
// The number types map to the same name, even though
// the function signatures are different. Zig and Wasm
// handle this just fine, and produces fewer unique methods
// in javascript so there's no reason not to do it.
i32, i64, f32, f64, comptime_int, comptime_float => "n",
// // The number types map to the same name, even though
// // the function signatures are different. Zig and Wasm
// // handle this just fine, and produces fewer unique methods
// // in javascript so there's no reason not to do it.
// i32, i64, f32, f64, comptime_int, comptime_float => "n",

// The above should be true, but 0.14.0 broke it. See https://github.com/scottredig/zig-javascript-bridge/issues/14
i32 => "i32",
i64 => "i64",
f32 => "f32",
f64, comptime_float, comptime_int => "f64",

else => unreachable,
};
}

fn mapType(comptime T: type) type {
if (T == comptime_int or T == comptime_float) {
if (T == comptime_float or T == comptime_int) {
return f64;
}
return T;
Expand Down