Skip to content

[Bug]: tslib 2.5.2 package.json exports change breaks Jest when using ESM modules #14173

@josundt

Description

@josundt

Version

29.5.0 (latest)

Steps to reproduce

Context

I have a TypeScript project that compiles to true ESM modules (moduleResolution/module NodeNext), and all ".ts" imports use ".js" extensions as recommended in TypeScript. The project uses f.ex. TypeScript experimentalDecorators and it uses importHelpers which adds a dependency to tslib.

My jest config looks as follows:

{
    moduleNameMapper: {
        "^(\\.{1,2}/.*)\\.js$": "$1"
    },
    transform: {
        "^.+\\.tsx?$": ["ts-jest", {
            tsconfig: "tsconfig.json",
            useESM: true
        }]
    },
    extensionsToTreatAsEsm: [".ts"],
    testEnvironment: "jsdom"
}

To support ESM, I run the tests with:
node --experimental-vm-modules --no-warnings node_modules/jest/bin/jest.js

This setup is following the jest/ts-jest documentation, and should be standard for ESM support in TypeScript projects.

The Jest bug

After upgrading tslib from v2.5.0 to v2.5.2, the Jest tests fail.
This is because tslib's exports in package.json has changed with the update, and it seems like the Jest's resolver does not support the more verbose export syntax.

tslib@2.5.0 package.json exports:

{
    //...
    "exports": {
        ".": {
            "module": "./tslib.es6.js",
            "import": "./modules/index.js",
            "default": "./tslib.js"
        },
        "./*": "./*",
        "./": "./"
    }
    //...
}

tslib@2.5.2 package.json exports:

{
    //...
    "exports": {
        ".": {
            "module": {
                "types": "./tslib.d.ts",
                "default": "./tslib.es6.js"
            },
            "import": {
                "node": "./modules/index.js",
                "default": {
                    "types": "./tslib.d.ts",
                    "default": "./tslib.es6.js"
                }
            },
            "default": "./tslib.js"
        },
        "./*": "./*",
        "./": "./"
    }
    //...
}

When I just copy the exports from 2.5.0 and replace the ones in 2.5.2 in *node_modules/tslib/package.json, the tests run just fine.

PS! This error only seems to happen when using jest config envirnoment: "jsdom". When setting it to "node", the problem is not triggered. It looks like this may be a jest-environment-jsom specific issue.

I have tested configuring jest with moduleNameMapper to force tslib to use:

  • node_modules/tslib/tslib.js
  • node_modules/tslib/tslib.es6.js
  • node_modules/tslib/modules/index.js
    ...but none of these fixed the issue.

Expected behavior

The tests should work like before

Actual behavior

                                                                                                                                                                                                                        
 FAIL test/views/app/app.spec.ts                                                                                                                                                                                        
  ● Test suite failed to run                                                                                                                                                                                             
                                                                                                                                                                                                                         
    Jest encountered an unexpected token                                                                                                                                                                                 
                                                                                                                                                                                                                         
    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.                                         
                                                                                                                                                                                                                         
    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.                                                                                      

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    C:\_Git\Adra.Reference.App\src\Adra.Reference.App\node_modules\tslib\tslib.es6.js:24
    export function __extends(d, b) {
    ^^^^^^

    SyntaxError: Unexpected token 'export'

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1495:14)


ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From test/views/app/app.spec.ts.                                                                                        
                                                                                                                                                                                                                         
                                                                                                                                                                                                                         
                                                                                                                                                                                                                         
ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From test/views/app/app.spec.ts.



ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From test/views/app/app.spec.ts.



ReferenceError: You are trying to `import` a file after the Jest environment has been torn down. From test/views/app/app.spec.ts.                                                                                        
                                                                                                                                                                                                                         

Additional context

My tsconfig.json file looks as follows:

{
  "compilerOptions": {
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "esModuleInterop": true,
    "exactOptionalPropertyTypes": false,
    "experimentalDecorators": true,
    "forceConsistentCasingInFileNames": true,
    "importHelpers": true,
    "lib": ["dom", "es2019"],
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "noFallthroughCasesInSwitch": true,
    "noImplicitAny": true,
    "noImplicitOverride": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": false,
    "noUnusedLocals": true,
    "noUnusedParameters": false,
    "preserveConstEnums": true,
    "sourceMap": true,
    "strictBindCallApply": true,
    "strictFunctionTypes": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "stripInternal": true,
    "target": "es2019",
    "useUnknownInCatchVariables": true,
    "verbatimModuleSyntax": true
  },
  "include": ["src", "test"]
}

Environment

System:
    OS: Windows 10 10.0.22621
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i7-11370H @ 3.30GHz
  Binaries:
    Node: 18.16.0 - C:\Program Files\nodejs\node.EXE
    npm: 9.5.1 - C:\Program Files\nodejs\npm.CMD
  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