Skip to content

[Bug]: The experimental ES modules support breaks when using it with some native addons that reexports the native addon module itself, such as isolated-vm #14156

@JCMais

Description

@JCMais

Version

29.5.0

Steps to reproduce

  1. Clone https://github.com/JCMais/jest-issue-native-addons
  2. Run: pnpm/npm install
  3. Run: pnpm test esBug
  4. Notice the error in the output:
❯ pnpm test esBug

> jest-issue-native-addons@1.0.0 test /home/jcm/projects/opensource/jest-issue-native-addons
> NODE_OPTIONS=--experimental-vm-modules pnpm jest --verbose "esBug"

 FAIL  ./esBug.test.ts
  ● Test suite failed to run

    Unexpected closing bracket.
      at @:1:61

      at @:1:61
          at Array.forEach (<anonymous>)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.399 s
Ran all test suites matching /esBug/i.
(node:19378) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
 ELIFECYCLE  Test failed. See above for more details.

In our codebase the error does include the stack trace, which is similar to this one:

Unexpected closing brace.
      at @:1:234

      at @:1:234
      at parseSource (node_modules/.pnpm/cjs-module-lexer@1.2.2/node_modules/cjs-module-lexer/lexer.js:185:17)
      at parseCJS (node_modules/.pnpm/cjs-module-lexer@1.2.2/node_modules/cjs-module-lexer/lexer.js:43:5)
          at Array.forEach (<anonymous>)

Expected behavior

It should work and console log the exported function of the isolated-vm module.

Actual behavior

The error above is thrown and jest crashes.

I am not familiar with Jest's codebase, but I think this could be due to the way reexports are handled here:

const {exports, reexports} = parseCjs(transformedCode);
const namedExports = new Set(exports);
reexports.forEach(reexport => {
if (this._resolver.isCoreModule(reexport)) {
const exports = this.requireModule(modulePath, reexport);
if (exports !== null && typeof exports === 'object') {
Object.keys(exports).forEach(namedExports.add, namedExports);
}
} else {
const resolved = this._resolveCjsModule(modulePath, reexport);
const exports = this.getExportsOfCjs(resolved);
exports.forEach(namedExports.add, namedExports);
}
});

It looks like it treats the isolated-vm export in the node_modules/isolated-vm/isolated-vm.js file as a re-export. This is the contents of that file:

module.exports = require('./out/isolated_vm').ivm;

It would then try to parse the ./out/isolated_vm module as a CommonJS module using cjs-module-lexer. However, this module is a native addon, which then breaks the lexer cuz it is a binary file.

Additional context

Workaround

Change node_modules/isolated-vm/isolated-vm.js from this:

module.exports = require('./out/isolated_vm').ivm;

to this:

const ivm = require('./out/isolated_vm').ivm
module.exports = ivm;

and it starts working again:

❯ pnpm test esBug

> jest-issue-native-addons@1.0.0 test /home/jcm/projects/opensource/jest-issue-native-addons
> NODE_OPTIONS=--experimental-vm-modules pnpm jest --verbose "esBug"

  console.log
    isolated_vm { lib: Lib {} }

      at Object.<anonymous> (esBug.test.ts:6:13)

  console.log
    [Function (anonymous)]

      at Object.<anonymous> (esBug.test.ts:7:13)

(node:13821) ExperimentalWarning: VM Modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
 PASS  ./esBug.test.ts
  test
    ✓ works (20 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |       0 |        0 |       0 |       0 |                   
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.533 s
Ran all test suites matching /esBug/i.

Environment

System:
    OS: Linux 5.10 Ubuntu 22.04.2 LTS 22.04.2 LTS (Jammy Jellyfish)
    CPU: (8) x64 AMD Ryzen 5 5600X 6-Core Processor
  Binaries:
    Node: 18.14.0 - ~/.nvm/versions/node/v18.14.0/bin/node
    Yarn: 1.22.19 - /usr/bin/yarn
    npm: 9.3.1 - ~/.nvm/versions/node/v18.14.0/bin/npm
  npmPackages:
    jest: ^29.5.0 => 29.5.0

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions