Merge pull request #749 from lightpanda-io/functions

Poor support for functions/namespaces.
This commit is contained in:
Karl Seguin
2025-06-04 08:33:51 +08:00
committed by GitHub
2 changed files with 49 additions and 9 deletions

View File

@@ -30,46 +30,46 @@ pub const Console = struct {
timers: std.StringHashMapUnmanaged(u32) = .{},
counts: std.StringHashMapUnmanaged(u32) = .{},
pub fn _lp(_: *const Console, values: []JsObject, page: *Page) !void {
pub fn static_lp(values: []JsObject, page: *Page) !void {
if (values.len == 0) {
return;
}
log.fatal(.console, "lightpanda", .{ .args = try serializeValues(values, page) });
}
pub fn _log(_: *const Console, values: []JsObject, page: *Page) !void {
pub fn static_log(values: []JsObject, page: *Page) !void {
if (values.len == 0) {
return;
}
log.info(.console, "info", .{ .args = try serializeValues(values, page) });
}
pub fn _info(console: *const Console, values: []JsObject, page: *Page) !void {
return console._log(values, page);
pub fn static_info(values: []JsObject, page: *Page) !void {
return static_log(values, page);
}
pub fn _debug(_: *const Console, values: []JsObject, page: *Page) !void {
pub fn static_debug(values: []JsObject, page: *Page) !void {
if (values.len == 0) {
return;
}
log.debug(.console, "debug", .{ .args = try serializeValues(values, page) });
}
pub fn _warn(_: *const Console, values: []JsObject, page: *Page) !void {
pub fn static_warn(values: []JsObject, page: *Page) !void {
if (values.len == 0) {
return;
}
log.warn(.console, "warn", .{ .args = try serializeValues(values, page) });
}
pub fn _error(_: *const Console, values: []JsObject, page: *Page) !void {
pub fn static_error(values: []JsObject, page: *Page) !void {
if (values.len == 0) {
return;
}
log.info(.console, "error", .{ .args = try serializeValues(values, page) });
}
pub fn _clear(_: *const Console) void {}
pub fn static_clear() void {}
pub fn _count(self: *Console, label_: ?[]const u8, page: *Page) !void {
const label = label_ orelse "default";
@@ -130,7 +130,7 @@ pub const Console = struct {
log.warn(.console, "timer stop", .{ .label = label, .elapsed = elapsed - kv.value });
}
pub fn _assert(_: *Console, assertion: JsObject, values: []JsObject, page: *Page) !void {
pub fn static_assert(assertion: JsObject, values: []JsObject, page: *Page) !void {
if (assertion.isTruthy()) {
return;
}
@@ -225,7 +225,18 @@ test "Browser.Console" {
try testing.expectEqual("[assertion failed] values= 1: x 2: true", captured[1]);
try testing.expectEqual("[assertion failed] values= 1: x", captured[2]);
}
{
test_capture.reset();
try runner.testCases(&.{
.{ "[1].forEach(console.log)", null },
}, .{});
const captured = test_capture.captured.items;
try testing.expectEqual("[info] args= 1: 1 2: 0 3: [1]", captured[0]);
}
}
const TestCapture = struct {
captured: std.ArrayListUnmanaged([]const u8) = .{},

View File

@@ -1680,6 +1680,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
}
} else if (comptime std.mem.startsWith(u8, name, "get_")) {
generateProperty(Struct, name[4..], isolate, template_proto);
} else if (comptime std.mem.startsWith(u8, name, "static_")) {
generateFunction(Struct, name[7..], isolate, template_proto);
}
}
@@ -1769,6 +1771,23 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
template_proto.set(js_name, function_template, v8.PropertyAttribute.None);
}
fn generateFunction(comptime Struct: type, comptime name: []const u8, isolate: v8.Isolate, template_proto: v8.ObjectTemplate) void {
const js_name = v8.String.initUtf8(isolate, name).toName();
const function_template = v8.FunctionTemplate.initCallback(isolate, struct {
fn callback(raw_info: ?*const v8.C_FunctionCallbackInfo) callconv(.c) void {
const info = v8.FunctionCallbackInfo.initFromV8(raw_info);
var caller = Caller(Self, State).init(info);
defer caller.deinit();
const named_function = comptime NamedFunction.init(Struct, "static_" ++ name);
caller.function(Struct, named_function, info) catch |err| {
caller.handleError(Struct, named_function, err, info);
};
}
}.callback);
template_proto.set(js_name, function_template, v8.PropertyAttribute.None);
}
fn generateAttribute(comptime Struct: type, comptime name: []const u8, isolate: v8.Isolate, template: v8.FunctionTemplate, template_proto: v8.ObjectTemplate) void {
const zig_value = @field(Struct, name);
const js_value = simpleZigValueToJs(isolate, zig_value, true);
@@ -2154,6 +2173,8 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
return @ptrFromInt(@intFromPtr(toa.ptr) + @as(usize, @intCast(offset)));
}
if (prototype_index == type_index) {
// When a type has itself as the prototype, then we've
// reached the end of the chain.
return error.InvalidArgument;
}
type_index = prototype_index;
@@ -2341,6 +2362,14 @@ fn Caller(comptime E: type, comptime State: type) type {
info.getReturnValue().set(try scope.zigValueToJs(res));
}
fn function(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, info: v8.FunctionCallbackInfo) !void {
const scope = self.scope;
const func = @field(Struct, named_function.name);
const args = try self.getArgs(Struct, named_function, 0, info);
const res = @call(.auto, func, args);
info.getReturnValue().set(try scope.zigValueToJs(res));
}
fn getter(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, info: v8.FunctionCallbackInfo) !void {
const scope = self.scope;
const func = @field(Struct, named_function.name);