Commit
fd54d52d freed all bytecode added after the parent module's
compilation checkpoint, including successfully compiled dependencies.
Those dependencies remain cached, so a later import in the same VM
executes freed bytecode. This is reachable in the interactive shell
and in embedders that continue after a compilation error.
The fix is to remove eager bytecode cleanup while retaining removal of
the failed module from the cache so subsequent loads can retry. Keep
the removed module and its name in the VM pool because cyclic
dependencies and code metadata can still reference them. These
allocations are released when the VM is destroyed.
Add a shell regression test that retries a failed parent import and then
executes its cached dependency.
}
-void
-njs_generator_cleanup(njs_vm_t *vm, njs_uint_t code_index)
-{
- njs_vm_code_t *code;
-
- if (vm->codes == NULL) {
- return;
- }
-
- while (vm->codes->items > code_index) {
- code = njs_arr_remove_last(vm->codes);
-
- if (code->start != NULL) {
- njs_mp_free(vm->mem_pool, code->start);
- }
-
- if (code->lines != NULL) {
- njs_arr_destroy(code->lines);
- }
- }
-}
-
-
static njs_int_t
njs_generate_scope_end(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_node_t *node)
njs_str_t *file, njs_int_t depth, njs_bool_t runtime);
njs_vm_code_t *njs_generate_scope(njs_vm_t *vm, njs_generator_t *generator,
njs_parser_scope_t *scope, const njs_str_t *name);
-void njs_generator_cleanup(njs_vm_t *vm, njs_uint_t code_index);
njs_vm_code_t *njs_lookup_code(njs_vm_t *vm, u_char *pc);
uint32_t njs_lookup_line(njs_arr_t *lines, uint32_t offset);
(void) njs_flathsh_delete(&vm->shared->modules_hash, &fhq);
- njs_mp_free(vm->mem_pool, module->name.start);
- njs_mp_free(vm->mem_pool, module);
+ /* Compiled dependencies may still reference this module and its name. */
}
u_char *end)
{
njs_int_t ret;
- njs_uint_t code_index;
njs_mod_t *module;
njs_parser_t parser;
njs_vm_code_t *code;
njs_function_lambda_t *lambda;
parser.mem_pool = NULL;
- code_index = (vm->codes != NULL) ? vm->codes->items : 0;
module = njs_module_find(vm, name, 1);
if (module != NULL) {
njs_parser_destroy(&parser);
}
- njs_generator_cleanup(vm, code_index);
njs_module_remove(vm, module);
return NULL;
--- /dev/null
+import name from './name.js';
+export default name;
+@
{"42\r\n" "42\r\n>> " "unhandled promise rejection"}
}
+njs_test {
+ {"import broken from './test/js/module/compile_exception.js';\r\n"
+ "SyntaxError:*\r\n*>> "}
+ {"import broken from './test/js/module/compile_exception.js';\r\n"
+ "SyntaxError:*\r\n*>> "}
+ {"import name from './test/js/module/name.js'; name;\r\n"
+ "'name'\r\n>> "}
+} "-n njs"
+
# CLI OPTIONS
# help