mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-22 04:34:44 +00:00
Merge pull request #1659 from lightpanda-io/nodelist_enumerable
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
e2e-integration-test / zig build release (push) Has been cancelled
e2e-integration-test / demo-integration-scripts (push) Has been cancelled
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
e2e-test / cdp-and-hyperfine-bench (push) Has been cancelled
e2e-test / perf-fmt (push) Has been cancelled
e2e-test / browser fetch (push) Has been cancelled
zig-test / zig test using v8 in debug mode (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
nightly build / build-linux-x86_64 (push) Has been cancelled
nightly build / build-linux-aarch64 (push) Has been cancelled
nightly build / build-macos-aarch64 (push) Has been cancelled
nightly build / build-macos-x86_64 (push) Has been cancelled
wpt / web platform tests json output (push) Has been cancelled
wpt / perf-fmt (push) Has been cancelled
e2e-integration-test / zig build release (push) Has been cancelled
e2e-integration-test / demo-integration-scripts (push) Has been cancelled
Make NodeList enumerable
This commit is contained in:
@@ -251,7 +251,33 @@ fn _deleteNamedIndex(comptime T: type, local: *const Local, func: anytype, name:
|
||||
return handleIndexedReturn(T, F, false, local, ret, info, opts);
|
||||
}
|
||||
|
||||
fn handleIndexedReturn(comptime T: type, comptime F: type, comptime getter: bool, local: *const Local, ret: anytype, info: PropertyCallbackInfo, comptime opts: CallOpts) !u8 {
|
||||
pub fn getEnumerator(self: *Caller, comptime T: type, func: anytype, handle: *const v8.PropertyCallbackInfo, comptime opts: CallOpts) u8 {
|
||||
const local = &self.local;
|
||||
|
||||
var hs: js.HandleScope = undefined;
|
||||
hs.init(local.isolate);
|
||||
defer hs.deinit();
|
||||
|
||||
const info = PropertyCallbackInfo{ .handle = handle };
|
||||
return _getEnumerator(T, local, func, info, opts) catch |err| {
|
||||
handleError(T, @TypeOf(func), local, err, info, opts);
|
||||
// not intercepted
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
fn _getEnumerator(comptime T: type, local: *const Local, func: anytype, info: PropertyCallbackInfo, comptime opts: CallOpts) !u8 {
|
||||
const F = @TypeOf(func);
|
||||
var args: ParameterTypes(F) = undefined;
|
||||
@field(args, "0") = try TaggedOpaque.fromJS(*T, info.getThis());
|
||||
if (@typeInfo(F).@"fn".params.len == 2) {
|
||||
@field(args, "1") = local.ctx.page;
|
||||
}
|
||||
const ret = @call(.auto, func, args);
|
||||
return handleIndexedReturn(T, F, true, local, ret, info, opts);
|
||||
}
|
||||
|
||||
fn handleIndexedReturn(comptime T: type, comptime F: type, comptime with_value: bool, local: *const Local, ret: anytype, info: PropertyCallbackInfo, comptime opts: CallOpts) !u8 {
|
||||
// need to unwrap this error immediately for when opts.null_as_undefined == true
|
||||
// and we need to compare it to null;
|
||||
const non_error_ret = switch (@typeInfo(@TypeOf(ret))) {
|
||||
@@ -274,7 +300,7 @@ fn handleIndexedReturn(comptime T: type, comptime F: type, comptime getter: bool
|
||||
else => ret,
|
||||
};
|
||||
|
||||
if (comptime getter) {
|
||||
if (comptime with_value) {
|
||||
info.getReturnValue().set(try local.zigValueToJs(non_error_ret, opts));
|
||||
}
|
||||
// intercepted
|
||||
|
||||
@@ -329,6 +329,7 @@ pub fn zigValueToJs(self: *const Local, value: anytype, comptime opts: CallOpts)
|
||||
},
|
||||
|
||||
inline
|
||||
js.Array,
|
||||
js.Function,
|
||||
js.Object,
|
||||
js.Promise,
|
||||
|
||||
@@ -308,13 +308,18 @@ fn countExternalReferences() comptime_int {
|
||||
const T = @TypeOf(value);
|
||||
if (T == bridge.Accessor) {
|
||||
count += 1; // getter
|
||||
if (value.setter != null) count += 1; // setter
|
||||
if (value.setter != null) {
|
||||
count += 1;
|
||||
}
|
||||
} else if (T == bridge.Function) {
|
||||
count += 1;
|
||||
} else if (T == bridge.Iterator) {
|
||||
count += 1;
|
||||
} else if (T == bridge.Indexed) {
|
||||
count += 1;
|
||||
if (value.enumerator != null) {
|
||||
count += 1;
|
||||
}
|
||||
} else if (T == bridge.NamedIndexed) {
|
||||
count += 1; // getter
|
||||
if (value.setter != null) count += 1;
|
||||
@@ -376,6 +381,10 @@ fn collectExternalReferences() [countExternalReferences()]isize {
|
||||
} else if (T == bridge.Indexed) {
|
||||
references[idx] = @bitCast(@intFromPtr(value.getter));
|
||||
idx += 1;
|
||||
if (value.enumerator) |enumerator| {
|
||||
references[idx] = @bitCast(@intFromPtr(enumerator));
|
||||
idx += 1;
|
||||
}
|
||||
} else if (T == bridge.NamedIndexed) {
|
||||
references[idx] = @bitCast(@intFromPtr(value.getter));
|
||||
idx += 1;
|
||||
@@ -515,10 +524,10 @@ fn attachClass(comptime JsApi: type, isolate: *v8.Isolate, template: *v8.Functio
|
||||
bridge.Indexed => {
|
||||
var configuration: v8.IndexedPropertyHandlerConfiguration = .{
|
||||
.getter = value.getter,
|
||||
.enumerator = value.enumerator,
|
||||
.setter = null,
|
||||
.query = null,
|
||||
.deleter = null,
|
||||
.enumerator = null,
|
||||
.definer = null,
|
||||
.descriptor = null,
|
||||
.data = null,
|
||||
|
||||
@@ -46,8 +46,8 @@ pub fn Builder(comptime T: type) type {
|
||||
return Function.init(T, func, opts);
|
||||
}
|
||||
|
||||
pub fn indexed(comptime getter_func: anytype, comptime opts: Indexed.Opts) Indexed {
|
||||
return Indexed.init(T, getter_func, opts);
|
||||
pub fn indexed(comptime getter_func: anytype, comptime enumerator_func: anytype, comptime opts: Indexed.Opts) Indexed {
|
||||
return Indexed.init(T, getter_func, enumerator_func, opts);
|
||||
}
|
||||
|
||||
pub fn namedIndexed(comptime getter_func: anytype, setter_func: anytype, deleter_func: anytype, comptime opts: NamedIndexed.Opts) NamedIndexed {
|
||||
@@ -230,26 +230,44 @@ pub const Accessor = struct {
|
||||
|
||||
pub const Indexed = struct {
|
||||
getter: *const fn (idx: u32, handle: ?*const v8.PropertyCallbackInfo) callconv(.c) u8,
|
||||
enumerator: ?*const fn (handle: ?*const v8.PropertyCallbackInfo) callconv(.c) u8,
|
||||
|
||||
const Opts = struct {
|
||||
as_typed_array: bool = false,
|
||||
null_as_undefined: bool = false,
|
||||
};
|
||||
|
||||
fn init(comptime T: type, comptime getter: anytype, comptime opts: Opts) Indexed {
|
||||
return .{ .getter = struct {
|
||||
fn wrap(idx: u32, handle: ?*const v8.PropertyCallbackInfo) callconv(.c) u8 {
|
||||
const v8_isolate = v8.v8__PropertyCallbackInfo__GetIsolate(handle).?;
|
||||
var caller: Caller = undefined;
|
||||
caller.init(v8_isolate);
|
||||
defer caller.deinit();
|
||||
fn init(comptime T: type, comptime getter: anytype, comptime enumerator: anytype, comptime opts: Opts) Indexed {
|
||||
var indexed = Indexed{
|
||||
.enumerator = null,
|
||||
.getter = struct {
|
||||
fn wrap(idx: u32, handle: ?*const v8.PropertyCallbackInfo) callconv(.c) u8 {
|
||||
const v8_isolate = v8.v8__PropertyCallbackInfo__GetIsolate(handle).?;
|
||||
var caller: Caller = undefined;
|
||||
caller.init(v8_isolate);
|
||||
defer caller.deinit();
|
||||
|
||||
return caller.getIndex(T, getter, idx, handle.?, .{
|
||||
.as_typed_array = opts.as_typed_array,
|
||||
.null_as_undefined = opts.null_as_undefined,
|
||||
});
|
||||
}
|
||||
}.wrap };
|
||||
return caller.getIndex(T, getter, idx, handle.?, .{
|
||||
.as_typed_array = opts.as_typed_array,
|
||||
.null_as_undefined = opts.null_as_undefined,
|
||||
});
|
||||
}
|
||||
}.wrap,
|
||||
};
|
||||
|
||||
if (@typeInfo(@TypeOf(enumerator)) != .null) {
|
||||
indexed.enumerator = struct {
|
||||
fn wrap(handle: ?*const v8.PropertyCallbackInfo) callconv(.c) u8 {
|
||||
const v8_isolate = v8.v8__PropertyCallbackInfo__GetIsolate(handle).?;
|
||||
var caller: Caller = undefined;
|
||||
caller.init(v8_isolate);
|
||||
defer caller.deinit();
|
||||
return caller.getEnumerator(T, enumerator, handle.?, .{});
|
||||
}
|
||||
}.wrap;
|
||||
}
|
||||
|
||||
return indexed;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
testing.expectEqual(expected.length, result.length);
|
||||
testing.expectEqual(expected, Array.from(result).map((e) => e.textContent));
|
||||
testing.expectEqual(expected, Array.from(result.values()).map((e) => e.textContent));
|
||||
|
||||
testing.expectEqual(expected.map((e, i) => i), Array.from(result.keys()));
|
||||
testing.expectEqual(expected.map((e, i) => i.toString()), Object.keys(result));
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ pub const JsApi = struct {
|
||||
|
||||
pub const length = bridge.property(0, .{ .template = false });
|
||||
pub const refresh = bridge.function(PluginArray.refresh, .{});
|
||||
pub const @"[int]" = bridge.indexed(PluginArray.getAtIndex, .{ .null_as_undefined = true });
|
||||
pub const @"[int]" = bridge.indexed(PluginArray.getAtIndex, null, .{ .null_as_undefined = true });
|
||||
pub const @"[str]" = bridge.namedIndexed(PluginArray.getByName, null, null, .{ .null_as_undefined = true });
|
||||
pub const item = bridge.function(_item, .{});
|
||||
fn _item(self: *const PluginArray, index: i32) ?*Plugin {
|
||||
|
||||
@@ -776,7 +776,7 @@ pub const JsApi = struct {
|
||||
pub const getSelection = bridge.function(Window.getSelection, .{});
|
||||
|
||||
pub const frames = bridge.accessor(Window.getWindow, null, .{});
|
||||
pub const index = bridge.indexed(Window.getFrame, .{ .null_as_undefined = true });
|
||||
pub const index = bridge.indexed(Window.getFrame, null, .{ .null_as_undefined = true });
|
||||
pub const length = bridge.accessor(Window.getFramesLength, null, .{});
|
||||
pub const scrollX = bridge.accessor(Window.getScrollX, null, .{});
|
||||
pub const scrollY = bridge.accessor(Window.getScrollY, null, .{});
|
||||
|
||||
@@ -321,5 +321,5 @@ pub const JsApi = struct {
|
||||
pub const entries = bridge.function(DOMTokenList.entries, .{});
|
||||
pub const symbol_iterator = bridge.iterator(DOMTokenList.values, .{});
|
||||
pub const forEach = bridge.function(DOMTokenList.forEach, .{});
|
||||
pub const @"[]" = bridge.indexed(DOMTokenList.item, .{ .null_as_undefined = true });
|
||||
pub const @"[]" = bridge.indexed(DOMTokenList.item, null, .{ .null_as_undefined = true });
|
||||
};
|
||||
|
||||
@@ -170,7 +170,7 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(HTMLAllCollection.length, null, .{});
|
||||
pub const @"[int]" = bridge.indexed(HTMLAllCollection.getAtIndex, .{ .null_as_undefined = true });
|
||||
pub const @"[int]" = bridge.indexed(HTMLAllCollection.getAtIndex, null, .{ .null_as_undefined = true });
|
||||
pub const @"[str]" = bridge.namedIndexed(HTMLAllCollection.getByName, null, null, .{ .null_as_undefined = true });
|
||||
|
||||
pub const item = bridge.function(_item, .{});
|
||||
|
||||
@@ -136,7 +136,7 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(HTMLCollection.length, null, .{});
|
||||
pub const @"[int]" = bridge.indexed(HTMLCollection.getAtIndex, .{ .null_as_undefined = true });
|
||||
pub const @"[int]" = bridge.indexed(HTMLCollection.getAtIndex, null, .{ .null_as_undefined = true });
|
||||
pub const @"[str]" = bridge.namedIndexed(HTMLCollection.getByName, null, null, .{ .null_as_undefined = true });
|
||||
|
||||
pub const item = bridge.function(_item, .{});
|
||||
|
||||
@@ -138,7 +138,7 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(HTMLFormControlsCollection.length, null, .{});
|
||||
pub const @"[int]" = bridge.indexed(HTMLFormControlsCollection.getAtIndex, .{ .null_as_undefined = true });
|
||||
pub const @"[int]" = bridge.indexed(HTMLFormControlsCollection.getAtIndex, null, .{ .null_as_undefined = true });
|
||||
pub const @"[str]" = bridge.namedIndexed(HTMLFormControlsCollection.namedItem, null, null, .{ .null_as_undefined = true });
|
||||
pub const namedItem = bridge.function(HTMLFormControlsCollection.namedItem, .{});
|
||||
};
|
||||
|
||||
@@ -102,7 +102,7 @@ pub const JsApi = struct {
|
||||
pub const length = bridge.accessor(HTMLOptionsCollection.length, null, .{});
|
||||
|
||||
// Indexed access
|
||||
pub const @"[int]" = bridge.indexed(HTMLOptionsCollection.getAtIndex, .{ .null_as_undefined = true });
|
||||
pub const @"[int]" = bridge.indexed(HTMLOptionsCollection.getAtIndex, null, .{ .null_as_undefined = true });
|
||||
pub const @"[str]" = bridge.namedIndexed(HTMLOptionsCollection.getByName, null, null, .{ .null_as_undefined = true });
|
||||
|
||||
pub const selectedIndex = bridge.accessor(HTMLOptionsCollection.getSelectedIndex, HTMLOptionsCollection.setSelectedIndex, .{});
|
||||
|
||||
@@ -125,11 +125,20 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(NodeList.length, null, .{});
|
||||
pub const @"[]" = bridge.indexed(NodeList.indexedGet, .{ .null_as_undefined = true });
|
||||
pub const @"[]" = bridge.indexed(NodeList.indexedGet, getIndexes, .{ .null_as_undefined = true });
|
||||
pub const item = bridge.function(NodeList.getAtIndex, .{});
|
||||
pub const keys = bridge.function(NodeList.keys, .{});
|
||||
pub const values = bridge.function(NodeList.values, .{});
|
||||
pub const entries = bridge.function(NodeList.entries, .{});
|
||||
pub const forEach = bridge.function(NodeList.forEach, .{});
|
||||
pub const symbol_iterator = bridge.iterator(NodeList.values, .{});
|
||||
|
||||
fn getIndexes(self: *NodeList, page: *Page) !js.Array {
|
||||
const len = try self.length(page);
|
||||
var arr = page.js.local.?.newArray(len);
|
||||
for (0..len) |i| {
|
||||
_ = try arr.set(@intCast(i), i, .{});
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,7 +122,7 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(RadioNodeList.getLength, null, .{});
|
||||
pub const @"[]" = bridge.indexed(RadioNodeList.getAtIndex, .{ .null_as_undefined = true });
|
||||
pub const @"[]" = bridge.indexed(RadioNodeList.getAtIndex, null, .{ .null_as_undefined = true });
|
||||
pub const item = bridge.function(RadioNodeList.getAtIndex, .{});
|
||||
pub const value = bridge.accessor(RadioNodeList.getValue, RadioNodeList.setValue, .{});
|
||||
};
|
||||
|
||||
@@ -32,5 +32,5 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(CSSRuleList.length, null, .{});
|
||||
pub const @"[]" = bridge.indexed(CSSRuleList.item, .{ .null_as_undefined = true });
|
||||
pub const @"[]" = bridge.indexed(CSSRuleList.item, null, .{ .null_as_undefined = true });
|
||||
};
|
||||
|
||||
@@ -30,5 +30,5 @@ pub const JsApi = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(StyleSheetList.length, null, .{});
|
||||
pub const @"[]" = bridge.indexed(StyleSheetList.item, .{ .null_as_undefined = true });
|
||||
pub const @"[]" = bridge.indexed(StyleSheetList.item, null, .{ .null_as_undefined = true });
|
||||
};
|
||||
|
||||
@@ -524,7 +524,7 @@ pub const NamedNodeMap = struct {
|
||||
};
|
||||
|
||||
pub const length = bridge.accessor(NamedNodeMap.length, null, .{});
|
||||
pub const @"[int]" = bridge.indexed(NamedNodeMap.getAtIndex, .{ .null_as_undefined = true });
|
||||
pub const @"[int]" = bridge.indexed(NamedNodeMap.getAtIndex, null, .{ .null_as_undefined = true });
|
||||
pub const @"[str]" = bridge.namedIndexed(NamedNodeMap.getByName, null, null, .{ .null_as_undefined = true });
|
||||
pub const getNamedItem = bridge.function(NamedNodeMap.getByName, .{});
|
||||
pub const setNamedItem = bridge.function(NamedNodeMap.set, .{});
|
||||
|
||||
Reference in New Issue
Block a user