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) = .{}, timers: std.StringHashMapUnmanaged(u32) = .{},
counts: 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) { if (values.len == 0) {
return; return;
} }
log.fatal(.console, "lightpanda", .{ .args = try serializeValues(values, page) }); 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) { if (values.len == 0) {
return; return;
} }
log.info(.console, "info", .{ .args = try serializeValues(values, page) }); log.info(.console, "info", .{ .args = try serializeValues(values, page) });
} }
pub fn _info(console: *const Console, values: []JsObject, page: *Page) !void { pub fn static_info(values: []JsObject, page: *Page) !void {
return console._log(values, page); 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) { if (values.len == 0) {
return; return;
} }
log.debug(.console, "debug", .{ .args = try serializeValues(values, page) }); 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) { if (values.len == 0) {
return; return;
} }
log.warn(.console, "warn", .{ .args = try serializeValues(values, page) }); 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) { if (values.len == 0) {
return; return;
} }
log.info(.console, "error", .{ .args = try serializeValues(values, page) }); 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 { pub fn _count(self: *Console, label_: ?[]const u8, page: *Page) !void {
const label = label_ orelse "default"; const label = label_ orelse "default";
@@ -130,7 +130,7 @@ pub const Console = struct {
log.warn(.console, "timer stop", .{ .label = label, .elapsed = elapsed - kv.value }); 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()) { if (assertion.isTruthy()) {
return; 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 2: true", captured[1]);
try testing.expectEqual("[assertion failed] values= 1: x", captured[2]); 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 { const TestCapture = struct {
captured: std.ArrayListUnmanaged([]const u8) = .{}, 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_")) { } else if (comptime std.mem.startsWith(u8, name, "get_")) {
generateProperty(Struct, name[4..], isolate, template_proto); 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); 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 { 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 zig_value = @field(Struct, name);
const js_value = simpleZigValueToJs(isolate, zig_value, true); 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))); return @ptrFromInt(@intFromPtr(toa.ptr) + @as(usize, @intCast(offset)));
} }
if (prototype_index == type_index) { 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; return error.InvalidArgument;
} }
type_index = prototype_index; type_index = prototype_index;
@@ -2341,6 +2362,14 @@ fn Caller(comptime E: type, comptime State: type) type {
info.getReturnValue().set(try scope.zigValueToJs(res)); 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 { fn getter(self: *Self, comptime Struct: type, comptime named_function: NamedFunction, info: v8.FunctionCallbackInfo) !void {
const scope = self.scope; const scope = self.scope;
const func = @field(Struct, named_function.name); const func = @field(Struct, named_function.name);