mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-17 00:38:59 +00:00
improve domexception
This commit is contained in:
@@ -91,8 +91,7 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool, global_cal
|
|||||||
const global_template = js_global.getInstanceTemplate();
|
const global_template = js_global.getInstanceTemplate();
|
||||||
global_template.setInternalFieldCount(1);
|
global_template.setInternalFieldCount(1);
|
||||||
|
|
||||||
// Configure the missing property callback on the global
|
// Configure the missing property callback on the global object.
|
||||||
// object.
|
|
||||||
if (global_callback != null) {
|
if (global_callback != null) {
|
||||||
const configuration = v8.NamedPropertyHandlerConfiguration{
|
const configuration = v8.NamedPropertyHandlerConfiguration{
|
||||||
.getter = struct {
|
.getter = struct {
|
||||||
@@ -162,15 +161,17 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool, global_cal
|
|||||||
}
|
}
|
||||||
errdefer if (enter) handle_scope.?.deinit();
|
errdefer if (enter) handle_scope.?.deinit();
|
||||||
|
|
||||||
|
const js_global = v8_context.getGlobal();
|
||||||
{
|
{
|
||||||
// If we want to overwrite the built-in console, we have to
|
// If we want to overwrite the built-in console, we have to
|
||||||
// delete the built-in one.
|
// delete the built-in one.
|
||||||
const js_obj = v8_context.getGlobal();
|
|
||||||
const console_key = v8.String.initUtf8(isolate, "console");
|
const console_key = v8.String.initUtf8(isolate, "console");
|
||||||
if (js_obj.deleteValue(v8_context, console_key) == false) {
|
if (js_global.deleteValue(v8_context, console_key) == false) {
|
||||||
return error.ConsoleDeleteError;
|
return error.ConsoleDeleteError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const context_id = env.context_id;
|
const context_id = env.context_id;
|
||||||
env.context_id = context_id + 1;
|
env.context_id = context_id + 1;
|
||||||
|
|
||||||
@@ -195,17 +196,11 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool, global_cal
|
|||||||
v8_context.setEmbedderData(1, data);
|
v8_context.setEmbedderData(1, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ZIGDOM
|
|
||||||
// Custom exception
|
// Custom exception
|
||||||
// NOTE: there is no way in v8 to subclass the Error built-in type
|
// TODO: this is an horrible hack, I can't figure out how to do this cleanly.
|
||||||
// TODO: this is an horrible hack
|
{
|
||||||
// inline for (JsApi) |JsApi| {
|
_ = try context.exec("DOMException.prototype.__proto__ = Error.prototype", "errorSubclass");
|
||||||
// const Struct = s.defaultValue().?;
|
}
|
||||||
// if (@hasDecl(Struct, "ErrorSet")) {
|
|
||||||
// const script = comptime JsApi.Meta.name ++ ".prototype.__proto__ = Error.prototype";
|
|
||||||
// _ = try context.exec(script, "errorSubclass");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
try context.setupGlobal();
|
try context.setupGlobal();
|
||||||
return context;
|
return context;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
<main>Main content</main>
|
<main>Main content</main>
|
||||||
|
|
||||||
<script id=byId name="test1">
|
<script id=byId name="test1">
|
||||||
testing.expectError("Syntax Error", () => document.querySelector(''));
|
testing.expectError("SyntaxError: Syntax Error", () => document.querySelector(''));
|
||||||
testing.withError((err) => {
|
testing.withError((err) => {
|
||||||
testing.expectEqual(12, err.code);
|
testing.expectEqual(12, err.code);
|
||||||
testing.expectEqual("SyntaxError", err.name);
|
testing.expectEqual("SyntaxError", err.name);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script id=script1 name="test1">
|
<script id=script1 name="test1">
|
||||||
testing.expectError("Syntax Error", () => document.querySelectorAll(''));
|
testing.expectError("SyntaxError: Syntax Error", () => document.querySelectorAll(''));
|
||||||
testing.withError((err) => {
|
testing.withError((err) => {
|
||||||
testing.expectEqual(12, err.code);
|
testing.expectEqual(12, err.code);
|
||||||
testing.expectEqual("SyntaxError", err.name);
|
testing.expectEqual("SyntaxError", err.name);
|
||||||
|
|||||||
@@ -120,16 +120,15 @@
|
|||||||
<div id="content">
|
<div id="content">
|
||||||
<a id="link" href="foo" class="ok">OK</a>
|
<a id="link" href="foo" class="ok">OK</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- <script id=hierarchy_error>
|
|
||||||
|
<script id=hierarchy_error>
|
||||||
let link = $('#link');
|
let link = $('#link');
|
||||||
let content = $('#content');
|
let content = $('#content');
|
||||||
|
|
||||||
testing.withError((err) => {
|
testing.withError((err) => {
|
||||||
const msg = "Failed to execute 'appendChild' on 'Node': The new child element contains the parent.";
|
|
||||||
testing.expectEqual(3, err.code);
|
testing.expectEqual(3, err.code);
|
||||||
testing.expectEqual(msg, err.message);
|
testing.expectEqual('Hierarchy Error', err.message);
|
||||||
testing.expectEqual('HierarchyRequestError: ' + msg, err.toString());
|
|
||||||
testing.expectEqual(true, err instanceof DOMException);
|
testing.expectEqual(true, err instanceof DOMException);
|
||||||
testing.expectEqual(true, err instanceof Error);
|
testing.expectEqual(true, err instanceof Error);
|
||||||
}, () => link.appendChild(content));
|
}, () => link.appendChild(content));
|
||||||
</script> -->
|
</script>
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
{
|
{
|
||||||
const container = $('#test-container');
|
const container = $('#test-container');
|
||||||
|
|
||||||
testing.expectError("Syntax Error", () => container.matches(''));
|
testing.expectError("SyntaxError: Syntax Error", () => container.matches(''));
|
||||||
testing.withError((err) => {
|
testing.withError((err) => {
|
||||||
testing.expectEqual(12, err.code);
|
testing.expectEqual(12, err.code);
|
||||||
testing.expectEqual("SyntaxError", err.name);
|
testing.expectEqual("SyntaxError", err.name);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
const p1 = $('#p1');
|
const p1 = $('#p1');
|
||||||
testing.expectEqual(null, p1.querySelector('#p1'));
|
testing.expectEqual(null, p1.querySelector('#p1'));
|
||||||
|
|
||||||
testing.expectError("Syntax Error", () => p1.querySelector(''));
|
testing.expectError("SyntaxError: Syntax Error", () => p1.querySelector(''));
|
||||||
testing.withError((err) => {
|
testing.withError((err) => {
|
||||||
testing.expectEqual(12, err.code);
|
testing.expectEqual(12, err.code);
|
||||||
testing.expectEqual("SyntaxError", err.name);
|
testing.expectEqual("SyntaxError", err.name);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<script id=errors>
|
<script id=errors>
|
||||||
{
|
{
|
||||||
const root = $('#root');
|
const root = $('#root');
|
||||||
testing.expectError("Syntax Error", () => root.querySelectorAll(''));
|
testing.expectError("SyntaxError: Syntax Error", () => root.querySelectorAll(''));
|
||||||
testing.withError((err) => {
|
testing.withError((err) => {
|
||||||
testing.expectEqual(12, err.code);
|
testing.expectEqual(12, err.code);
|
||||||
testing.expectEqual("SyntaxError", err.name);
|
testing.expectEqual("SyntaxError", err.name);
|
||||||
|
|||||||
@@ -45,8 +45,8 @@
|
|||||||
const container = $('#container');
|
const container = $('#container');
|
||||||
|
|
||||||
// Empty selectors
|
// Empty selectors
|
||||||
testing.expectError("Syntax Error", () => container.querySelector(''));
|
testing.expectError("SyntaxError: Syntax Error", () => container.querySelector(''));
|
||||||
testing.expectError("Syntax Error", () => document.querySelectorAll(''));
|
testing.expectError("SyntaxError: Syntax Error", () => document.querySelectorAll(''));
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -10,10 +10,9 @@
|
|||||||
let link = $('#link');
|
let link = $('#link');
|
||||||
|
|
||||||
testing.withError((err) => {
|
testing.withError((err) => {
|
||||||
const msg = "Failed to execute 'appendChild' on 'Node': The new child element contains the parent.";
|
|
||||||
testing.expectEqual(3, err.code);
|
testing.expectEqual(3, err.code);
|
||||||
testing.expectEqual(msg, err.message);
|
testing.expectEqual('Hierarchy Error', err.message);
|
||||||
testing.expectEqual('HierarchyRequestError: ' + msg, err.toString());
|
testing.expectEqual('HierarchyRequestError: Hierarchy Error', err.toString());
|
||||||
testing.expectEqual(true, err instanceof DOMException);
|
testing.expectEqual(true, err instanceof DOMException);
|
||||||
testing.expectEqual(true, err instanceof Error);
|
testing.expectEqual(true, err instanceof Error);
|
||||||
}, () => link.appendChild(content));
|
}, () => link.appendChild(content));
|
||||||
|
|||||||
@@ -23,16 +23,16 @@ const Page = @import("../Page.zig");
|
|||||||
const DOMException = @This();
|
const DOMException = @This();
|
||||||
|
|
||||||
_code: Code = .none,
|
_code: Code = .none,
|
||||||
_custom_message: ?[]const u8 = null,
|
|
||||||
_custom_name: ?[]const u8 = null,
|
_custom_name: ?[]const u8 = null,
|
||||||
|
_custom_message: ?[]const u8 = null,
|
||||||
|
|
||||||
pub fn init(message: ?[]const u8, name: ?[]const u8) DOMException {
|
pub fn init(message: ?[]const u8, name: ?[]const u8) DOMException {
|
||||||
// If name is provided, try to map it to a legacy code
|
// If name is provided, try to map it to a legacy code
|
||||||
const code = if (name) |n| Code.fromName(n) else .none;
|
const code = if (name) |n| Code.fromName(n) else .none;
|
||||||
return .{
|
return .{
|
||||||
._code = code,
|
._code = code,
|
||||||
._custom_message = message,
|
|
||||||
._custom_name = name,
|
._custom_name = name,
|
||||||
|
._custom_message = message,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,8 +104,8 @@ pub fn getMessage(self: *const DOMException) []const u8 {
|
|||||||
}
|
}
|
||||||
return switch (self._code) {
|
return switch (self._code) {
|
||||||
.none => "",
|
.none => "",
|
||||||
.invalid_character_error => "Error: Invalid Character",
|
.invalid_character_error => "Invalid Character",
|
||||||
.index_size_error => "IndexSizeError: Index or size is negative or greater than the allowed amount",
|
.index_size_error => "Index or size is negative or greater than the allowed amount",
|
||||||
.syntax_error => "Syntax Error",
|
.syntax_error => "Syntax Error",
|
||||||
.not_supported => "Not Supported",
|
.not_supported => "Not Supported",
|
||||||
.not_found => "Not Found",
|
.not_found => "Not Found",
|
||||||
@@ -114,14 +114,17 @@ pub fn getMessage(self: *const DOMException) []const u8 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toString(self: *const DOMException) []const u8 {
|
pub fn toString(self: *const DOMException, page: *Page) ![]const u8 {
|
||||||
if (self._custom_message) |msg| {
|
const msg = blk: {
|
||||||
return msg;
|
if (self._custom_message) |msg| {
|
||||||
}
|
break :blk msg;
|
||||||
return switch (self._code) {
|
}
|
||||||
.none => "Error",
|
switch (self._code) {
|
||||||
else => self.getMessage(),
|
.none => return "Error",
|
||||||
|
else => break :blk self.getMessage(),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
return std.fmt.bufPrint(&page.buf, "{s}: {s}", .{ self.getName(), msg }) catch return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn className(_: *const DOMException) []const u8 {
|
pub fn className(_: *const DOMException) []const u8 {
|
||||||
|
|||||||
@@ -190,12 +190,27 @@ pub fn parentElement(self: *const Node) ?*Element {
|
|||||||
return parent.is(Element);
|
return parent.is(Element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validates that a node can be inserted as a child of parent.
|
||||||
|
fn validateNodeInsertion(parent: *Node, node: *Node) !void {
|
||||||
|
// Check if parent is a valid type to have children
|
||||||
|
if (parent._type != .document and parent._type != .element and parent._type != .document_fragment) {
|
||||||
|
return error.HierarchyError;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if node contains parent (would create a cycle)
|
||||||
|
if (node.contains(parent)) {
|
||||||
|
return error.HierarchyError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn appendChild(self: *Node, child: *Node, page: *Page) !*Node {
|
pub fn appendChild(self: *Node, child: *Node, page: *Page) !*Node {
|
||||||
if (child.is(DocumentFragment)) |_| {
|
if (child.is(DocumentFragment)) |_| {
|
||||||
try page.appendAllChildren(child, self);
|
try page.appendAllChildren(child, self);
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try validateNodeInsertion(self, child);
|
||||||
|
|
||||||
page.domChanged();
|
page.domChanged();
|
||||||
|
|
||||||
// If the child is currently connected, and if its new parent is connected,
|
// If the child is currently connected, and if its new parent is connected,
|
||||||
@@ -435,6 +450,8 @@ pub fn insertBefore(self: *Node, new_node: *Node, ref_node_: ?*Node, page: *Page
|
|||||||
return new_node;
|
return new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try validateNodeInsertion(self, new_node);
|
||||||
|
|
||||||
const child_already_connected = new_node.isConnected();
|
const child_already_connected = new_node.isConnected();
|
||||||
// Check if we're adopting the node to a different document
|
// Check if we're adopting the node to a different document
|
||||||
const child_root = new_node.getRootNode(null);
|
const child_root = new_node.getRootNode(null);
|
||||||
@@ -464,12 +481,8 @@ pub fn replaceChild(self: *Node, new_child: *Node, old_child: *Node, page: *Page
|
|||||||
if (old_child._parent == null or old_child._parent.? != self) {
|
if (old_child._parent == null or old_child._parent.? != self) {
|
||||||
return error.HierarchyError;
|
return error.HierarchyError;
|
||||||
}
|
}
|
||||||
if (self._type != .document and self._type != .element) {
|
|
||||||
return error.HierarchyError;
|
try validateNodeInsertion(self, new_child);
|
||||||
}
|
|
||||||
if (new_child.contains(self)) {
|
|
||||||
return error.HierarchyError;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = try self.insertBefore(new_child, old_child, page);
|
_ = try self.insertBefore(new_child, old_child, page);
|
||||||
page.removeNode(self, old_child, .{ .will_be_reconnected = false });
|
page.removeNode(self, old_child, .{ .will_be_reconnected = false });
|
||||||
@@ -840,7 +853,7 @@ pub const JsApi = struct {
|
|||||||
pub const previousSibling = bridge.accessor(Node.previousSibling, null, .{});
|
pub const previousSibling = bridge.accessor(Node.previousSibling, null, .{});
|
||||||
pub const parentNode = bridge.accessor(Node.parentNode, null, .{});
|
pub const parentNode = bridge.accessor(Node.parentNode, null, .{});
|
||||||
pub const parentElement = bridge.accessor(Node.parentElement, null, .{});
|
pub const parentElement = bridge.accessor(Node.parentElement, null, .{});
|
||||||
pub const appendChild = bridge.function(Node.appendChild, .{});
|
pub const appendChild = bridge.function(Node.appendChild, .{ .dom_exception = true });
|
||||||
pub const childNodes = bridge.accessor(Node.childNodes, null, .{});
|
pub const childNodes = bridge.accessor(Node.childNodes, null, .{});
|
||||||
pub const isConnected = bridge.accessor(Node.isConnected, null, .{});
|
pub const isConnected = bridge.accessor(Node.isConnected, null, .{});
|
||||||
pub const ownerDocument = bridge.accessor(Node.ownerDocument, null, .{});
|
pub const ownerDocument = bridge.accessor(Node.ownerDocument, null, .{});
|
||||||
|
|||||||
Reference in New Issue
Block a user