oracle / graaljs

GraalJS – A high-performance, ECMAScript compliant, and embeddable JavaScript runtime for Java
https://www.graalvm.org/javascript/
Universal Permissive License v1.0
1.82k stars 192 forks source link

graalvm-nodejs npm global root directory missing (or wrong?) #247

Open slippycheeze opened 4 years ago

slippycheeze commented 4 years ago
] npm root --global
/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.0.0/Contents/Home/languages/js/lib/node_modules

The Home/languages/js/lib directory does not exist, which causes any npm global operation to fail because it can't read that directory. Obviously any operation beyond that is also going to fail.

Why: global npm modules can be useful for various tools (eg: remark and friends) that are used outside of nodejs software development, etc. Alternatives to global installations exist, and are definitely better in many ways.

That said, if GraalVM NodeJS deliberately doesn't support global installation it should handle that in a more robust way. (eg: intercept the --global flag, refuse to run with a clear, obvious statement that this isn't supported.)

Trivial reproduction:

] npm outdated --global

That should run fine, and report nothing (in general), but fails with the error below. You can obviously also reproduce with any other mutating global npm operation.

Version info:

] which node
/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.0.0/Contents/Home/bin/node
] node --version
v12.15.0
] java --version
openjdk 11.0.6 2020-01-14
OpenJDK Runtime Environment GraalVM CE 20.0.0 (build 11.0.6+9-jvmci-20.0-b02)
OpenJDK 64-Bit Server VM GraalVM CE 20.0.0 (build 11.0.6+9-jvmci-20.0-b02, mixed mode, sharing)

Error:

] npm root -g
/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.0.0/Contents/Home/languages/js/lib/node_modules
] npm outdated -g
npm ERR! code ENOENT
npm ERR! syscall lstat
npm ERR! path /Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.0.0/Contents/Home/languages/js/lib
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, lstat '/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.0.0/Contents/Home/languages/js/lib'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/slippycheeze/.npm/_logs/2020-02-19T16_28_02_364Z-debug.log
wirthi commented 4 years ago

Hi @slippycheeze

thanks for your report. All the commands you report work fine for me, on Linux. I can globally install npm modules without problems (I regularly do, e.g. jsvu).

I see you are on MacOS. I'll check with our engineers what could be the problem there. Have you tried setting the --nodedir argument?

Thanks, Christian

marfier commented 4 years ago

I'm also having the same issue. Global packages (installed using npm install -g) are not linked to $PATH in graalvm-nodejs.

wirthi commented 4 years ago

I'm also having the same issue. Global packages (installed using npm install -g) are not linked to $PATH in graalvm-nodejs.

GraalVM usually does not put itself on the path. I usually put /path/to/graalvm/bin and /path/to/graalvm/jre/languages/js/bin on my path. The second one should resolve the issue with global packages. (actual paths might be different on MacOS, please double-check).

slippycheeze commented 3 years ago

Sorry for the delayed response. I still see this error on macOS with a clean install, but once I install a global module it goes away. So, seems like the issue is that the directory is not created until a global install has been done. Afterwards it works as expected.

So, not the problem I thought, just a problem with the sequence of operations I was using. I found this adding automation for checking outdated upstream nodejs modules in global install, so the error did break that, but I can probably work around it.

It'd be nice if this was resolved, so it didn't fail before the first global install, but certainly not critical.

] java --version
openjdk 11.0.9 2020-10-20
OpenJDK Runtime Environment GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06)
OpenJDK 64-Bit Server VM GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06, mixed mode, sharing)
] node --version
v12.18.4
] sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H15
wirthi commented 3 years ago

Hi @slippycheeze

ok, I now see your point. The directory is not created automatically by GraalVM; it is however created once needed, i.e. when you install something globally. Thus, we never see anything fail (meaning: we don't have any failing tests, as installing globally in a fresh GraalVM installation will work).

Is there any actual failing behavior you can reproduce from the npm or node side? I mean, obviously you can write a script that cds into the not-yet-existing directory and fails by that, but will npm itself ever fail? My assumption is that it always creates that directory on demand. If that is the case, I don't think we would want to change our current behavior.

-- Christian

slippycheeze commented 3 years ago

Oh, my! I'm so sorry, I apparently had an attack of foolish user (🙀 ☠️ 👻), and never included the command that actually failed with a clean install, npm outdated --global. With a clean install of nodejs native that works fine, since the global lib dir is created. The graalvm version falls over because npm outdated doesn't create the directory.

npm install does auto-create the directory, as noted. I'm not sure why npm outdated falls over, and now I think about it, that is probably an upstream bug, so I'll send them ... https://github.com/npm/cli/issues/2219

Again, I'm so sorry I didn't include the actual error in the report. I don't know why I didn't do it in the first place, and then just assumed I had done that until you asked.

Anyway, the relevant output, produced with a clean install of graalvm using your own tap:

] npm outdated --global
npm ERR! code ENOENT
npm ERR! syscall lstat
npm ERR! path /Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.3.0/Contents/Home/languages/js/lib
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, lstat '/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.3.0/Contents/Home/languages/js/lib'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/dpittman/.npm/_logs/2020-11-21T11_30_46_197Z-debug.log
npm outdated --global  6.89s user 0.84s system 283% cpu 2.726 total

and, for reference, the full set of commands I ran to reproduce this now, including verifying that the right npm binary was picked up, there was no leftover content, etc.

] brew cask zap graalvm/tap/graalvm-ce-java11
# output elided

] ls /Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.3.0/Contents/Home
ls: /Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.3.0/Contents/Home: No such file or directory

] brew cask install graalvm/tap/graalvm-ce-java11
# output elided

] export JAVA_HOME=$(/usr/libexec/java_home -v 11.0.9) ; echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.3.0/Contents/Home

] hash -r ; type npm
npm is /Library/Java/JavaVirtualMachines/graalvm-ce-java11-20.3.0/Contents/Home/bin/npm

] npm --version ; node --version ; java --version
6.14.6
v12.18.4
openjdk 11.0.9 2020-10-20
OpenJDK Runtime Environment GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06)
OpenJDK 64-Bit Server VM GraalVM CE 20.3.0 (build 11.0.9+10-jvmci-20.3-b06, mixed mode, sharing)
wirthi commented 3 years ago

Hi @slippycheeze

oh, thanks, I missed the outdated, only tried with npm root or installing a global package. I don't think we have npm outdated in our test scripts.

Will check what we can do here. (internally tracked as GR-27632)

-- Christian