mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-09-28 23:47:31 -04:00
webapi: Give iterator to types with an indexed property
Apparently, any type that ah indexed property also gets an iterator, even if the iterator isn't explicitly listed in the spec. This showed up as a bug rendering washingtonpost.com.
This commit is contained in:
5 files changed
+104
-1
No files matched your search
@@ -24,6 +24,42 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="StyleSheetList_iterable">
|
||||
{
|
||||
// WebIDL: indexed getter => @@iterator, but no iterable<> declaration,
|
||||
// so no keys/values/entries. Stitches does [...document.styleSheets].
|
||||
const sheets = document.styleSheets;
|
||||
testing.expectEqual('function', typeof sheets[Symbol.iterator]);
|
||||
testing.expectEqual(undefined, sheets.values);
|
||||
testing.expectEqual(0, [...sheets].length);
|
||||
|
||||
const style = document.createElement('style');
|
||||
document.head.appendChild(style);
|
||||
style.sheet.insertRule('.it-a { color: green; }', 0);
|
||||
style.sheet.insertRule('.it-b { color: blue; }', 1);
|
||||
|
||||
const collected = [...document.styleSheets];
|
||||
testing.expectEqual(1, collected.length);
|
||||
testing.expectTrue(collected[0] === sheets[0]);
|
||||
|
||||
const rules = style.sheet.cssRules;
|
||||
testing.expectEqual('function', typeof rules[Symbol.iterator]);
|
||||
testing.expectEqual(undefined, rules.values);
|
||||
const selectors = [...rules].map(r => r.selectorText);
|
||||
testing.expectEqual('.it-a,.it-b', selectors.join(','));
|
||||
|
||||
// The iterator is live: rules removed mid-iteration are not visited
|
||||
const seen = [];
|
||||
for (const rule of rules) {
|
||||
seen.push(rule.selectorText);
|
||||
style.sheet.deleteRule(1);
|
||||
}
|
||||
testing.expectEqual('.it-a', seen.join(','));
|
||||
|
||||
document.head.removeChild(style);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id="CSSStyleDeclaration_setCssText_basic">
|
||||
{
|
||||
const div = document.createElement('div');
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id=navigator_plugins_iterable>
|
||||
// WebIDL: indexed getter => @@iterator (Chrome: [...navigator.plugins] works)
|
||||
testing.expectEqual('function', typeof navigator.plugins[Symbol.iterator]);
|
||||
testing.expectEqual(0, [...navigator.plugins].length);
|
||||
</script>
|
||||
|
||||
<script id=navigator_native_descriptor_walk>
|
||||
// Mirror the bot-detection fingerprint: read every navigator property's
|
||||
// descriptor and call toString() on its value/getter. This must not throw.
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const js = @import("../js/js.zig");
|
||||
const Frame = @import("../Frame.zig");
|
||||
const GenericIterator = @import("collections/iterator.zig").Entry;
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{ PluginArray, Plugin };
|
||||
return &.{ PluginArray, Plugin, ValueIterator };
|
||||
}
|
||||
|
||||
const PluginArray = @This();
|
||||
@@ -51,6 +53,18 @@ const Plugin = struct {
|
||||
};
|
||||
};
|
||||
|
||||
fn values(_: *const PluginArray, frame: *Frame) !*ValueIterator {
|
||||
return .init(.{}, frame);
|
||||
}
|
||||
|
||||
const ValueIterator = GenericIterator(Iterator, null);
|
||||
|
||||
const Iterator = struct {
|
||||
pub fn next(_: *Iterator, _: *Frame) ?*Plugin {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(PluginArray);
|
||||
|
||||
@@ -73,4 +87,5 @@ pub const JsApi = struct {
|
||||
return self.getAtIndex(@intCast(index));
|
||||
}
|
||||
pub const namedItem = bridge.function(PluginArray.getByName, .{});
|
||||
pub const symbol_iterator = bridge.iterator(PluginArray.values, .{});
|
||||
};
|
||||
@@ -2,9 +2,14 @@ const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
const CSSRule = @import("CSSRule.zig");
|
||||
const GenericIterator = @import("../collections/iterator.zig").Entry;
|
||||
|
||||
const CSSRuleList = @This();
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{ CSSRuleList, ValueIterator };
|
||||
}
|
||||
|
||||
_rules: std.ArrayList(*CSSRule) = .empty,
|
||||
|
||||
pub fn init(frame: *Frame) !*CSSRuleList {
|
||||
@@ -40,6 +45,23 @@ pub fn clear(self: *CSSRuleList) void {
|
||||
self._rules.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
fn values(self: *CSSRuleList, frame: *Frame) !*ValueIterator {
|
||||
return .init(.{ .list = self }, frame);
|
||||
}
|
||||
|
||||
const ValueIterator = GenericIterator(Iterator, null);
|
||||
|
||||
const Iterator = struct {
|
||||
index: u32 = 0,
|
||||
list: *CSSRuleList,
|
||||
|
||||
pub fn next(self: *Iterator, _: *Frame) ?*CSSRule {
|
||||
const rule = self.list.item(self.index) orelse return null;
|
||||
self.index += 1;
|
||||
return rule;
|
||||
}
|
||||
};
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(CSSRuleList);
|
||||
|
||||
@@ -51,4 +73,5 @@ pub const JsApi = struct {
|
||||
|
||||
pub const length = bridge.accessor(CSSRuleList.length, null, .{});
|
||||
pub const @"[]" = bridge.indexed(CSSRuleList.item, null, .{ .null_as_undefined = true });
|
||||
pub const symbol_iterator = bridge.iterator(CSSRuleList.values, .{});
|
||||
};
|
||||
@@ -2,9 +2,14 @@ const std = @import("std");
|
||||
const js = @import("../../js/js.zig");
|
||||
const Frame = @import("../../Frame.zig");
|
||||
const CSSStyleSheet = @import("CSSStyleSheet.zig");
|
||||
const GenericIterator = @import("../collections/iterator.zig").Entry;
|
||||
|
||||
const StyleSheetList = @This();
|
||||
|
||||
pub fn registerTypes() []const type {
|
||||
return &.{ StyleSheetList, ValueIterator };
|
||||
}
|
||||
|
||||
_sheets: std.ArrayList(*CSSStyleSheet) = .empty,
|
||||
|
||||
pub fn init(frame: *Frame) !*StyleSheetList {
|
||||
@@ -33,6 +38,23 @@ pub fn remove(self: *StyleSheetList, sheet: *CSSStyleSheet) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn values(self: *StyleSheetList, frame: *Frame) !*ValueIterator {
|
||||
return .init(.{ .list = self }, frame);
|
||||
}
|
||||
|
||||
const ValueIterator = GenericIterator(Iterator, null);
|
||||
|
||||
const Iterator = struct {
|
||||
index: u32 = 0,
|
||||
list: *StyleSheetList,
|
||||
|
||||
pub fn next(self: *Iterator, _: *Frame) ?*CSSStyleSheet {
|
||||
const sheet = self.list.item(self.index) orelse return null;
|
||||
self.index += 1;
|
||||
return sheet;
|
||||
}
|
||||
};
|
||||
|
||||
pub const JsApi = struct {
|
||||
pub const bridge = js.Bridge(StyleSheetList);
|
||||
|
||||
@@ -44,4 +66,5 @@ pub const JsApi = struct {
|
||||
|
||||
pub const length = bridge.accessor(StyleSheetList.length, null, .{});
|
||||
pub const @"[]" = bridge.indexed(StyleSheetList.item, null, .{ .null_as_undefined = true });
|
||||
pub const symbol_iterator = bridge.iterator(StyleSheetList.values, .{});
|
||||
};
|
||||
Reference in new issue
Block a user