n-riesco / ijavascript

IJavascript is a javascript kernel for the Jupyter notebook
Other
2.18k stars 187 forks source link

Error using `import` #210

Open QGB opened 4 years ago

QGB commented 4 years ago
import defaultExport from  "/root/hs-airdrop/bin/hs-airdrop"
       ^^^^^^^^^^^^^

SyntaxError: Unexpected identifier
    at new Script (vm.js:83:7)
    at createScript (vm.js:277:10)
    at Object.runInThisContext (vm.js:329:10)
    at run ([eval]:1054:15)
    at onRunRequest ([eval]:888:18)
    at onMessage ([eval]:848:13)
    at process.emit (events.js:198:13)
    at emit (internal/child_process.js:832:12)
    at process._tickCallback (internal/process/next_tick.js:63:19)
n-riesco commented 4 years ago

Your experience with ES6 modules depends on your Node version.

I've just tested the REPL in the current version (v13.9.0) and this is the error Node throws:

$ node -e "import defaultExport from './test.mjs'"
[eval]:1
import defaultExport from './test.mjs'
^^^^^^

SyntaxError: Cannot use import statement outside a module
    at new Script (vm.js:88:7)
    at createScript (vm.js:263:10)
    at Object.runInThisContext (vm.js:311:10)
    at Object.<anonymous> ([eval]-wrapper:10:26)
    at Module._compile (internal/modules/cjs/loader.js:1151:30)
    at evalScript (internal/process/execution.js:94:25)
    at internal/main/eval_string.js:23:3

And for example, I'm able to reproduce the error message you get, using Node v10:

$ node --experimental-modules -e "import defaultExport from './test.mjs'"
[eval]:1
import defaultExport from './test.mjs'
       ^^^^^^^^^^^^^

SyntaxError: Unexpected identifier
    at new Script (vm.js:79:7)
    at createScript (vm.js:251:10)
    at Proxy.runInThisContext (vm.js:303:10)
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (internal/modules/cjs/loader.js:689:30)
    at evalScript (internal/bootstrap/node.js:587:27)
    at startup (internal/bootstrap/node.js:265:9)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:743:3)
radamson commented 3 years ago

I've looked through this issue and some of the related ones, but I wasn't able to find a solution for this.

Is enabling ECMAScript modules supported by ijavascript for use in Jupyter Notebooks? I tried setting type in package.json and also using NODE_OPTIONS=-r esm, but no dice.

n-riesco commented 3 years ago

Last time I checked (node.js v14.13.0), the REPL doesn't support this use yet. It fails with:

$ node
Welcome to Node.js v14.13.0.
Type ".help" for more information.
> import test from ".";
import test from ".";
^^^^^^

Uncaught:
SyntaxError: Cannot use import statement inside the Node.js REPL, alternatively use dynamic import
> 
n-riesco commented 3 years ago

Re esm, unfortunately esm doesn't work on vm. See https://github.com/n-riesco/ijavascript/issues/215#issuecomment-678268578

I haven't seen any activity in https://github.com/standard-things/esm/issues/886 ,

n-riesco commented 3 years ago

The issue is not related to the extension used for a module. I wouldn't expect the use of type to help.

n-riesco commented 3 years ago

From #239, alternatives to a static import:

prothSFDC commented 2 years ago

