scala-js / scala-js-env-jsdom-nodejs

Node.js with jsdom environment for Scala.js
BSD 3-Clause "New" or "Revised" License
8 stars 10 forks source link

ReferenceError: require is not defined #44

Open japgolly opened 4 years ago

japgolly commented 4 years ago

I've got this in my SBT:

jsEnv := new JSDOMNodeJSEnv(JSDOMNodeJSEnv.Config().withArgs("--experimental-worker" :: Nil)),
jsDependencies ++= Seq(
  (ProvidedJS / "polyfill.js" dependsOn ReactDom.dev) % Test),

and this src/test/resources/polyfill.js:

window.MessageChannel = require('worker_threads').MessageChannel;
window.scrollTo = function(){}

When I run my tests I get this error:

ReferenceError: require is not defined
ReferenceError: require is not defined
    at file:///home/golly/projects/public/scalajs-react/test/target/scala-2.13/test-classes/polyfill.js:1:1
    at Script.runInContext (vm.js:142:20)
    at Object.runInContext (vm.js:281:6)
    at processJavaScript (/home/golly/.npm/lib/node_modules/jsdom/lib/jsdom/living/nodes/HTMLScriptElement-impl.js:241:10)
    at HTMLScriptElementImpl._innerEval (/home/golly/.npm/lib/node_modules/jsdom/lib/jsdom/living/nodes/HTMLScriptElement-impl.js:176:5)
    at onLoadExternalScript (/home/golly/.npm/lib/node_modules/jsdom/lib/jsdom/living/nodes/HTMLScriptElement-impl.js:98:12)
    at onLoadWrapped (/home/golly/.npm/lib/node_modules/jsdom/lib/jsdom/browser/resources/per-document-resource-loader.js:53:33)
    at Object.check (/home/golly/.npm/lib/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:76:23)
    at /home/golly/.npm/lib/node_modules/jsdom/lib/jsdom/browser/resources/resource-queue.js:83:27
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

The polyfill.js is being executed by Node so using require() should work, no?

japgolly commented 4 years ago

This doesn't work either:

org.scalajs.dom.window.asInstanceOf[js.Dynamic].MessageChannel =
  js.Dynamic.global.require("worker_threads").MessageChannel

Isn't require() always available in Node?

sjrd commented 4 years ago

jsdom is not Node.js. jsdom goes out of its way to expose a browser-like environment within Node.js, so it hides things like require. This is by design.

japgolly commented 4 years ago

Wait, jsdom hides require??! (Off to the jsdom doc....)

japgolly commented 4 years ago

I can't find anything in the jsdom code that attempts to remove or replace require. Are you sure? Where'd you see that?

sjrd commented 4 years ago

The vm.runInContext in HTMLScriptElement-impl.js (in your stack trace) does that.

japgolly commented 4 years ago

Thanks, I created an elaborate regex over require to search. I never would've come across this. I'll look into it but seeing as you already have at some point, do you know of a means to disable that particular aspect of jsdom?

sjrd commented 4 years ago

You can't disable the hiding mechanism, but you can explicitly reintroduce things inside the window. You need to tweak the code using the jsdom API, though.

This fork does precisely that.

japgolly commented 4 years ago

Ah ok cool. Can we merge it into this main repo? Maybe behind a flag if you're cautious?

sjrd commented 4 years ago

IMO it does not fit the philosophy of this repo. With this repo, we are trying to expose a browser-like environment more than a Node.js environment. If we start exposing require, even under a flag, how many other things will we have to expose?

The beauty of open source is that not everyone has to agree with the philosophy. It's very good that one can just create a fork with another philosophy and publish it, and people can use it.

japgolly commented 4 years ago

This repo doesn't say anything about the browser though, and why should it, especially now that it's been decoupled from Scala.JS itself? After all it's JSDOMNodeJSEnv, not JSDOMNodeJSBrowserEnv :grinning:

Jokes aside though, what other aspects of a browser-like environment is this repo applying if any? Or maybe phrased another way, providing access to Node JS is the purpose of this library right? Why would the philosophy go beyond that and be opinionated if it doesn't have to. It think it's very reasonable to anyone who comes knocking on this library's door (and they will over forks and other OSS that you suggested because of that big shiny "org.scala-js" groupId), it's reasonable that they are going to assume that they have access to an unconstrained Node JS env.

sjrd commented 4 years ago

Perhaps the name of the env is inaccurate, but it has always been about providing a reliable headless-browser-like environment. The fact that it uses jsdom on Node.js to do so is the strategy more than a public contract.

and they will over forks and other OSS that you suggested because of that big shiny "org.scala-js" groupId

I'm happy to add a note in the readme that people who want require should use the fork I mentioned above, if that helps.