MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1#include <compat.h> // IWYU pragma: keep
2
3#include <string.h>
4#include <stdbool.h>
5
6#include "ant.h"
7#include "errors.h"
8#include "runtime.h"
9#include "internal.h"
10#include "descriptors.h"
11#include "silver/engine.h"
12
13#include "modules/events.h"
14#include "modules/globals.h"
15
16ant_value_t js_report_error(ant_t *js, ant_value_t *args, int nargs) {
17 if (nargs < 1) return js_mkerr_typed(js, JS_ERR_TYPE, "reportError requires 1 argument");
18
19 ant_value_t error = args[0];
20 ant_value_t global = js_glob(js);
21
22 const char *msg = "";
23 uint8_t et = vtype(error);
24
25 if (et == T_STR) {
26 msg = js_str(js, error);
27 } else if (et == T_OBJ) {
28 const char *m = get_str_prop(js, error, "message", 7, NULL);
29 if (m && *m) msg = m;
30 }
31
32 if (!*msg) {
33 ant_value_t str = js_tostring_val(js, error);
34 if (vtype(str) == T_STR) { const char *s = js_str(js, str); if (s) msg = s; }
35 }
36
37 const char *filename = "";
38 int lineno = 1, colno = 1;
39 js_get_call_location(js, &filename, &lineno, &colno);
40 if (!filename) filename = "";
41
42 ant_value_t loc = js_get(js, global, "location");
43 if (vtype(loc) == T_OBJ) {
44 const char *href = get_str_prop(js, loc, "href", 4, NULL);
45 if (href && *href) filename = href;
46 }
47
48 ant_value_t event = js_mkobj(js);
49 js_set(js, event, "type", js_mkstr(js, "error", 5));
50 js_set(js, event, "message", js_mkstr(js, msg, strlen(msg)));
51 js_set(js, event, "filename", js_mkstr(js, filename, strlen(filename)));
52 js_set(js, event, "lineno", js_mknum(lineno));
53 js_set(js, event, "colno", js_mknum(colno));
54 js_set(js, event, "error", error);
55
56 js_dispatch_global_event(js, event);
57 ant_value_t handler = js_get(js, global, "onerror");
58
59 uint8_t ht = vtype(handler);
60 if (ht == T_FUNC || ht == T_CFUNC) {
61 ant_value_t msg_str = js_mkstr(js, msg, strlen(msg));
62 ant_value_t file_str = js_mkstr(js, filename, strlen(filename));
63 ant_value_t call_args[5] = { msg_str, file_str, js_mknum(lineno), js_mknum(colno), error };
64 sv_vm_call(js->vm, js, handler, global, call_args, 5, NULL, false);
65 }
66
67 return js_mkundef();
68}
69
70bool js_fire_unhandled_rejection(ant_t *js, ant_value_t promise_val, ant_value_t reason) {
71 ant_value_t global = js_glob(js);
72 ant_value_t handler = js_get(js, global, "onunhandledrejection");
73
74 uint8_t ht = vtype(handler);
75 if (ht != T_FUNC && ht != T_CFUNC) return false;
76
77 ant_value_t event = js_mkobj(js);
78 js_set(js, event, "type", js_mkstr(js, "unhandledrejection", 18));
79 js_set(js, event, "reason", reason);
80 js_set(js, event, "promise", promise_val);
81
82 ant_value_t call_args[1] = { event };
83 sv_vm_call(js->vm, js, handler, global, call_args, 1, NULL, false);
84
85 return true;
86}
87
88void js_fire_rejection_handled(ant_t *js, ant_value_t promise_val, ant_value_t reason) {
89 ant_value_t global = js_glob(js);
90 ant_value_t handler = js_get(js, global, "onrejectionhandled");
91
92 uint8_t ht = vtype(handler);
93 if (ht != T_FUNC && ht != T_CFUNC) return;
94
95 ant_value_t event = js_mkobj(js);
96 js_set(js, event, "type", js_mkstr(js, "rejectionhandled", 16));
97 js_set(js, event, "reason", reason);
98 js_set(js, event, "promise", promise_val);
99
100 ant_value_t call_args[1] = { event };
101 sv_vm_call(js->vm, js, handler, global, call_args, 1, NULL, false);
102}
103
104void init_globals_module(void) {
105 ant_t *js = rt->js;
106 ant_value_t global = js_glob(js);
107
108 js_set(js, global, "reportError", js_mkfun(js_report_error));
109 js_set_descriptor(js, global, "reportError", 11, JS_DESC_W | JS_DESC_C);
110}