@@ -20,10 +20,11 @@ const std = @import("std");
2020const allocPrint = std .fmt .allocPrint ;
2121
2222const parser = @import ("../netsurf.zig" );
23+ const Page = @import ("../page.zig" ).Page ;
2324
2425// https://webidl.spec.whatwg.org/#idl-DOMException
2526pub const DOMException = struct {
26- err : parser.DOMError ,
27+ err : ? parser.DOMError ,
2728 str : []const u8 ,
2829
2930 pub const ErrorSet = parser .DOMError ;
@@ -55,6 +56,17 @@ pub const DOMException = struct {
5556 pub const _INVALID_NODE_TYPE_ERR = 24 ;
5657 pub const _DATA_CLONE_ERR = 25 ;
5758
59+ pub fn constructor (message_ : ? []const u8 , name_ : ? []const u8 , page : * const Page ) ! DOMException {
60+ const message = message_ orelse "" ;
61+ const err = if (name_ ) | n | error_from_str (n ) else null ;
62+ const fixed_name = name (err );
63+
64+ if (message .len == 0 ) return .{ .err = err , .str = fixed_name };
65+
66+ const str = try allocPrint (page .arena , "{s}: {s}" , .{ fixed_name , message });
67+ return .{ .err = err , .str = str };
68+ }
69+
5870 // TODO: deinit
5971 pub fn init (alloc : std.mem.Allocator , err : anyerror , callerName : []const u8 ) ! DOMException {
6072 const errCast = @as (parser .DOMError , @errorCast (err ));
@@ -75,14 +87,52 @@ pub const DOMException = struct {
7587 return .{ .err = errCast , .str = str };
7688 }
7789
78- fn name (err : parser.DOMError ) []const u8 {
90+ fn error_from_str (name_ : []const u8 ) ? parser.DOMError {
91+ // @speed: Consider length first, left as is for maintainability, awaiting switch on string support
92+ if (std .mem .eql (u8 , name_ , "IndexSizeError" )) return error .IndexSize ;
93+ if (std .mem .eql (u8 , name_ , "StringSizeError" )) return error .StringSize ;
94+ if (std .mem .eql (u8 , name_ , "HierarchyRequestError" )) return error .HierarchyRequest ;
95+ if (std .mem .eql (u8 , name_ , "WrongDocumentError" )) return error .WrongDocument ;
96+ if (std .mem .eql (u8 , name_ , "InvalidCharacterError" )) return error .InvalidCharacter ;
97+ if (std .mem .eql (u8 , name_ , "NoDataAllowedError" )) return error .NoDataAllowed ;
98+ if (std .mem .eql (u8 , name_ , "NoModificationAllowedError" )) return error .NoModificationAllowed ;
99+ if (std .mem .eql (u8 , name_ , "NotFoundError" )) return error .NotFound ;
100+ if (std .mem .eql (u8 , name_ , "NotSupportedError" )) return error .NotSupported ;
101+ if (std .mem .eql (u8 , name_ , "InuseAttributeError" )) return error .InuseAttribute ;
102+ if (std .mem .eql (u8 , name_ , "InvalidStateError" )) return error .InvalidState ;
103+ if (std .mem .eql (u8 , name_ , "SyntaxError" )) return error .Syntax ;
104+ if (std .mem .eql (u8 , name_ , "InvalidModificationError" )) return error .InvalidModification ;
105+ if (std .mem .eql (u8 , name_ , "NamespaceError" )) return error .Namespace ;
106+ if (std .mem .eql (u8 , name_ , "InvalidAccessError" )) return error .InvalidAccess ;
107+ if (std .mem .eql (u8 , name_ , "ValidationError" )) return error .Validation ;
108+ if (std .mem .eql (u8 , name_ , "TypeMismatchError" )) return error .TypeMismatch ;
109+ if (std .mem .eql (u8 , name_ , "SecurityError" )) return error .Security ;
110+ if (std .mem .eql (u8 , name_ , "NetworkError" )) return error .Network ;
111+ if (std .mem .eql (u8 , name_ , "AbortError" )) return error .Abort ;
112+ if (std .mem .eql (u8 , name_ , "URLismatchError" )) return error .URLismatch ;
113+ if (std .mem .eql (u8 , name_ , "QuotaExceededError" )) return error .QuotaExceeded ;
114+ if (std .mem .eql (u8 , name_ , "TimeoutError" )) return error .Timeout ;
115+ if (std .mem .eql (u8 , name_ , "InvalidNodeTypeError" )) return error .InvalidNodeType ;
116+ if (std .mem .eql (u8 , name_ , "DataCloneError" )) return error .DataClone ;
117+
118+ // custom netsurf error
119+ if (std .mem .eql (u8 , name_ , "UnspecifiedEventTypeError" )) return error .UnspecifiedEventType ;
120+ if (std .mem .eql (u8 , name_ , "DispatchRequestError" )) return error .DispatchRequest ;
121+ if (std .mem .eql (u8 , name_ , "NoMemoryError" )) return error .NoMemory ;
122+ if (std .mem .eql (u8 , name_ , "AttributeWrongTypeError" )) return error .AttributeWrongType ;
123+ return null ;
124+ }
125+
126+ fn name (err_ : ? parser.DOMError ) []const u8 {
127+ const err = err_ orelse return "Error" ;
128+
79129 return switch (err ) {
80130 error .IndexSize = > "IndexSizeError" ,
81- error .StringSize = > "StringSizeError" ,
131+ error .StringSize = > "StringSizeError" , // Legacy: DOMSTRING_SIZE_ERR
82132 error .HierarchyRequest = > "HierarchyRequestError" ,
83133 error .WrongDocument = > "WrongDocumentError" ,
84134 error .InvalidCharacter = > "InvalidCharacterError" ,
85- error .NoDataAllowed = > "NoDataAllowedError" ,
135+ error .NoDataAllowed = > "NoDataAllowedError" , // Legacy: NO_DATA_ALLOWED_ERR
86136 error .NoModificationAllowed = > "NoModificationAllowedError" ,
87137 error .NotFound = > "NotFoundError" ,
88138 error .NotSupported = > "NotSupportedError" ,
@@ -92,7 +142,7 @@ pub const DOMException = struct {
92142 error .InvalidModification = > "InvalidModificationError" ,
93143 error .Namespace = > "NamespaceError" ,
94144 error .InvalidAccess = > "InvalidAccessError" ,
95- error .Validation = > "ValidationError" ,
145+ error .Validation = > "ValidationError" , // Legacy: VALIDATION_ERR
96146 error .TypeMismatch = > "TypeMismatchError" ,
97147 error .Security = > "SecurityError" ,
98148 error .Network = > "NetworkError" ,
@@ -115,7 +165,8 @@ pub const DOMException = struct {
115165 // JS properties and methods
116166
117167 pub fn get_code (self : * const DOMException ) u8 {
118- return switch (self .err ) {
168+ const err = self .err orelse return 0 ;
169+ return switch (err ) {
119170 error .IndexSize = > 1 ,
120171 error .StringSize = > 2 ,
121172 error .HierarchyRequest = > 3 ,
@@ -157,7 +208,8 @@ pub const DOMException = struct {
157208
158209 pub fn get_message (self : * const DOMException ) []const u8 {
159210 const errName = DOMException .name (self .err );
160- return self .str [errName .len + 2 .. ];
211+ if (self .str .len <= errName .len + 2 ) return "" ;
212+ return self .str [errName .len + 2 .. ]; // ! Requires str is formatted as "{name}: {message}"
161213 }
162214
163215 pub fn _toString (self : * const DOMException ) []const u8 {
@@ -188,4 +240,25 @@ test "Browser.DOM.Exception" {
188240 .{ "he instanceof DOMException" , "true" },
189241 .{ "he instanceof Error" , "true" },
190242 }, .{});
243+
244+ // Test DOMException constructor
245+ try runner .testCases (&.{
246+ .{ "let exc0 = new DOMException()" , "undefined" },
247+ .{ "exc0.name" , "Error" },
248+ .{ "exc0.code" , "0" },
249+ .{ "exc0.message" , "" },
250+ .{ "exc0.toString()" , "Error" },
251+
252+ .{ "let exc1 = new DOMException('Sandwich malfunction')" , "undefined" },
253+ .{ "exc1.name" , "Error" },
254+ .{ "exc1.code" , "0" },
255+ .{ "exc1.message" , "Sandwich malfunction" },
256+ .{ "exc1.toString()" , "Error: Sandwich malfunction" },
257+
258+ .{ "let exc2 = new DOMException('Caterpillar turned into a butterfly', 'NoModificationAllowedError')" , "undefined" },
259+ .{ "exc2.name" , "NoModificationAllowedError" },
260+ .{ "exc2.code" , "7" },
261+ .{ "exc2.message" , "Caterpillar turned into a butterfly" },
262+ .{ "exc2.toString()" , "NoModificationAllowedError: Caterpillar turned into a butterfly" },
263+ }, .{});
191264}
0 commit comments