MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1#include <string.h>
2
3#include "ant.h"
4#include "common.h"
5#include "errors.h"
6#include "internal.h"
7#include "runtime.h"
8#include "descriptors.h"
9
10#include "gc/modules.h"
11#include "modules/symbol.h"
12#include "modules/domexception.h"
13
14static ant_value_t g_domexception_proto = 0;
15static bool g_initialized = false;
16
17static const struct { const char *name; int code; } domex_codes[] = {
18 { "IndexSizeError", 1 },
19 { "HierarchyRequestError", 3 },
20 { "WrongDocumentError", 4 },
21 { "InvalidCharacterError", 5 },
22 { "NoModificationAllowedError", 7 },
23 { "NotFoundError", 8 },
24 { "NotSupportedError", 9 },
25 { "InUseAttributeError", 10 },
26 { "InvalidStateError", 11 },
27 { "SyntaxError", 12 },
28 { "InvalidModificationError", 13 },
29 { "NamespaceError", 14 },
30 { "InvalidAccessError", 15 },
31 { "TypeMismatchError", 17 },
32 { "SecurityError", 18 },
33 { "NetworkError", 19 },
34 { "AbortError", 20 },
35 { "URLMismatchError", 21 },
36 { "QuotaExceededError", 22 },
37 { "TimeoutError", 23 },
38 { "InvalidNodeTypeError", 24 },
39 { "DataCloneError", 25 },
40};
41
42static const struct { const char *prop; int code; } domex_constants[] = {
43 { "INDEX_SIZE_ERR", 1 },
44 { "DOMSTRING_SIZE_ERR", 2 },
45 { "HIERARCHY_REQUEST_ERR", 3 },
46 { "WRONG_DOCUMENT_ERR", 4 },
47 { "INVALID_CHARACTER_ERR", 5 },
48 { "NO_DATA_ALLOWED_ERR", 6 },
49 { "NO_MODIFICATION_ALLOWED_ERR", 7 },
50 { "NOT_FOUND_ERR", 8 },
51 { "NOT_SUPPORTED_ERR", 9 },
52 { "INUSE_ATTRIBUTE_ERR", 10 },
53 { "INVALID_STATE_ERR", 11 },
54 { "SYNTAX_ERR", 12 },
55 { "INVALID_MODIFICATION_ERR", 13 },
56 { "NAMESPACE_ERR", 14 },
57 { "INVALID_ACCESS_ERR", 15 },
58 { "VALIDATION_ERR", 16 },
59 { "TYPE_MISMATCH_ERR", 17 },
60 { "SECURITY_ERR", 18 },
61 { "NETWORK_ERR", 19 },
62 { "ABORT_ERR", 20 },
63 { "URL_MISMATCH_ERR", 21 },
64 { "QUOTA_EXCEEDED_ERR", 22 },
65 { "TIMEOUT_ERR", 23 },
66 { "INVALID_NODE_TYPE_ERR", 24 },
67 { "DATA_CLONE_ERR", 25 },
68};
69
70#define DOMEX_CONSTANTS_LEN (sizeof(domex_constants) / sizeof(domex_constants[0]))
71
72static int name_to_code(const char *name) {
73 if (!name) return 0;
74 for (size_t i = 0; i < sizeof(domex_codes) / sizeof(domex_codes[0]); i++) {
75 if (strcmp(name, domex_codes[i].name) == 0) return domex_codes[i].code;
76 }
77 return 0;
78}
79
80static void set_constants(ant_t *js, ant_value_t obj) {
81for (size_t i = 0; i < DOMEX_CONSTANTS_LEN; i++) {
82 const char *prop = domex_constants[i].prop;
83 size_t len = strlen(prop);
84 js_set(js, obj, prop, js_mknum(domex_constants[i].code));
85 js_set_descriptor(js, obj, prop, len, JS_DESC_E);
86}}
87
88// new DOMException(message?, name?)
89static ant_value_t domexception_ctor(ant_t *js, ant_value_t *args, int nargs) {
90 ant_value_t self = js_getthis(js);
91
92 const char *msg;
93 if (nargs < 1 || vtype(args[0]) == T_UNDEF) {
94 msg = "";
95 } else if (vtype(args[0]) == T_STR) {
96 msg = js_getstr(js, args[0], NULL);
97 if (!msg) msg = "";
98 } else {
99 ant_value_t str_val = js_tostring_val(js, args[0]);
100 msg = (vtype(str_val) == T_STR) ? js_getstr(js, str_val, NULL) : "";
101 if (!msg) msg = "";
102 }
103
104 const char *name = (nargs >= 2 && vtype(args[1]) == T_STR) ? js_getstr(js, args[1], NULL) : "Error";
105 if (!name) name = "Error";
106
107 int code = name_to_code(name);
108 size_t msg_len = strlen(msg);
109 size_t name_len = strlen(name);
110
111 js_set(js, self, "message", js_mkstr(js, msg, msg_len));
112 js_set(js, self, "name", js_mkstr(js, name, name_len));
113 js_set(js, self, "code", js_mknum(code));
114
115 js_set_slot(self, SLOT_ERROR_BRAND, js_true);
116 js_capture_stack(js, self);
117
118 return js_mkundef();
119}
120
121ant_value_t make_dom_exception(ant_t *js, const char *message, const char *name) {
122 size_t msg_len = strlen(message);
123 size_t name_len = strlen(name);
124 int code = name_to_code(name);
125
126 ant_value_t obj = js_mkobj(js);
127 if (g_initialized) js_set_slot_wb(js, obj, SLOT_PROTO, g_domexception_proto);
128
129 js_set(js, obj, "message", js_mkstr(js, message, msg_len));
130 js_set(js, obj, "name", js_mkstr(js, name, name_len));
131 js_set(js, obj, "code", js_mknum(code));
132
133 js_set_sym(js, obj, get_toStringTag_sym(), js_mkstr(js, "DOMException", 12));
134 js_set_slot(obj, SLOT_ERROR_BRAND, js_true);
135
136 return obj;
137}
138
139void init_domexception_module(void) {
140 ant_t *js = rt->js;
141 ant_value_t global = js_glob(js);
142
143 ant_value_t proto = js_mkobj(js);
144 g_domexception_proto = proto;
145 g_initialized = true;
146
147 ant_value_t error_proto = js_get_ctor_proto(js, "Error", 5);
148 if (vtype(error_proto) != T_UNDEF) js_set_proto_init(proto, error_proto);
149
150 js_set(js, proto, "name", js_mkstr(js, "Error", 5));
151 js_set(js, proto, "message", js_mkstr(js, "", 0));
152 js_set(js, proto, "code", js_mknum(0));
153
154 js_set_sym(js, proto, get_toStringTag_sym(), js_mkstr(js, "DOMException", 12));
155 set_constants(js, proto);
156
157 ant_value_t ctor = js_mkobj(js);
158 js_set_slot(ctor, SLOT_CFUNC, js_mkfun(domexception_ctor));
159 js_mkprop_fast(js, ctor, "prototype", 9, proto);
160 js_set_descriptor(js, ctor, "prototype", 9, 0);
161
162 js_mkprop_fast(js, ctor, "name", 4, ANT_STRING("DOMException"));
163 js_set_descriptor(js, ctor, "name", 4, 0);
164 set_constants(js, ctor);
165
166 ant_value_t fn = js_obj_to_func(ctor);
167 js_set(js, proto, "constructor", fn);
168 js_set_descriptor(js, proto, "constructor", 11, JS_DESC_W | JS_DESC_C);
169
170 js_set(js, global, "DOMException", fn);
171 js_set_descriptor(js, global, "DOMException", 12, JS_DESC_W | JS_DESC_C);
172}
173
174void gc_mark_domexception(ant_t *js, gc_mark_fn mark) {
175 if (g_initialized) mark(js, g_domexception_proto);
176}