GeezerVison is showing github.com — repl: display dynamic import variant in static import error messages · nodejs/node@bbafd42
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: lib/repl.js +26-1Lines changed: 26 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -62,6 +62,7 @@ const { | 62 | 62 | Boolean, | 63 | 63 | Error, | 64 | 64 | FunctionPrototypeBind, | | 65 | + JSONStringify, | 65 | 66 | MathMaxApply, | 66 | 67 | NumberIsNaN, | 67 | 68 | NumberParseFloat, | @@ -105,7 +106,9 @@ const { | 105 | 106 | const { | 106 | 107 | isIdentifierStart, | 107 | 108 | isIdentifierChar, | | 109 | + parse: acornParse, | 108 | 110 | } = require('internal/deps/acorn/acorn/dist/acorn'); | | 111 | +const acornWalk = require('internal/deps/acorn/acorn-walk/dist/walk'); | 109 | 112 | const { | 110 | 113 | decorateErrorStack, | 111 | 114 | isError, | @@ -225,6 +228,28 @@ module.paths = CJSModule._nodeModulePaths(module.filename); | 225 | 228 | const writer = (obj) => inspect(obj, writer.options); | 226 | 229 | writer.options = { ...inspect.defaultOptions, showProxy: true }; | 227 | 230 |
| | 231 | +// Converts static import statement to dynamic import statement | | 232 | +const toDynamicImport = (codeLine) => { | | 233 | + let dynamicImportStatement = ''; | | 234 | + const ast = acornParse(codeLine, { __proto__: null, sourceType: 'module', ecmaVersion: 'latest' }); | | 235 | + acornWalk.ancestor(ast, { | | 236 | + ImportDeclaration(node) { | | 237 | + const awaitDynamicImport = `await import(${JSONStringify(node.source.value)});`; | | 238 | + if (node.specifiers.length === 0) { | | 239 | + dynamicImportStatement += awaitDynamicImport; | | 240 | + } else if (node.specifiers.length === 1 && node.specifiers[0].type === 'ImportNamespaceSpecifier') { | | 241 | + dynamicImportStatement += `const ${node.specifiers[0].local.name} = ${awaitDynamicImport}`; | | 242 | + } else { | | 243 | + const importNames = ArrayPrototypeJoin(ArrayPrototypeMap(node.specifiers, ({ local, imported }) => | | 244 | + (local.name === imported?.name ? local.name : `${imported?.name ?? 'default'}: ${local.name}`), | | 245 | + ), ', '); | | 246 | + dynamicImportStatement += `const { ${importNames} } = ${awaitDynamicImport}`; | | 247 | + } | | 248 | + }, | | 249 | + }); | | 250 | + return dynamicImportStatement; | | 251 | +}; | | 252 | + | 228 | 253 | function REPLServer(prompt, | 229 | 254 | stream, | 230 | 255 | eval_, | @@ -686,7 +711,7 @@ function REPLServer(prompt, | 686 | 711 | 'module'; | 687 | 712 | if (StringPrototypeIncludes(e.message, importErrorStr)) { | 688 | 713 | e.message = 'Cannot use import statement inside the Node.js ' + | 689 | | - 'REPL, alternatively use dynamic import'; | | 714 | + 'REPL, alternatively use dynamic import: ' + toDynamicImport(self.lines.at(-1)); | 690 | 715 | e.stack = SideEffectFreeRegExpPrototypeSymbolReplace( | 691 | 716 | /SyntaxError:.*\n/, | 692 | 717 | e.stack, | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-repl.js +68-1Lines changed: 68 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -817,7 +817,74 @@ const tcpTests = [ | 817 | 817 | kArrow, | 818 | 818 | '', | 819 | 819 | 'Uncaught:', | 820 | | - /^SyntaxError: .* dynamic import/, | | 820 | + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ | | 821 | +alternatively use dynamic import: const { default: comeOn } = await import("fhqwhgads");', | | 822 | + ] | | 823 | + }, | | 824 | + { | | 825 | + send: 'import { export1, export2 } from "module-name"', | | 826 | + expect: [ | | 827 | + kSource, | | 828 | + kArrow, | | 829 | + '', | | 830 | + 'Uncaught:', | | 831 | + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ | | 832 | +alternatively use dynamic import: const { export1, export2 } = await import("module-name");', | | 833 | + ] | | 834 | + }, | | 835 | + { | | 836 | + send: 'import * as name from "module-name";', | | 837 | + expect: [ | | 838 | + kSource, | | 839 | + kArrow, | | 840 | + '', | | 841 | + 'Uncaught:', | | 842 | + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ | | 843 | +alternatively use dynamic import: const name = await import("module-name");', | | 844 | + ] | | 845 | + }, | | 846 | + { | | 847 | + send: 'import "module-name";', | | 848 | + expect: [ | | 849 | + kSource, | | 850 | + kArrow, | | 851 | + '', | | 852 | + 'Uncaught:', | | 853 | + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ | | 854 | +alternatively use dynamic import: await import("module-name");', | | 855 | + ] | | 856 | + }, | | 857 | + { | | 858 | + send: 'import { export1 as localName1, export2 } from "bar";', | | 859 | + expect: [ | | 860 | + kSource, | | 861 | + kArrow, | | 862 | + '', | | 863 | + 'Uncaught:', | | 864 | + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ | | 865 | +alternatively use dynamic import: const { export1: localName1, export2 } = await import("bar");', | | 866 | + ] | | 867 | + }, | | 868 | + { | | 869 | + send: 'import alias from "bar";', | | 870 | + expect: [ | | 871 | + kSource, | | 872 | + kArrow, | | 873 | + '', | | 874 | + 'Uncaught:', | | 875 | + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ | | 876 | +alternatively use dynamic import: const { default: alias } = await import("bar");', | | 877 | + ] | | 878 | + }, | | 879 | + { | | 880 | + send: 'import alias, {namedExport} from "bar";', | | 881 | + expect: [ | | 882 | + kSource, | | 883 | + kArrow, | | 884 | + '', | | 885 | + 'Uncaught:', | | 886 | + 'SyntaxError: Cannot use import statement inside the Node.js REPL, \ | | 887 | +alternatively use dynamic import: const { default: alias, namedExport } = await import("bar");', | 821 | 888 | ] | 822 | 889 | }, | 823 | 890 | ]; | |
|