MIRROR: javascript for ๐Ÿœ's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

allow dynamic tla

+159 -22
+1
include/esm/loader.h
··· 36 36 ant_value_t js_esm_import_sync_cstr(ant_t *js, const char *specifier, size_t spec_len); 37 37 ant_value_t js_esm_resolve_specifier(ant_t *js, ant_value_t specifier, const char *base_path); 38 38 ant_value_t js_esm_import_sync_cstr_from(ant_t *js, const char *specifier, size_t spec_len, const char *base_path); 39 + ant_value_t js_esm_import_dynamic(ant_t *js, ant_value_t specifier, ant_value_t *out_tla_promise); 39 40 40 41 #endif
+29 -1
src/ant.c
··· 4884 4884 return arr; 4885 4885 } 4886 4886 4887 + static ant_value_t builtin_error_isError(ant_t *js, ant_value_t *args, int nargs) { 4888 + if (nargs < 1) return js_false; 4889 + ant_value_t val = args[0]; 4890 + if (!is_object_type(val)) return js_false; 4891 + return get_slot(val, SLOT_ERROR_BRAND) == js_true ? js_true : js_false; 4892 + } 4893 + 4887 4894 static ant_value_t builtin_Error(ant_t *js, ant_value_t *args, int nargs) { 4888 4895 bool is_new = (vtype(js->new_target) != T_UNDEF); 4889 4896 ant_value_t this_val = js->this_val; ··· 10885 10892 return mkval(T_BOOL, found != 0 ? 1 : 0); 10886 10893 } 10887 10894 10895 + static ant_value_t builtin_import_tla_resolve(ant_t *js, ant_value_t *args, int nargs) { 10896 + ant_value_t me = js->current_func; 10897 + return get_slot(me, SLOT_DATA); 10898 + } 10899 + 10888 10900 static ant_value_t builtin_import(ant_t *js, ant_value_t *args, int nargs) { 10889 10901 if (nargs < 1) return js_mkerr(js, "import() requires a string specifier"); 10890 - ant_value_t ns = js_esm_import_sync(js, args[0]); 10902 + 10903 + ant_value_t tla_promise = js_mkundef(); 10904 + ant_value_t ns = js_esm_import_dynamic(js, args[0], &tla_promise); 10891 10905 if (is_err(ns)) return builtin_Promise_reject(js, &ns, 1); 10906 + 10907 + if (vtype(tla_promise) == T_PROMISE) { 10908 + ant_value_t resolve_fn = make_data_cfunc(js, ns, builtin_import_tla_resolve); 10909 + ant_value_t saved = js->this_val; 10910 + 10911 + js->this_val = tla_promise; 10912 + ant_value_t then_args[] = { resolve_fn }; 10913 + 10914 + ant_value_t result = builtin_promise_then(js, then_args, 1); 10915 + js->this_val = saved; 10916 + 10917 + return result; 10918 + } 10892 10919 10893 10920 ant_value_t promise_args[] = { ns }; 10894 10921 return builtin_Promise_resolve(js, promise_args, 1); ··· 11679 11706 js_setprop(js, glob, ANT_STRING("Error"), err_ctor_func); 11680 11707 js_setprop(js, error_proto, js_mkstr(js, "constructor", 11), err_ctor_func); 11681 11708 js_set_descriptor(js, error_proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 11709 + js_setprop(js, err_ctor_func, ANT_STRING("isError"), js_mkfun(builtin_error_isError)); 11682 11710 11683 11711 #define REGISTER_ERROR_SUBTYPE(name_str) do { \ 11684 11712 ant_value_t proto = js_mkobj(js); \
+36 -7
src/esm/loader.c
··· 41 41 size_t url_content_len; 42 42 ant_value_t namespace_obj; 43 43 ant_value_t default_export; 44 + ant_value_t tla_promise; 44 45 UT_hash_handle hh; 45 46 esm_module_kind_t kind; 46 47 ant_module_format_t format; 47 48 bool is_loaded; 48 49 bool is_loading; 50 + bool has_tla; 49 51 } esm_module_t; 50 52 51 53 typedef struct { ··· 59 61 } esm_file_data_t; 60 62 61 63 static esm_module_cache_t global_module_cache = {NULL, 0}; 64 + static int esm_dynamic_import_depth = 0; 62 65 static char *esm_resolve_node_module(const char *specifier, const char *base_path); 63 66 64 67 static char *esm_file_url_to_path(const char *specifier) { ··· 869 872 .format = MODULE_EVAL_FORMAT_UNKNOWN, 870 873 .url_content = NULL, 871 874 .url_content_len = 0, 875 + .tla_promise = js_mkundef(), 876 + .has_tla = false, 872 877 }; 873 878 874 879 HASH_ADD_STR(global_module_cache.modules, resolved_path, mod); ··· 1078 1083 ); 1079 1084 1080 1085 free(content); 1081 - if (vtype(result) == T_PROMISE) js_run_event_loop(js); 1086 + if (vtype(result) == T_PROMISE) { 1087 + if (esm_dynamic_import_depth > 0) { 1088 + mod->has_tla = true; 1089 + mod->tla_promise = result; 1090 + } else js_run_event_loop(js); } 1082 1091 1083 1092 js_module_eval_ctx_pop(js, &eval_ctx); 1084 1093 js_set_filename(js, prev_filename); ··· 1160 1169 return js_esm_import_sync_from(js, specifier, NULL); 1161 1170 } 1162 1171 1172 + ant_value_t js_esm_import_dynamic(ant_t *js, ant_value_t specifier, ant_value_t *out_tla_promise) { 1173 + *out_tla_promise = js_mkundef(); 1174 + esm_dynamic_import_depth++; 1175 + 1176 + ant_value_t ns = js_esm_import_sync(js, specifier); 1177 + esm_dynamic_import_depth--; 1178 + if (is_err(ns)) return ns; 1179 + 1180 + esm_module_t *mod = NULL, *tmp = NULL; 1181 + HASH_ITER(hh, global_module_cache.modules, mod, tmp) { 1182 + if (mod->has_tla && mod->namespace_obj == ns) { 1183 + *out_tla_promise = mod->tla_promise; 1184 + mod->has_tla = false; 1185 + mod->tla_promise = js_mkundef(); 1186 + break; 1187 + }} 1188 + 1189 + return ns; 1190 + } 1191 + 1163 1192 ant_value_t js_esm_make_file_url(ant_t *js, const char *path) { 1164 1193 size_t url_len = strlen(path) + 8; 1165 1194 char *url = malloc(url_len); ··· 1172 1201 } 1173 1202 1174 1203 void gc_mark_esm(ant_t *js, gc_mark_fn mark) { 1175 - esm_module_t *mod = NULL, *tmp = NULL; 1176 - HASH_ITER(hh, global_module_cache.modules, mod, tmp) { 1177 - mark(js, mod->namespace_obj); 1178 - mark(js, mod->default_export); 1179 - } 1180 - } 1204 + esm_module_t *mod = NULL, *tmp = NULL; 1205 + HASH_ITER(hh, global_module_cache.modules, mod, tmp) { 1206 + mark(js, mod->namespace_obj); 1207 + mark(js, mod->default_export); 1208 + if (mod->has_tla) mark(js, mod->tla_promise); 1209 + }} 1181 1210 1182 1211 ant_value_t js_esm_resolve_specifier(ant_t *js, ant_value_t specifier, const char *base_path) { 1183 1212 if (vtype(specifier) != T_STR) {
+12 -6
src/modules/assert.c
··· 196 196 return obj && obj->promise_state && obj->promise_state->state == 2; 197 197 } 198 198 199 + static void promise_mark_handled(ant_value_t result) { 200 + if (vtype(result) != T_PROMISE) return; 201 + ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 202 + if (obj && obj->promise_state) obj->promise_state->has_rejection_handler = true; 203 + } 204 + 199 205 static bool promise_was_fulfilled(ant_value_t result) { 200 206 if (vtype(result) != T_PROMISE) return false; 201 207 ant_object_t *obj = js_obj_ptr(js_as_obj(result)); ··· 208 214 ant_value_t result = vtype(args[0]) == T_FUNC 209 215 ? sv_vm_call(js->vm, js, args[0], js_mkundef(), NULL, 0, NULL, false) 210 216 : args[0]; 211 - if (is_err(result) || promise_was_rejected(result)) 217 + if (is_err(result) || promise_was_rejected(result)) { 218 + promise_mark_handled(result); 212 219 js_resolve_promise(js, promise, js_mkundef()); 213 - else 214 - js_reject_promise(js, promise, js_mkerr(js, "Missing expected rejection")); 220 + } else js_reject_promise(js, promise, js_mkerr(js, "Missing expected rejection")); 215 221 return promise; 216 222 } 217 223 ··· 221 227 ant_value_t result = vtype(args[0]) == T_FUNC 222 228 ? sv_vm_call(js->vm, js, args[0], js_mkundef(), NULL, 0, NULL, false) 223 229 : args[0]; 224 - if (is_err(result) || promise_was_rejected(result)) 230 + if (is_err(result) || promise_was_rejected(result)) { 231 + promise_mark_handled(result); 225 232 js_reject_promise(js, promise, js_mkerr(js, "Got unwanted rejection")); 226 - else 227 - js_resolve_promise(js, promise, js_mkundef()); 233 + } else js_resolve_promise(js, promise, js_mkundef()); 228 234 return promise; 229 235 } 230 236
+68 -1
src/modules/domexception.c
··· 1 1 #include <string.h> 2 2 3 3 #include "ant.h" 4 + #include "common.h" 5 + #include "errors.h" 4 6 #include "internal.h" 5 7 #include "runtime.h" 6 8 #include "descriptors.h" ··· 26 28 { "InvalidModificationError", 13 }, 27 29 { "NamespaceError", 14 }, 28 30 { "InvalidAccessError", 15 }, 31 + { "TypeMismatchError", 17 }, 29 32 { "SecurityError", 18 }, 30 33 { "NetworkError", 19 }, 31 34 { "AbortError", 20 }, ··· 36 39 { "DataCloneError", 25 }, 37 40 }; 38 41 42 + static 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 + 39 72 static int name_to_code(const char *name) { 40 73 if (!name) return 0; 41 74 for (size_t i = 0; i < sizeof(domex_codes) / sizeof(domex_codes[0]); i++) { ··· 44 77 return 0; 45 78 } 46 79 80 + static void set_constants(ant_t *js, ant_value_t obj) { 81 + for (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 + 47 88 // new DOMException(message?, name?) 48 89 static ant_value_t domexception_ctor(ant_t *js, ant_value_t *args, int nargs) { 49 90 ant_value_t self = js_getthis(js); 50 91 51 - const char *msg = (nargs >= 1 && vtype(args[0]) == T_STR) ? js_getstr(js, args[0], NULL) : ""; 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 + 52 104 const char *name = (nargs >= 2 && vtype(args[1]) == T_STR) ? js_getstr(js, args[1], NULL) : "Error"; 105 + if (!name) name = "Error"; 53 106 54 107 int code = name_to_code(name); 55 108 size_t msg_len = strlen(msg); ··· 59 112 js_set(js, self, "name", js_mkstr(js, name, name_len)); 60 113 js_set(js, self, "code", js_mknum(code)); 61 114 115 + js_set_slot(self, SLOT_ERROR_BRAND, js_true); 116 + js_capture_stack(js, self); 117 + 62 118 return js_mkundef(); 63 119 } 64 120 ··· 73 129 js_set(js, obj, "message", js_mkstr(js, message, msg_len)); 74 130 js_set(js, obj, "name", js_mkstr(js, name, name_len)); 75 131 js_set(js, obj, "code", js_mknum(code)); 132 + 76 133 js_set_sym(js, obj, get_toStringTag_sym(), js_mkstr(js, "DOMException", 12)); 134 + js_set_slot(obj, SLOT_ERROR_BRAND, js_true); 77 135 78 136 return obj; 79 137 } ··· 86 144 g_domexception_proto = proto; 87 145 g_initialized = true; 88 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 + 89 150 js_set(js, proto, "name", js_mkstr(js, "Error", 5)); 90 151 js_set(js, proto, "message", js_mkstr(js, "", 0)); 91 152 js_set(js, proto, "code", js_mknum(0)); 153 + 92 154 js_set_sym(js, proto, get_toStringTag_sym(), js_mkstr(js, "DOMException", 12)); 155 + set_constants(js, proto); 93 156 94 157 ant_value_t ctor = js_mkobj(js); 95 158 js_set_slot(ctor, SLOT_CFUNC, js_mkfun(domexception_ctor)); 96 159 js_mkprop_fast(js, ctor, "prototype", 9, proto); 160 + js_set_descriptor(js, ctor, "prototype", 9, 0); 161 + 97 162 js_mkprop_fast(js, ctor, "name", 4, ANT_STRING("DOMException")); 98 163 js_set_descriptor(js, ctor, "name", 4, 0); 164 + set_constants(js, ctor); 99 165 100 166 ant_value_t fn = js_obj_to_func(ctor); 101 167 js_set(js, proto, "constructor", fn); 102 168 js_set_descriptor(js, proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 103 169 104 170 js_set(js, global, "DOMException", fn); 171 + js_set_descriptor(js, global, "DOMException", 12, JS_DESC_W | JS_DESC_C); 105 172 } 106 173 107 174 void gc_mark_domexception(ant_t *js, gc_mark_fn mark) {
+13 -7
src/runtime.c
··· 1 1 #include "ant.h" 2 2 #include "runtime.h" 3 3 #include "descriptors.h" 4 - #include "silver/engine.h" 5 4 6 5 #include <stdio.h> 7 6 #include <stdlib.h> ··· 164 163 } 165 164 166 165 struct ant_runtime *ant_runtime_init(ant_t *js, int argc, char **argv, struct arg_file *ls_p) { 166 + ant_value_t global = js_glob(js); 167 + 167 168 runtime = (struct ant_runtime){ 168 169 .js = js, 169 170 .ant_obj = js_newobj(js), ··· 171 172 .pid = (int)ant_getpid(), 172 173 .ls_fp = (ls_p && ls_p->count > 0) ? ls_p->filename[0] : NULL, 173 174 }; 174 - 175 - ant_value_t global = js_glob(js); 175 + 176 + js_set(js, global, "self", global); 177 + js_set_descriptor(js, global, "self", 4, JS_DESC_W | JS_DESC_C); 178 + 176 179 js_set(js, global, "window", global); 180 + js_set_descriptor(js, global, "window", 6, JS_DESC_W | JS_DESC_C); 181 + 177 182 js_set(js, global, "global", global); 183 + js_set_descriptor(js, global, "global", 6, JS_DESC_W | JS_DESC_C); 184 + 178 185 js_set(js, global, "globalThis", global); 186 + js_set_descriptor(js, global, "globalThis", 10, JS_DESC_W | JS_DESC_C); 187 + 179 188 js_set(js, global, "Ant", runtime.ant_obj); 180 - 181 - js_set_descriptor(js, js_as_obj(global), "window", 6, JS_DESC_W | JS_DESC_C); 182 - js_set_descriptor(js, js_as_obj(global), "global", 6, JS_DESC_W | JS_DESC_C); 183 - js_set_descriptor(js, js_as_obj(global), "globalThis", 10, JS_DESC_W | JS_DESC_C); 189 + js_set_descriptor(js, global, "Ant", 3, JS_DESC_E); 184 190 185 191 return &runtime; 186 192 }