diff --git a/src/ast_utils.js b/src/ast_utils.js index c394a1f..017cf82 100644 --- a/src/ast_utils.js +++ b/src/ast_utils.js @@ -41,9 +41,17 @@ export const map_destructuring_identifiers = (node, mapper) => { } export const collect_imports = module => { - const imports = module.stmts - .filter(n => n.type == 'import') - .filter(n => !n.is_external) + const import_statements = + module.stmts + .filter(n => n.type == 'import') + .filter(n => !n.is_external) + + const imported_modules = uniq( + import_statements.map(n => n.full_import_path) + ) + + const imports = + import_statements .map(n => n.imports.map(i => ({name: i.value, module: n.full_import_path}) @@ -51,8 +59,7 @@ export const collect_imports = module => { ) .flat() - const modules = uniq(imports.map(i => i.module)) - const by_module = Object.fromEntries(modules.map(m => + const by_module = Object.fromEntries(imported_modules.map(m => [ m, imports @@ -60,6 +67,7 @@ export const collect_imports = module => { .map(i => i.name) ] )) + return by_module } diff --git a/src/eval.js b/src/eval.js index 907fe75..8a1b9ad 100644 --- a/src/eval.js +++ b/src/eval.js @@ -240,7 +240,11 @@ const codegen = (node, cxt, parent) => { return do_codegen(node.key) + ' : ' + do_codegen(node.value); } else if(node.type == 'import') { const names = node.imports.map(n => n.value) - return `const {${names.join(',')}} = __modules['${node.full_import_path}'];`; + if(names.length == 0) { + return '' + } else { + return `const {${names.join(',')}} = __modules['${node.full_import_path}'];`; + } } else if(node.type == 'export') { const identifiers = collect_destructuring_identifiers(node.binding.name_node) .map(i => i.value) diff --git a/src/parse_js.js b/src/parse_js.js index 9c39250..fd82b57 100644 --- a/src/parse_js.js +++ b/src/parse_js.js @@ -1178,16 +1178,20 @@ const import_statement = optional(by_type('pragma_external')), seq([ literal('import'), - list( - ['{', '}'], - identifier, + optional( + seq([ + list( + ['{', '}'], + identifier, + ), + literal('from'), + ]) ), - literal('from'), string_literal ]) ]), ({value: [external, imp]}) => { - const {value: [_import, identifiers, _from, module], ...node} = imp + const {value: [_import, identifiers, module], ...node} = imp return { ...node, not_evaluatable: true, @@ -1196,7 +1200,7 @@ const import_statement = // TODO refactor hanlding of string literals. Drop quotes from value and // fix codegen for string_literal module: module.value.slice(1, module.value.length - 1), - children: identifiers.value, + children: identifiers == null ? [] : identifiers.value[0].value, } } ) diff --git a/test/test.js b/test/test.js index 3cdcc8a..524cea8 100644 --- a/test/test.js +++ b/test/test.js @@ -786,6 +786,24 @@ export const tests = [ assert_equal(mods.root.is_eq, true) }), + test('modules empty import', () => { + const i = test_initial_state({ + '': 'import {} from "a"', + 'a': 'Object.assign(globalThis, {test_import: true})', + }) + assert_equal(i.active_calltree_node.ok, true) + assert_equal(globalThis.test_import, true) + }), + + test('modules bare import', () => { + const i = test_initial_state({ + '': 'import "a"', + 'a': 'Object.assign(globalThis, {test_import: true})', + }) + assert_equal(i.active_calltree_node.ok, true) + assert_equal(globalThis.test_import, true) + }), + test('bug parser pragma external', () => { const result = parse(` // external