diff --git a/src/ast_utils.js b/src/ast_utils.js index c15ca97..c394a1f 100644 --- a/src/ast_utils.js +++ b/src/ast_utils.js @@ -63,6 +63,16 @@ export const collect_imports = module => { return by_module } +export const collect_external_imports = modules => + Object + .entries(modules) + .map(([module_name, node]) => + node + .children + .filter(c => c.type == 'import' && c.is_external) + .map(node => ({node, module_name})) + ) + .flat() export const find_leaf = (node, index) => { if(!(node.index <= index && node.index + node.length > index)){ diff --git a/src/cmd.js b/src/cmd.js index 4553c06..6bc4805 100644 --- a/src/cmd.js +++ b/src/cmd.js @@ -2,7 +2,8 @@ import {map_object, pick_keys, collect_nodes_with_parents, uniq} from './utils.js' import { is_eq, is_child, ancestry, ancestry_inc, map_tree, - find_leaf, find_fn_by_location, find_node, find_error_origin_node + find_leaf, find_fn_by_location, find_node, find_error_origin_node, + collect_external_imports } from './ast_utils.js' import {load_modules} from './parse_js.js' import {find_export} from './find_definitions.js' @@ -90,19 +91,9 @@ const run_code = (s, index, dirty_files) => { return state } - const external_import_nodes = - Object - .entries(state.parse_result.modules) - .map(([module_name, node]) => - node - .children - .filter(c => c.type == 'import' && c.is_external) - .map(node => ({node, module_name})) - ) - .flat() - const external_imports = uniq( - external_import_nodes.map(i => i.node.full_import_path) + collect_external_imports(state.parse_result.modules) + .map(i => i.node.full_import_path) ) if( @@ -118,7 +109,6 @@ const run_code = (s, index, dirty_files) => { loading_external_imports_state: { index, external_imports, - external_import_nodes, } } } else { @@ -155,9 +145,7 @@ const do_external_imports_loaded = ( .map(([url, result]) => url) ) if(errors.size != 0) { - const problems = state - .loading_external_imports_state - .external_import_nodes + const problems = collect_external_imports(state.parse_result.modules) .filter(({node}) => errors.has(node.full_import_path)) .map(({node, module_name}) => ({ index: node.index, diff --git a/test/test.js b/test/test.js index 9766d5d..9fe936c 100644 --- a/test/test.js +++ b/test/test.js @@ -907,6 +907,50 @@ export const tests = [ assert_equal(embed.args[0].result.value, 'foo_value') }), + test('module external cache error bug', () => { + const code = ` + // external + import {foo_var} from 'foo.js' + console.log(foo_var) + ` + const initial = test_initial_state(code) + + // simulate module load error + const next = COMMANDS.external_imports_loaded(initial, initial, { + 'foo.js': { + ok: false, + error: new Error('Failed to resolve module'), + } + }) + + const edited = ` + // external + import {foo_var} from 'foo.js' + // edit + console.log(foo_var) + ` + + // edit code + const {state, effects} = COMMANDS.input( + next, + edited, + edited.lastIndexOf('foo_var'), + ) + + // Error must preserve after error + assert_equal(next.parse_result.ok, false) + assert_equal( + next.parse_result.problems, + [ + { + index: code.indexOf('import'), + message: 'Failed to resolve module', + module: '', + } + ] + ) + }), + // Static analysis test('undeclared', () => { @@ -2227,7 +2271,7 @@ const y = x()` ) }), - test_only('async calls', () => { + test('async calls', () => { const code = ` const fn = () => { }