vercel / ncc

Compile a Node.js project into a single file. Supports TypeScript, binary addons, dynamic requires.
https://npmjs.com/@vercel/ncc
MIT License
9.27k stars 291 forks source link

Error using XMLSerializer from jsdom / jsdom-global #592

Open shaunco opened 4 years ago

shaunco commented 4 years ago

I have attached jsdom-ncc-issue.zip which reduces this issue to the smallest amount of code I could reproduce this in.

If you run:

npm install
npm run build
node ./build/server.js

and then visit http://localhost:8080 you will get a simple blue SVG square with a green outline.

If you run:

npm install
npm run package
node ./dist/index.js

and then visit http://localhost:8080, you will get

Example app listening at http://localhost:8080
(node:58932) UnhandledPromiseRejectionWarning: TypeError: Object prototype may only be an Object or null: undefined
    at Function.create (<anonymous>)
    at new XMLSerializer (R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\jsdom\lib\jsdom\living\generated\XMLSerializer.js:90:1)
    at R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\src\server.ts:34:1
    at Layer.handle [as handle_request] (R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\express\lib\router\layer.js:95:1)
    at next (R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\express\lib\router\route.js:137:1)
    at Route.dispatch (R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\express\lib\router\route.js:112:1)
    at Layer.handle [as handle_request] (R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\express\lib\router\layer.js:95:1)
    at R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\express\lib\router\index.js:281:1
    at Function.process_params (R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\express\lib\router\index.js:335:1)
    at next (R:\dev\jsdom-ncc-issue\webpack:\jsdom-ncc-issue\node_modules\express\lib\router\index.js:275:1)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:58932) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

NCC seems to be changing jsdom in some way which breaks XMLSerializer. I haven't been able to dig deep enough to provide any additional insight, but the sample project should at least make the issue reproducible.

shaunco commented 4 years ago

Looks like ncc transpiled:

  class XMLSerializer {
    constructor() {
      return exports.setup(Object.create(new.target.prototype), globalObject, undefined);
    }

In to:

  class XMLSerializer {
    constructor() {
      return exports.setup(Object.create(/* unsupported import.meta.prototype */ undefined), globalObject, undefined);
    }

Along with about 40 other spots in jsdom that ended up with /* unsupported import.meta.prototype */ undefined.

shaunco commented 4 years ago

Turns out it is the ImportMetaPlugin for WebPack that produced this: https://github.com/webpack/webpack/blob/8295202bc86b45b791c28215703f7ce4e2eac370/lib/dependencies/ImportMetaPlugin.js#L147

Is there any hope of fixing this on the NCC side, or should I report this issue against webpack?

shaunco commented 4 years ago

I tried using webpack's new "external" flag that was added to work around similar issues with canvas and jsdom:

const path = require("path");
module.exports = {
    target: "node",
    externals: {
        jsdom: "commonjs jsdom"
    }
};

But it looks like ncc ignores the webpack.config.js (I tried purposely making it invalid and ncc still completes without error).

No luck via the node-loader route either.

sisp commented 4 years ago

I have the same problem when using the Vercel CLI (vercel dev). When a Lambda function throws an exception, the stack trace is not shown because

Object.setPrototypeOf(this, new.target.prototype);

(github.com/vercel/fun/src/errors.ts#L15) is transpiled incorrectly to

Object.setPrototypeOf(this, /* unsupported import.meta.prototype */ undefined);

which prevents the stack trace from being printed in the terminal.

Sumolari commented 4 years ago

I'm experiencing the same thing with errors from simple-git