Skip to content

Commit

Permalink
add eval function and example
Browse files Browse the repository at this point in the history
  • Loading branch information
Tobias Simetsreiter committed Mar 21, 2023
1 parent a7e24cd commit 326b8b9
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 1 deletion.
3 changes: 2 additions & 1 deletion example/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ fetch(url.href).then(response =>
).then(bytes =>
WebAssembly.instantiate(bytes, importObject)
).then(results => {
const { memory, alert, set_title } = results.instance.exports;
const { memory, alert, set_title, zig_eval } = results.instance.exports;
zjs.memory = memory;

// Call whatever example you want:
set_title();
zig_eval();
//alert();
});
18 changes: 18 additions & 0 deletions example/example.payload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
try {
console.log(this);

const example = {
description: "This message is passed from a zig @embed()'ed js string in wasm.",
msg: "Hello World from zig-js",
};
console.log(example);

const div = document.createElement('pre');
div.style.backgroundColor = "lightgray";
div.innerText = JSON.stringify(example, null, 4);
this.body.appendChild(div);
} catch (error) {
console.error(error);
}
// the last statement needs to be a returnable value
null;
12 changes: 12 additions & 0 deletions example/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ fn set_title_() !void {
try doc.set("title", js.string("Hello!"));
}

export fn zig_eval() void {
__zig_eval() catch unreachable;
}

fn __zig_eval() !void {
const script = js.string(@embedFile("example.payload.js"));

const doc = try js.global.get(js.Object, "document");

_ = try doc.eval(void, script);
}

fn alert_() !void {
try js.global.call(void, "alert", .{js.string("Hello, world!")});
}
16 changes: 16 additions & 0 deletions js/src/zigjs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export class ZigJS {
valueStringCopy: this.valueStringCopy.bind(this),
valueNew: this.valueNew.bind(this),
funcApply: this.funcApply.bind(this),
funcEval: this.funcEval.bind(this),
},
};
}
Expand Down Expand Up @@ -164,6 +165,20 @@ export class ZigJS {
this.storeValue(out, result);
}

/**
* Eval a js string by id with 'this' set to current Object. Return the last statement.
* */
protected funcEval(__out: number, __thisRef: number, __script_addr: number, __script_len: number): void {
const __thisVal = this.loadRef(__thisRef);
const __script = this.loadString(__script_addr, __script_len);
function __f (){
return eval(__script);
}

const __result = __f.call(__thisVal);
this.storeValue(__out, __result);
}

/**
* This can be used to load a value given by an ID. A WASM function
* might return a value as an ID. This can be used to retrieve it.
Expand Down Expand Up @@ -282,5 +297,6 @@ export interface ImportObject {
valueDeinit: (id: number) => void;
valueNew: (out: number, funcId: number, argsPtr: number, argsLen: number) => void;
funcApply: (out: number, funcId: number, thisRef: number, argsPtr: number, argsLen: number) => void;
funcEval: (__out: number, __thisRef: number, __script_addr: number, __script_len: number) => void;
};
};
1 change: 1 addition & 0 deletions src/extern.zig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub usingnamespace if (!builtin.is_test) struct {
argsPtr: [*]const u64,
argsLen: usize,
) void;
pub extern "zig-js" fn funcEval(out: *u64, this: *u64, scriptPtr: u32, scriptLen: u32) void;
} else struct {
const alloc = std.testing.allocator;

Expand Down
14 changes: 14 additions & 0 deletions src/object.zig
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,20 @@ pub const Object = struct {
try self.value.set(n, js_value);
}

/// Evaluate a previously created String as a js script
pub fn eval(
self: Object,
comptime T: type,
script: js.String,
) !Get(T).result {
var result: u64 = undefined;
var ref = @bitCast(u64, @enumToInt(self.value));
@import("extern.zig").funcEval( &result, &ref, @as(u32, @ptrToInt(script.ptr)), @as(u32, script.len));
const rv = @intToEnum(js.Value, result);
return try convertValue(T, undefined, rv);
}


/// Call a function on a object. This will set the "this" parameter
/// to the object properly. This should only be used with return types
/// that don't need any allocations.
Expand Down

0 comments on commit 326b8b9

Please sign in to comment.