Hi @n-riesco - Might you have any thoughts on what the status of this is? (It seems like the only workaround I've found is by importing older cjs module versions, instead of the newer ones)

I've tried using the suggestions provided above (like from 239, or the related ones that mentions)

Might you have any other thoughts we could try?

n-riesco commented 2 years ago

Hi @prothSFDC

I'm sorry it took me so long to come back to you. It's been hard to find chunks of time long enough to look into this.

These are the options I've looked into so far:

  1. top level ES modules supported by the CLI: judging by https://github.com/nodejs/node/issues/39353 this is an ongoing discussion.
  2. use of esm: not working in vm.runInThisContext, no feedback from https://github.com/standard-things/esm/issues/886 and no development since September 2019.
  3. use of --input-type=module: I've tried this approach, but it has 2 major issues:
    • require is undefined,
    • and, as with esm, the flag doesn't work with code run in vm.runInThisContext.
  4. use of dynamic imports: again, not working in vm.runInThisContext.
  5. use a parser: this is what we do in ijavascript-await, and essentially what esm does.

I've opened https://github.com/nodejs/node/issues/40898 with nodejs re vm.runInThisContext, but I reckon it has to be fixed at V8 first.

I'm not familiar with esm, but I had a quick look through their code. The solution could be as simple as adding vmHook to our case (i.e. running with node --eval).

disarticulate commented 2 years ago

check out:

Name: Node.js Notebooks (REPL) Id: donjayamanne.typescript-notebook Description: Iterative & interactive programming for Node.js in JavaScript/TypeScript (REPL), with great support for Tensorflow.js, debugging, & more.. Version: 2.0.6 Publisher: Don Jayamanne VS Marketplace Link: https://marketplace.visualstudio.com/items?itemName=donjayamanne.typescript-notebook

https://github.com/DonJayamanne/typescript-notebook

It appears to be using runInNewContext and can do imports

jpshackelford commented 1 year ago

For the time being I am using https://github.com/DonJayamanne/typescript-notebook (very well done) but I would prefer to use Jupyter as I would like to share notebooks with non-developers who aren't running vs-code. Without import I am not sure how I would use the redis npm which my project depends on. If I've missed a work-around please let me know. Otherwise, I'll be watching this space.

n-riesco commented 1 year ago

@disarticulate apologies for the late reply (somehow I missed your message).

I had a look at ts-node (I imagine the same results apply to typescript-notebook). ts-node uses esbuild to transpile import statements into require calls. This means ts-node fails to import ES modules (for the same reason iJavaScript does). See:

# ts-node
> import d3 from "d3"
undefined
> d3
node:internal/modules/cjs/loader:1210
      throw err;
      ^

Uncaught:
Error [ERR_REQUIRE_ESM]: require() of ES Module /usr/local/lib/node_modules/d3/src/index.js not supported.
Instead change the require of index.js in null to a dynamic import() which is available in all CommonJS modules.
    at require.extensions.<computed> [as .js] (/usr/local/lib/node_modules/ts-node/dist/index.js:851:20)
    at /usr/local/lib/<repl>.ts:1:30
    at Script.runInThisContext (node:vm:129:12)
    at runInContext (/usr/local/lib/node_modules/ts-node/dist/repl.js:466:23)
    at Object.execCommand (/usr/local/lib/node_modules/ts-node/dist/repl.js:434:36)
    at /usr/local/lib/node_modules/ts-node/dist/repl.js:456:48
    at Array.reduce (<anonymous>)
    at appendCompileAndEvalInput (/usr/local/lib/node_modules/ts-node/dist/repl.js:456:29)
    at evalCodeInternal (/usr/local/lib/node_modules/ts-node/dist/repl.js:117:16)
    at REPLServer.nodeEval (/usr/local/lib/node_modules/ts-node/dist/repl.js:132:32)
    at bound (node:domain:433:15)
    at REPLServer.runBound [as eval] (node:domain:444:12)
    at REPLServer.onLine (node:repl:902:10)
    at REPLServer.emit (node:events:525:35)
    at REPLServer.emit (node:domain:489:12)
    at REPLServer.self._ttyWrite (node:repl:997:9)
    at ReadStream.emit (node:events:513:28)
    at ReadStream.emit (node:domain:489:12)
    at emitKeys.next (<anonymous>)
    at ReadStream.emit (node:events:513:28)
    at ReadStream.emit (node:domain:489:12) {
  code: 'ERR_REQUIRE_ESM'
}

BTW, the reason iJavasScript is using runInThisContext is because the node REPL makes some of the node.js API available in the global context without the need for require.

n-riesco commented 1 year ago

For those interested in using ES modules in iJavaScript: I've been able to do so using esm-hook and a recent version of node.js (failed with v12, worked with v18):

# cat test.mjs
const test = "test";
export default test;

# node
Welcome to Node.js v18.12.1.
Type ".help" for more information.
> require("esm-hook")
[Function (anonymous)]
> var test1 = require("./test.mjs").default; test1
'test'
> vm.runInThisContext("var test2 = require('./test.mjs').default; test2")
'test'
n-riesco commented 5 months ago

Flag --experimental-require-module (see https://github.com/nodejs/node/pull/51977 ).