mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-29 23:23:28 +00:00
Merge pull request #651 from lightpanda-io/html_all_collection
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / puppeteer-perf (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
Some checks failed
e2e-test / zig build release (push) Has been cancelled
e2e-test / puppeteer-perf (push) Has been cancelled
e2e-test / demo-scripts (push) Has been cancelled
zig-test / zig build dev (push) Has been cancelled
zig-test / browser fetch (push) Has been cancelled
zig-test / zig test (push) Has been cancelled
zig-test / perf-fmt (push) Has been cancelled
Rework HTMLAllCollection
This commit is contained in:
2
.github/actions/install/action.yml
vendored
2
.github/actions/install/action.yml
vendored
@@ -17,7 +17,7 @@ inputs:
|
|||||||
zig-v8:
|
zig-v8:
|
||||||
description: 'zig v8 version to install'
|
description: 'zig v8 version to install'
|
||||||
required: false
|
required: false
|
||||||
default: 'v0.1.22'
|
default: 'v0.1.23'
|
||||||
v8:
|
v8:
|
||||||
description: 'v8 version to install'
|
description: 'v8 version to install'
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ ARG ZIG=0.14.0
|
|||||||
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
|
ARG ZIG_MINISIG=RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
|
||||||
ARG ARCH=x86_64
|
ARG ARCH=x86_64
|
||||||
ARG V8=11.1.134
|
ARG V8=11.1.134
|
||||||
ARG ZIG_V8=v0.1.22
|
ARG ZIG_V8=v0.1.23
|
||||||
|
|
||||||
RUN apt-get update -yq && \
|
RUN apt-get update -yq && \
|
||||||
apt-get install -yq xz-utils \
|
apt-get install -yq xz-utils \
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
|
.hash = "tigerbeetle_io-0.0.0-ViLgxpyRBAB5BMfIcj3KMXfbJzwARs9uSl8aRy2OXULd",
|
||||||
},
|
},
|
||||||
.v8 = .{
|
.v8 = .{
|
||||||
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/4809111f930293c6d5082971ad7ffc3d822b6f37.tar.gz",
|
.url = "https://github.com/lightpanda-io/zig-v8-fork/archive/6f1ee74a0e7002ea3568e337ab716c1e75c53769.tar.gz",
|
||||||
.hash = "v8-0.0.0-xddH632xAwAjF7ieh48tjbMpu7fVVGr3r3aLwmBbFvPk",
|
.hash = "v8-0.0.0-xddH6z2yAwCOPUGmy1IgXysI1yWt8ftd2Z3D5zp0I9tV",
|
||||||
},
|
},
|
||||||
//.v8 = .{ .path = "../zig-v8-fork" },
|
//.v8 = .{ .path = "../zig-v8-fork" },
|
||||||
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },
|
//.tigerbeetle_io = .{ .path = "../tigerbeetle-io" },
|
||||||
|
|||||||
@@ -149,17 +149,43 @@ pub fn HTMLCollectionByName(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn HTMLCollectionAll(
|
// HTMLAllCollection is a special type: instances of it are falsy. It's the only
|
||||||
root: ?*parser.Node,
|
// object in the WebAPI that behaves like this - in fact, it's even a special
|
||||||
include_root: bool,
|
// case in the JavaScript spec.
|
||||||
) !HTMLCollection {
|
// This is important, because a lot of browser detection rely on this behavior
|
||||||
return HTMLCollection{
|
// to determine what browser is running.
|
||||||
.root = root,
|
|
||||||
.walker = .{ .walkerDepthFirst = .{} },
|
// It's also possible to use an instance like a function:
|
||||||
.matcher = .{ .matchTrue = .{} },
|
// document.all(3)
|
||||||
.include_root = include_root,
|
// document.all('some_id')
|
||||||
|
pub const HTMLAllCollection = struct {
|
||||||
|
pub const prototype = *HTMLCollection;
|
||||||
|
|
||||||
|
proto: HTMLCollection,
|
||||||
|
|
||||||
|
pub const mark_as_undetectable = true;
|
||||||
|
|
||||||
|
pub fn init(root: ?*parser.Node) HTMLAllCollection {
|
||||||
|
return .{ .proto = .{
|
||||||
|
.root = root,
|
||||||
|
.walker = .{ .walkerDepthFirst = .{} },
|
||||||
|
.matcher = .{ .matchTrue = .{} },
|
||||||
|
.include_root = true,
|
||||||
|
} };
|
||||||
|
}
|
||||||
|
|
||||||
|
const CAllAsFunctionArg = union(enum) {
|
||||||
|
index: u32,
|
||||||
|
id: []const u8,
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
pub fn jsCallAsFunction(self: *HTMLAllCollection, arg: CAllAsFunctionArg) !?Union {
|
||||||
|
return switch (arg) {
|
||||||
|
.index => |i| self.proto._item(i),
|
||||||
|
.id => |id| self.proto._namedItem(id),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub fn HTMLCollectionChildren(
|
pub fn HTMLCollectionChildren(
|
||||||
root: ?*parser.Node,
|
root: ?*parser.Node,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const Document = @import("document.zig").Document;
|
|||||||
const DocumentType = @import("document_type.zig").DocumentType;
|
const DocumentType = @import("document_type.zig").DocumentType;
|
||||||
const DocumentFragment = @import("document_fragment.zig").DocumentFragment;
|
const DocumentFragment = @import("document_fragment.zig").DocumentFragment;
|
||||||
const HTMLCollection = @import("html_collection.zig").HTMLCollection;
|
const HTMLCollection = @import("html_collection.zig").HTMLCollection;
|
||||||
|
const HTMLAllCollection = @import("html_collection.zig").HTMLAllCollection;
|
||||||
const HTMLCollectionIterator = @import("html_collection.zig").HTMLCollectionIterator;
|
const HTMLCollectionIterator = @import("html_collection.zig").HTMLCollectionIterator;
|
||||||
const Walker = @import("walker.zig").WalkerDepthFirst;
|
const Walker = @import("walker.zig").WalkerDepthFirst;
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ pub const Interfaces = .{
|
|||||||
DocumentType,
|
DocumentType,
|
||||||
DocumentFragment,
|
DocumentFragment,
|
||||||
HTMLCollection,
|
HTMLCollection,
|
||||||
|
HTMLAllCollection,
|
||||||
HTMLCollectionIterator,
|
HTMLCollectionIterator,
|
||||||
HTML.Interfaces,
|
HTML.Interfaces,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -151,8 +151,8 @@ pub const HTMLDocument = struct {
|
|||||||
return try collection.HTMLCollectionByAnchors(parser.documentHTMLToNode(self), false);
|
return try collection.HTMLCollectionByAnchors(parser.documentHTMLToNode(self), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_all(self: *parser.DocumentHTML) !collection.HTMLCollection {
|
pub fn get_all(self: *parser.DocumentHTML) collection.HTMLAllCollection {
|
||||||
return try collection.HTMLCollectionAll(parser.documentHTMLToNode(self), true);
|
return collection.HTMLAllCollection.init(parser.documentHTMLToNode(self));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_currentScript(self: *parser.DocumentHTML) !?*parser.Script {
|
pub fn get_currentScript(self: *parser.DocumentHTML) !?*parser.Script {
|
||||||
@@ -260,4 +260,11 @@ test "Browser.HTML.Document" {
|
|||||||
.{ "document.cookie = 'favorite_food=tripe; SameSite=None; Secure'", "favorite_food=tripe; SameSite=None; Secure" },
|
.{ "document.cookie = 'favorite_food=tripe; SameSite=None; Secure'", "favorite_food=tripe; SameSite=None; Secure" },
|
||||||
.{ "document.cookie", "name=Oeschger; favorite_food=tripe" },
|
.{ "document.cookie", "name=Oeschger; favorite_food=tripe" },
|
||||||
}, .{});
|
}, .{});
|
||||||
|
|
||||||
|
try runner.testCases(&.{
|
||||||
|
.{ "!document.all", "true" },
|
||||||
|
.{ "!!document.all", "false" },
|
||||||
|
.{ "document.all(5)", "[object HTMLParagraphElement]" },
|
||||||
|
.{ "document.all('content')", "[object HTMLDivElement]" },
|
||||||
|
}, .{});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1221,6 +1221,7 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
|||||||
|
|
||||||
generateIndexer(Struct, template_proto);
|
generateIndexer(Struct, template_proto);
|
||||||
generateNamedIndexer(Struct, template_proto);
|
generateNamedIndexer(Struct, template_proto);
|
||||||
|
generateUndetectable(Struct, template.getInstanceTemplate());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even if a struct doesn't have a `constructor` function, we still
|
// Even if a struct doesn't have a `constructor` function, we still
|
||||||
@@ -1420,6 +1421,32 @@ pub fn Env(comptime State: type, comptime WebApis: type) type {
|
|||||||
template_proto.setNamedProperty(configuration, null);
|
template_proto.setNamedProperty(configuration, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generateUndetectable(comptime Struct: type, template: v8.ObjectTemplate) void {
|
||||||
|
const has_js_call_as_function = @hasDecl(Struct, "jsCallAsFunction");
|
||||||
|
|
||||||
|
if (has_js_call_as_function) {
|
||||||
|
template.setCallAsFunctionHandler(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, "jsCallAsFunction");
|
||||||
|
caller.method(Struct, named_function, info) catch |err| {
|
||||||
|
caller.handleError(Struct, named_function, err, info);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}.callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@hasDecl(Struct, "mark_as_undetectable") and Struct.mark_as_undetectable) {
|
||||||
|
if (!has_js_call_as_function) {
|
||||||
|
@compileError(@typeName(Struct) ++ ": mark_as_undetectable required jsCallAsFunction to be defined. This is a hard-coded requirement in V8, because mark_as_undetectable only exists for HTMLAllCollection which is also callable.");
|
||||||
|
}
|
||||||
|
template.markAsUndetectable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Turns a Zig value into a JS one.
|
// Turns a Zig value into a JS one.
|
||||||
fn zigValueToJs(
|
fn zigValueToJs(
|
||||||
templates: []v8.FunctionTemplate,
|
templates: []v8.FunctionTemplate,
|
||||||
|
|||||||
Reference in New Issue
Block a user