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.

add named export error instead of undefined placeholder

+122 -8
+1
include/silver/opcode.h
··· 220 220 OP_DEF( IMPORT, 1, 2, 1, none) /* dynamic import(specifier) */ 221 221 OP_DEF( IMPORT_SYNC, 1, 1, 1, none) /* sync module load for static import */ 222 222 OP_DEF( IMPORT_DEFAULT, 1, 1, 1, none) /* ns -> default (SLOT_DEFAULT or ns) */ 223 + OP_DEF( IMPORT_NAMED, 5, 1, 1, atom) /* ns -> named export (throw if missing) */ 223 224 OP_DEF( EXPORT, 5, 1, 0, atom) /* value -> (module namespace[name] = value) */ 224 225 OP_DEF( EXPORT_ALL, 1, 1, 0, none) /* ns -> (export all properties) */ 225 226
+12
src/builtins/node/http.mjs
··· 106 106 } 107 107 } 108 108 109 + function clientNotImplemented() { 110 + throw new Error('node:http client transport is not implemented yet'); 111 + } 112 + 109 113 export class IncomingMessage extends EventEmitter { 110 114 constructor(socket, parsed) { 111 115 super(); ··· 449 453 450 454 export function createServer(options, requestListener) { 451 455 return new Server(options, requestListener); 456 + } 457 + 458 + export function request() { 459 + clientNotImplemented(); 460 + } 461 + 462 + export function get() { 463 + clientNotImplemented(); 452 464 } 453 465 454 466 export { METHODS, STATUS_CODES } from 'ant:internal/http_metadata';
+11 -1
src/esm/loader.c
··· 203 203 ant_module_t *out_ctx 204 204 ) { 205 205 ant_value_t module_ctx = js_create_module_context(js, resolved_path, is_main); 206 + 206 207 if (is_err(module_ctx)) return module_ctx; 208 + if (is_object_type(ns)) js_set_slot_wb(js, ns, SLOT_MODULE_CTX, module_ctx); 207 209 208 210 *out_ctx = (ant_module_t){ 209 211 .module_ns = ns, ··· 212 214 .format = format, 213 215 .prev = NULL, 214 216 }; 217 + 215 218 return js_mkundef(); 216 219 } 217 220 ··· 1028 1031 case ESM_MODULE_KIND_NATIVE: { 1029 1032 ant_value_t ns = esm_make_namespace_object(js); 1030 1033 mod->namespace_obj = ns; 1031 - 1034 + 1035 + ant_value_t module_ctx = js_create_module_context(js, mod->resolved_path, false); 1036 + if (is_err(module_ctx)) { 1037 + mod->is_loading = false; 1038 + return module_ctx; 1039 + } 1040 + js_set_slot_wb(js, ns, SLOT_MODULE_CTX, module_ctx); 1041 + 1032 1042 ant_value_t native_exports = napi_load_native_module(js, mod->resolved_path, ns); 1033 1043 if (is_err(native_exports)) { 1034 1044 mod->is_loading = false;
+2 -2
src/silver/compiler.c
··· 2919 2919 !spec->left || spec->left->type != N_IDENT) { 2920 2920 emit_op(c, OP_IMPORT_DEFAULT); 2921 2921 } else { 2922 - emit_atom_op(c, OP_GET_FIELD, spec->left->str, spec->left->len); 2922 + emit_atom_op(c, OP_IMPORT_NAMED, spec->left->str, spec->left->len); 2923 2923 } 2924 2924 } 2925 2925 ··· 3089 3089 if (spec->left->len == 7 && memcmp(spec->left->str, "default", 7) == 0) 3090 3090 emit_op(c, OP_IMPORT_DEFAULT); 3091 3091 else 3092 - emit_atom_op(c, OP_GET_FIELD, spec->left->str, spec->left->len); 3092 + emit_atom_op(c, OP_IMPORT_NAMED, spec->left->str, spec->left->len); 3093 3093 emit_atom_op(c, OP_EXPORT, spec->right->str, spec->right->len); 3094 3094 } else { 3095 3095 emit_get_var(c, spec->left->str, spec->left->len);
+6 -5
src/silver/engine.c
··· 1277 1277 L_IS_UNDEF: { sv_op_is_undef(vm); NEXT(1); } 1278 1278 L_IS_NULL: { sv_op_is_null(vm); NEXT(1); } 1279 1279 1280 - L_IMPORT: { VM_CHECK(sv_op_import(vm, js)); NEXT(1); } 1281 - L_IMPORT_SYNC: { VM_CHECK(sv_op_import_sync(vm, js)); NEXT(1); } 1282 - L_IMPORT_DEFAULT: { sv_op_import_default(vm, js); NEXT(1); } 1283 - L_EXPORT: { VM_CHECK(sv_op_export(vm, js, func, ip)); NEXT(5); } 1284 - L_EXPORT_ALL: { VM_CHECK(sv_op_export_all(vm, js)); NEXT(1); } 1280 + L_IMPORT: { VM_CHECK(sv_op_import(vm, js)); NEXT(1); } 1281 + L_IMPORT_SYNC: { VM_CHECK(sv_op_import_sync(vm, js)); NEXT(1); } 1282 + L_IMPORT_DEFAULT: { sv_op_import_default(vm, js); NEXT(1); } 1283 + L_IMPORT_NAMED: { VM_CHECK(sv_op_import_named(vm, js, func, ip)); NEXT(5); } 1284 + L_EXPORT: { VM_CHECK(sv_op_export(vm, js, func, ip)); NEXT(5); } 1285 + L_EXPORT_ALL: { VM_CHECK(sv_op_export_all(vm, js)); NEXT(1); } 1285 1286 1286 1287 L_ENTER_WITH: { VM_CHECK(sv_op_enter_with(vm, js, frame)); NEXT(1); } 1287 1288 L_EXIT_WITH: { sv_op_exit_with(vm, frame); NEXT(1); }
+64
src/silver/ops/coercion.h
··· 85 85 } 86 86 } 87 87 88 + static inline bool sv_module_namespace_has_export( 89 + ant_t *js, 90 + ant_value_t ns, 91 + const char *name, 92 + size_t len 93 + ) { 94 + if (!is_object_type(ns)) return false; 95 + 96 + ant_value_t as_obj = js_as_obj(ns); 97 + if (is_proxy(as_obj)) return false; 98 + if (lkp(js, as_obj, name, len) != 0) return true; 99 + 100 + prop_meta_t meta; 101 + return lookup_string_prop_meta(js, as_obj, name, len, &meta); 102 + } 103 + 104 + static inline const char *sv_module_namespace_filename(ant_t *js, ant_value_t ns) { 105 + if (!is_object_type(ns)) return NULL; 106 + 107 + ant_value_t module_ctx = js_get_slot(ns, SLOT_MODULE_CTX); 108 + if (!is_object_type(module_ctx)) return NULL; 109 + 110 + ant_value_t filename = js_get(js, module_ctx, "filename"); 111 + if (vtype(filename) != T_STR) return NULL; 112 + 113 + return js_getstr(js, filename, NULL); 114 + } 115 + 116 + static inline ant_value_t sv_missing_named_export_error( 117 + ant_t *js, 118 + ant_value_t ns, 119 + const char *name, 120 + size_t len 121 + ) { 122 + const char *filename = sv_module_namespace_filename(js, ns); 123 + if (!filename) filename = "<unknown>"; 124 + return js_mkerr_typed( 125 + js, JS_ERR_SYNTAX, 126 + "The requested module '%s' does not provide an export named '%.*s'", 127 + filename, (int)len, name 128 + ); 129 + } 130 + 131 + static inline ant_value_t sv_op_import_named( 132 + sv_vm_t *vm, 133 + ant_t *js, 134 + sv_func_t *func, 135 + uint8_t *ip 136 + ) { 137 + uint32_t atom_idx = sv_get_u32(ip + 1); 138 + if (atom_idx >= (uint32_t)func->atom_count) 139 + return js_mkerr(js, "invalid import atom index"); 140 + 141 + ant_value_t ns = vm->stack[vm->sp - 1]; 142 + sv_atom_t *a = &func->atoms[atom_idx]; 143 + if (!sv_module_namespace_has_export(js, ns, a->str, a->len)) 144 + return sv_missing_named_export_error(js, ns, a->str, a->len); 145 + 146 + ant_value_t value = js_get(js, ns, a->str); 147 + if (is_err(value)) return value; 148 + vm->stack[vm->sp - 1] = value; 149 + return tov(0); 150 + } 151 + 88 152 static inline ant_value_t sv_op_export(sv_vm_t *vm, ant_t *js, sv_func_t *func, uint8_t *ip) { 89 153 uint32_t atom_idx = sv_get_u32(ip + 1); 90 154 if (atom_idx >= (uint32_t)func->atom_count)
+3
tests/missing_named_export_importer.mjs
··· 1 + import { createDebug } from './missing_named_export_target.mjs'; 2 + 3 + export default createDebug;
+1
tests/missing_named_export_target.mjs
··· 1 + export const ok = true;
+22
tests/test_missing_named_export.mjs
··· 1 + function assert(condition, message) { 2 + if (!condition) throw new Error(message); 3 + } 4 + 5 + const expectedPath = import.meta.dirname + '/missing_named_export_target.mjs'; 6 + const expectedMessage = 7 + `The requested module '${expectedPath}' does not provide an export named 'createDebug'`; 8 + 9 + let caught = null; 10 + 11 + try { 12 + await import('./missing_named_export_importer.mjs'); 13 + } catch (err) { 14 + caught = err; 15 + } 16 + 17 + assert(caught, 'expected import to fail'); 18 + assert(caught.name === 'SyntaxError', `expected SyntaxError, got ${caught && caught.name}`); 19 + assert(caught.message === expectedMessage, 20 + `unexpected message:\n${caught && caught.message}\n!=\n${expectedMessage}`); 21 + 22 + console.log('missing named export test passed');