mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-12-16 16:28:58 +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();
|
||||
global_template.setInternalFieldCount(1);
|
||||
|
||||
// Configure the missing property callback on the global
|
||||
// object.
|
||||
// Configure the missing property callback on the global object.
|
||||
if (global_callback != null) {
|
||||
const configuration = v8.NamedPropertyHandlerConfiguration{
|
||||
.getter = struct {
|
||||
@@ -162,15 +161,17 @@ pub fn createContext(self: *ExecutionWorld, page: *Page, enter: bool, global_cal
|
||||
}
|
||||
errdefer if (enter) handle_scope.?.deinit();
|
||||
|
||||
const js_global = v8_context.getGlobal();
|
||||
{
|
||||
// If we want to overwrite the built-in console, we have to
|
||||
// delete the built-in one.
|
||||
const js_obj = v8_context.getGlobal();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
const context_id = env.context_id;
|
||||
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);
|
||||
}
|
||||
|
||||
// @ZIGDOM
|
||||
// Custom exception
|
||||
// NOTE: there is no way in v8 to subclass the Error built-in type
|
||||
// TODO: this is an horrible hack
|
||||
// inline for (JsApi) |JsApi| {
|
||||
// const Struct = s.defaultValue().?;
|
||||
// if (@hasDecl(Struct, "ErrorSet")) {
|
||||
// const script = comptime JsApi.Meta.name ++ ".prototype.__proto__ = Error.prototype";
|
||||
// _ = try context.exec(script, "errorSubclass");
|
||||
// }
|
||||
// }
|
||||
// TODO: this is an horrible hack, I can't figure out how to do this cleanly.
|
||||
{
|
||||
_ = try context.exec("DOMException.prototype.__proto__ = Error.prototype", "errorSubclass");
|
||||
}
|
||||
|
||||
try context.setupGlobal();
|
||||
return context;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<main>Main content</main>
|
||||
|
||||
<script id=byId name="test1">
|
||||
testing.expectError("Syntax Error", () => document.querySelector(''));
|
||||
testing.expectError("SyntaxError: Syntax Error", () => document.querySelector(''));
|
||||
testing.withError((err) => {
|
||||
testing.expectEqual(12, err.code);
|
||||
testing.expectEqual("SyntaxError", err.name);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
</script>
|
||||
|
||||
<script id=script1 name="test1">
|
||||
testing.expectError("Syntax Error", () => document.querySelectorAll(''));
|
||||
testing.expectError("SyntaxError: Syntax Error", () => document.querySelectorAll(''));
|
||||
testing.withError((err) => {
|
||||
testing.expectEqual(12, err.code);
|
||||
testing.expectEqual("SyntaxError", err.name);
|
||||
|
||||
@@ -120,16 +120,15 @@
|
||||
<div id="content">
|
||||
<a id="link" href="foo" class="ok">OK</a>
|
||||
</div>
|
||||
<!-- <script id=hierarchy_error>
|
||||
|
||||
<script id=hierarchy_error>
|
||||
let link = $('#link');
|
||||
let content = $('#content');
|
||||
|
||||
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(msg, err.message);
|
||||
testing.expectEqual('HierarchyRequestError: ' + msg, err.toString());
|
||||
testing.expectEqual('Hierarchy Error', err.message);
|
||||
testing.expectEqual(true, err instanceof DOMException);
|
||||
testing.expectEqual(true, err instanceof Error);
|
||||
}, () => link.appendChild(content));
|
||||
</script> -->
|
||||
</script>
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
{
|
||||
const container = $('#test-container');
|
||||
|
||||
testing.expectError("Syntax Error", () => container.matches(''));
|
||||
testing.expectError("SyntaxError: Syntax Error", () => container.matches(''));
|
||||
testing.withError((err) => {
|
||||
testing.expectEqual(12, err.code);
|
||||
testing.expectEqual("SyntaxError", err.name);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
const p1 = $('#p1');
|
||||
testing.expectEqual(null, p1.querySelector('#p1'));
|
||||
|
||||
testing.expectError("Syntax Error", () => p1.querySelector(''));
|
||||
testing.expectError("SyntaxError: Syntax Error", () => p1.querySelector(''));
|
||||
testing.withError((err) => {
|
||||
testing.expectEqual(12, err.code);
|
||||
testing.expectEqual("SyntaxError", err.name);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<script id=errors>
|
||||
{
|
||||
const root = $('#root');
|
||||
testing.expectError("Syntax Error", () => root.querySelectorAll(''));
|
||||
testing.expectError("SyntaxError: Syntax Error", () => root.querySelectorAll(''));
|
||||
testing.withError((err) => {
|
||||
testing.expectEqual(12, err.code);
|
||||
testing.expectEqual("SyntaxError", err.name);
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
const container = $('#container');
|
||||
|
||||
// Empty selectors
|
||||
testing.expectError("Syntax Error", () => container.querySelector(''));
|
||||
testing.expectError("Syntax Error", () => document.querySelectorAll(''));
|
||||
testing.expectError("SyntaxError: Syntax Error", () => container.querySelector(''));
|
||||
testing.expectError("SyntaxError: Syntax Error", () => document.querySelectorAll(''));
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -10,10 +10,9 @@
|
||||
let link = $('#link');
|
||||
|
||||
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(msg, err.message);
|
||||
testing.expectEqual('HierarchyRequestError: ' + msg, err.toString());
|
||||
testing.expectEqual('Hierarchy Error', err.message);
|
||||
testing.expectEqual('HierarchyRequestError: Hierarchy Error', err.toString());
|
||||
testing.expectEqual(true, err instanceof DOMException);
|
||||
testing.expectEqual(true, err instanceof Error);
|
||||
}, () => link.appendChild(content));
|
||||
|
||||
@@ -23,16 +23,16 @@ const Page = @import("../Page.zig");
|
||||
const DOMException = @This();
|
||||
|
||||
_code: Code = .none,
|
||||
_custom_message: ?[]const u8 = null,
|
||||
_custom_name: ?[]const u8 = null,
|
||||
_custom_message: ?[]const u8 = null,
|
||||
|
||||
pub fn init(message: ?[]const u8, name: ?[]const u8) DOMException {
|
||||
// If name is provided, try to map it to a legacy code
|
||||
const code = if (name) |n| Code.fromName(n) else .none;
|
||||
return .{
|
||||
._code = code,
|
||||
._custom_message = message,
|
||||
._custom_name = name,
|
||||
._custom_message = message,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ pub fn getMessage(self: *const DOMException) []const u8 {
|
||||
}
|
||||
return switch (self._code) {
|
||||
.none => "",
|
||||
.invalid_character_error => "Error: Invalid Character",
|
||||
.index_size_error => "IndexSizeError: Index or size is negative or greater than the allowed amount",
|
||||
.invalid_character_error => "Invalid Character",
|
||||
.index_size_error => "Index or size is negative or greater than the allowed amount",
|
||||
.syntax_error => "Syntax Error",
|
||||
.not_supported => "Not Supported",
|
||||
.not_found => "Not Found",
|
||||
@@ -114,14 +114,17 @@ pub fn getMessage(self: *const DOMException) []const u8 {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn toString(self: *const DOMException) []const u8 {
|
||||
if (self._custom_message) |msg| {
|
||||
return msg;
|
||||
}
|
||||
return switch (self._code) {
|
||||
.none => "Error",
|
||||
else => self.getMessage(),
|
||||
pub fn toString(self: *const DOMException, page: *Page) ![]const u8 {
|
||||
const msg = blk: {
|
||||
if (self._custom_message) |msg| {
|
||||
break :blk msg;
|
||||
}
|
||||
switch (self._code) {
|
||||
.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 {
|
||||
|
||||
@@ -190,12 +190,27 @@ pub fn parentElement(self: *const Node) ?*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 {
|
||||
if (child.is(DocumentFragment)) |_| {
|
||||
try page.appendAllChildren(child, self);
|
||||
return child;
|
||||
}
|
||||
|
||||
try validateNodeInsertion(self, child);
|
||||
|
||||
page.domChanged();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
try validateNodeInsertion(self, new_node);
|
||||
|
||||
const child_already_connected = new_node.isConnected();
|
||||
// Check if we're adopting the node to a different document
|
||||
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) {
|
||||
return error.HierarchyError;
|
||||
}
|
||||
if (self._type != .document and self._type != .element) {
|
||||
return error.HierarchyError;
|
||||
}
|
||||
if (new_child.contains(self)) {
|
||||
return error.HierarchyError;
|
||||
}
|
||||
|
||||
try validateNodeInsertion(self, new_child);
|
||||
|
||||
_ = try self.insertBefore(new_child, old_child, page);
|
||||
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 parentNode = bridge.accessor(Node.parentNode, 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 isConnected = bridge.accessor(Node.isConnected, null, .{});
|
||||
pub const ownerDocument = bridge.accessor(Node.ownerDocument, null, .{});
|
||||
|
||||
Reference in New Issue
Block a user