mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-07-30 17:25:58 -04:00
limit range collection to container range
This commit is contained in:
@@ -269,17 +269,10 @@ pub fn blob(_: *const Factory, arena: Allocator, child: anytype) !*@TypeOf(child
|
||||
return chain.get(1);
|
||||
}
|
||||
|
||||
pub fn abstractRange(self: *const Factory, arena: Allocator, child: anytype, frame: *Frame) !*@TypeOf(child) {
|
||||
return self.abstractRangeIn(arena, child, frame.document.asNode(), frame);
|
||||
}
|
||||
|
||||
// `container` is the initial start/end container: per spec, createRange()
|
||||
// initializes both boundary points to (document, 0) of the document it was
|
||||
// called on, which is not necessarily the frame's main document.
|
||||
pub fn abstractRangeIn(_: *const Factory, arena: Allocator, child: anytype, container: *Node, frame: *Frame) !*@TypeOf(child) {
|
||||
pub fn abstractRange(_: *const Factory, arena: Allocator, child: anytype, frame: *Frame) !*@TypeOf(child) {
|
||||
const chain = try PrototypeChain(&.{ AbstractRange, @TypeOf(child) }).allocate(arena);
|
||||
|
||||
const doc = container;
|
||||
const doc = frame.document.asNode();
|
||||
const abstract_range = chain.get(0);
|
||||
abstract_range.* = AbstractRange{
|
||||
._rc = .{},
|
||||
|
||||
@@ -162,15 +162,14 @@ pub fn setLocation(self: *Document, url: [:0]const u8) !void {
|
||||
return frame.scheduleNavigation(url, .{ .reason = .script, .kind = .{ .push = null } }, .{ .script = frame });
|
||||
}
|
||||
|
||||
// Approximation of quirks mode: an HTML document without a doctype is in
|
||||
// quirks mode. (Legacy doctypes that also trigger quirks are not detected.)
|
||||
// Approximation of quirks mode: an HTML document without a doctype is in quirks mode.
|
||||
pub fn isQuirksMode(self: *const Document) bool {
|
||||
if (self._type != .html) {
|
||||
return false;
|
||||
}
|
||||
var child = self._proto.firstChild();
|
||||
while (child) |c| : (child = c.nextSibling()) {
|
||||
if (c._type == .document_type) {
|
||||
var it = self._proto.childrenIterator();
|
||||
while (it.next()) |child| {
|
||||
if (child._type == .document_type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1402,8 +1402,7 @@ pub fn getElementsByClassName(self: *Node, class_name: []const u8, frame: *Frame
|
||||
try class_names.append(arena, try frame.dupeString(name));
|
||||
}
|
||||
|
||||
const doc: ?*Document = if (self._type == .document) self._type.document else self.ownerDocument(frame);
|
||||
const quirks = if (doc) |d| d.isQuirksMode() else false;
|
||||
const quirks = if (self.ownerDocumentIncludingSelf(frame)) |doc| doc.isQuirksMode() else false;
|
||||
return collections.NodeLive(.class_name).init(self, .{
|
||||
.names = class_names.items,
|
||||
.case_insensitive = quirks,
|
||||
|
||||
@@ -38,11 +38,15 @@ pub fn init(frame: *Frame) !*Range {
|
||||
}
|
||||
|
||||
// Both boundary points start at (container, 0); document.createRange()
|
||||
// passes the document it was called on.
|
||||
// passes the document it was called on, which is not necessarily the
|
||||
// frame's main document.
|
||||
pub fn initIn(container: *Node, frame: *Frame) !*Range {
|
||||
const arena = try frame.getArena(.medium, "Range");
|
||||
errdefer frame.releaseArena(arena);
|
||||
return frame._factory.abstractRangeIn(arena, Range{ ._proto = undefined }, container, frame);
|
||||
const range = try frame._factory.abstractRange(arena, Range{ ._proto = undefined }, frame);
|
||||
range._proto._start_container = container;
|
||||
range._proto._end_container = container;
|
||||
return range;
|
||||
}
|
||||
|
||||
pub fn asAbstractRange(self: *Range) *AbstractRange {
|
||||
@@ -452,11 +456,14 @@ pub fn deleteContents(self: *Range, frame: *Frame) !void {
|
||||
// range's boundary points. Appends the top-most contained nodes (those whose
|
||||
// parent isn't contained) under `node`, without descending into them.
|
||||
fn collectContained(self: *const Range, node: *Node, list: *std.ArrayList(*Node), arena: std.mem.Allocator) !void {
|
||||
var child = node.firstChild();
|
||||
while (child) |c| : (child = c.nextSibling()) {
|
||||
var it = node.childrenIterator();
|
||||
while (it.next()) |c| {
|
||||
if (self.nodeContained(c)) {
|
||||
try list.append(arena, c);
|
||||
} else {
|
||||
} else if (c.contains(self._proto._start_container) or c.contains(self._proto._end_container)) {
|
||||
// A non-contained child either straddles a boundary point or lies
|
||||
// entirely outside the range; only the former can have contained
|
||||
// descendants, so don't descend into the rest.
|
||||
try self.collectContained(c, list, arena);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,14 +187,17 @@ pub fn classAttributeContains(class_attr: []const u8, class_name: []const u8) bo
|
||||
}
|
||||
|
||||
pub fn classAttributeContainsCase(class_attr: []const u8, class_name: []const u8, case_insensitive: bool) bool {
|
||||
if (class_name.len == 0 or class_name.len > class_attr.len) return false;
|
||||
if (class_name.len == 0 or class_name.len > class_attr.len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var search = class_attr;
|
||||
while (if (case_insensitive)
|
||||
std.ascii.indexOfIgnoreCase(search, class_name)
|
||||
else
|
||||
std.mem.indexOf(u8, search, class_name)) |pos|
|
||||
{
|
||||
while (true) {
|
||||
const pos = (if (case_insensitive)
|
||||
std.ascii.indexOfIgnoreCase(search, class_name)
|
||||
else
|
||||
std.mem.indexOf(u8, search, class_name)) orelse break;
|
||||
|
||||
const is_start = pos == 0 or isClassWhitespace(search[pos - 1]);
|
||||
const end = pos + class_name.len;
|
||||
const is_end = end == search.len or isClassWhitespace(search[end]);
|
||||
|
||||
Reference in New Issue
Block a user