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.

at type-hints-typescript 223 lines 7.0 kB view raw
1#include "esm/commonjs.h" 2#include "esm/loader.h" 3 4#include "internal.h" 5#include "reactor.h" 6#include "errors.h" 7 8#include "silver/compiler.h" 9#include "silver/engine.h" 10 11#include <libgen.h> 12#include <string.h> 13#include <stdlib.h> 14 15static ant_value_t esm_cjs_require(ant_t *js, ant_value_t *args, int nargs) { 16 if (nargs < 1 || vtype(args[0]) != T_STR) 17 return js_mkerr(js, "require() expects a string specifier"); 18 19 ant_value_t fn = js_getcurrentfunc(js); 20 ant_value_t data = js_get_slot(fn, SLOT_DATA); 21 const char *base_path = js_module_eval_active_filename(js); 22 23 if (vtype(data) == T_STR) { 24 ant_offset_t path_len = 0; 25 ant_offset_t path_off = vstr(js, data, &path_len); 26 base_path = (const char *)(uintptr_t)(path_off); 27 } 28 29 ant_value_t ns = js_esm_import_sync_from_require(js, args[0], base_path); 30 if (is_err(ns)) return ns; 31 32 if (vtype(ns) == T_OBJ) { 33 ant_value_t default_export = js_get_slot(ns, SLOT_DEFAULT); 34 if (vtype(default_export) != T_UNDEF) return default_export; 35 } 36 37 return ns; 38} 39 40static ant_value_t esm_cjs_require_resolve(ant_t *js, ant_value_t *args, int nargs) { 41 if (nargs < 1 || vtype(args[0]) != T_STR) { 42 return js_mkerr(js, "require.resolve() expects a string specifier"); 43 } 44 45 ant_value_t fn = js_getcurrentfunc(js); 46 ant_value_t data = js_get_slot(fn, SLOT_DATA); 47 const char *base_path = js_module_eval_active_filename(js); 48 49 if (vtype(data) == T_STR) { 50 ant_offset_t data_len = 0; 51 ant_offset_t data_off = vstr(js, data, &data_len); 52 base_path = (const char *)(uintptr_t)(data_off); 53 } 54 55 ant_value_t resolved = js_esm_resolve_specifier_require(js, args[0], base_path); 56 if (is_err(resolved)) return resolved; 57 if (vtype(resolved) != T_STR) return resolved; 58 59 ant_offset_t len = 0; 60 ant_offset_t off = vstr(js, resolved, &len); 61 62 const char *s = (const char *)(uintptr_t)(off); 63 static const char *prefix = "file://"; 64 65 if ((size_t)len >= strlen(prefix) && strncmp(s, prefix, strlen(prefix)) == 0) { 66 const char *path_part = s + strlen(prefix); 67 size_t path_len = (size_t)len - strlen(prefix); 68 return js_mkstr(js, path_part, path_len); 69 } 70 71 return resolved; 72} 73 74static bool copy_own_prop( 75 ant_t *js, ant_value_t dst, ant_value_t src, 76 const char *key, size_t key_len, ant_value_t *err 77) { 78 ant_value_t value = js_mkundef(); 79 80 if (js_try_get_own_data_prop(js, src, key, key_len, &value)) { 81 ant_value_t res = setprop_cstr(js, dst, key, key_len, value); 82 if (is_err(res)) { *err = res; return false; } 83 return true; 84 } 85 86 prop_meta_t meta; 87 if (lookup_string_prop_meta(js, src, key, key_len, &meta) && (meta.has_getter || meta.has_setter)) { 88 ant_value_t ns = js_as_obj(dst); 89 int flags = (meta.enumerable ? JS_DESC_E : 0) | (meta.configurable ? JS_DESC_C : 0); 90 if (meta.has_getter) js_set_getter_desc(js, ns, key, key_len, meta.getter, flags); 91 if (meta.has_setter) js_set_setter_desc(js, ns, key, key_len, meta.setter, flags); 92 return true; 93 } 94 95 value = js_get(js, src, key); 96 if (is_err(value)) { *err = value; return false; } 97 if (vtype(value) == T_UNDEF) return true; 98 99 ant_value_t res = setprop_cstr(js, dst, key, key_len, value); 100 if (is_err(res)) { *err = res; return false; } 101 102 return true; 103} 104 105static ant_value_t esm_populate_cjs_namespace(ant_t *js, ant_value_t ns, ant_value_t exports_val) { 106 ant_value_t set_default = setprop_cstr(js, ns, "default", 7, exports_val); 107 if (is_err(set_default)) return set_default; 108 109 js_set_slot_wb(js, ns, SLOT_DEFAULT, exports_val); 110 if (!is_object_type(exports_val)) return js_mkundef(); 111 112 ant_iter_t iter = js_prop_iter_begin(js, exports_val); 113 const char *key = NULL; 114 size_t key_len = 0; 115 116 while (js_prop_iter_next(&iter, &key, &key_len, NULL)) { 117 if (key_len == 7 && memcmp(key, "default", 7) == 0) continue; 118 119 ant_value_t err = js_mkundef(); 120 if (!copy_own_prop(js, ns, exports_val, key, key_len, &err)) { 121 if (is_err(err)) { js_prop_iter_end(&iter); return err; } 122 }} 123 124 js_prop_iter_end(&iter); 125 return js_mkundef(); 126} 127 128static ant_value_t esm_eval_commonjs_function( 129 ant_t *js, 130 const char *code, 131 size_t code_len, 132 ant_value_t require_fn, 133 ant_value_t module_obj, 134 ant_value_t exports_obj, 135 ant_value_t filename_val, 136 ant_value_t dirname_val 137) { 138 static const sv_param_t cjs_params[] = { 139 SV_PARAM("require"), 140 SV_PARAM("module"), 141 SV_PARAM("exports"), 142 SV_PARAM("__filename"), 143 SV_PARAM("__dirname"), 144 }; 145 146 sv_func_t *compiled = sv_compile_function_with_params( 147 js, cjs_params, 148 (int)(sizeof(cjs_params) / sizeof(cjs_params[0])), 149 code, code_len, false 150 ); 151 152 if (!compiled) { 153 if (js->thrown_exists) return mkval(T_ERR, 0); 154 return js_mkerr_typed(js, JS_ERR_INTERNAL | JS_ERR_NO_STACK, "Unexpected compile error"); 155 } 156 157 js_clear_error_site(js); 158 ant_value_t args[] = {require_fn, module_obj, exports_obj, filename_val, dirname_val}; 159 return sv_execute_entry(js->vm, compiled, exports_obj, args, 5); 160} 161 162ant_value_t esm_load_commonjs_module( 163 ant_t *js, 164 const char *module_path, const char *code, 165 size_t code_len, ant_value_t ns 166) { 167 char *path_copy = strdup(module_path); 168 if (!path_copy) return js_mkerr(js, "OOM loading CommonJS module"); 169 170 ant_value_t object_proto = js->sym.object_proto; 171 ant_value_t module_obj = js_mkobj(js); 172 ant_value_t exports_obj = js_mkobj(js); 173 174 if (is_object_type(object_proto)) { 175 js_set_proto_init(module_obj, object_proto); 176 js_set_proto_init(exports_obj, object_proto); 177 } 178 179 js_set(js, module_obj, "exports", exports_obj); 180 js_set(js, module_obj, "loaded", js_false); 181 js_set(js, module_obj, "id", js_mkstr(js, module_path, strlen(module_path))); 182 js_set(js, module_obj, "filename", js_mkstr(js, module_path, strlen(module_path))); 183 184 ant_value_t require_fn = js_heavy_mkfun( 185 js, esm_cjs_require, 186 js_mkstr(js, module_path, strlen(module_path)) 187 ); 188 189 ant_value_t require_resolve_fn = js_heavy_mkfun( 190 js, esm_cjs_require_resolve, 191 js_mkstr(js, module_path, strlen(module_path)) 192 ); 193 194 js_set(js, require_fn, "resolve", require_resolve_fn); 195 196 char *dir = dirname(path_copy); 197 ant_value_t dirname_val = js_mkstr(js, dir, strlen(dir)); 198 ant_value_t filename_val = js_mkstr(js, module_path, strlen(module_path)); 199 200 const char *prev_filename = js->filename; 201 js_set_filename(js, module_path); 202 203 ant_value_t result = esm_eval_commonjs_function( 204 js, code, code_len, 205 require_fn, module_obj, exports_obj, 206 filename_val, dirname_val 207 ); 208 209 if (vtype(result) == T_PROMISE) js_run_event_loop(js); 210 js_set(js, module_obj, "loaded", js_true); 211 ant_value_t exports_val = js_get(js, module_obj, "exports"); 212 213 if (!is_err(result) && !js->thrown_exists) { 214 ant_value_t ns_res = esm_populate_cjs_namespace(js, ns, exports_val); 215 if (is_err(ns_res)) result = ns_res; 216 } 217 218 js_set_filename(js, prev_filename); 219 free(path_copy); 220 221 if (is_err(result)) return result; 222 return exports_val; 223}