Skip to content

jimp v1.6.0 — dist/browser/index.js contains strict-mode-invalid code #1405

Description

@jtstuedle

Environment

  • jimp: 1.6.0
  • webpack: 5.x (web target)
  • Node.js: Any — the issue is in the published artifact, not the build toolchain
  • OS: Any
  • Impact: Blocks webpack builds targeting browser; strict mode parsing may have been disabled as a mitigation strategy.

Summary

jimp/dist/browser/index.js is declared as an ES module (it ends with export { ... } and the package has "type": "module") but its body contains rollup-generated CommonJS interop helpers that use duplicate identifier names (e.g. function e(e) { ... }). This is invalid in strict mode, which ES modules enforce unconditionally. Webpack — and any other bundler that respects the "browser" export condition — fails to parse the file.

Expected Behavior

dist/browser/index.js should be parseable as a strict-mode ES module. The minified helper function should not shadow its own name as a parameter.

Actual Behavior

Any bundler that resolves the "browser" export condition fails with a strict-mode parse error on the duplicate identifier.

Steps to Reproduce

package.json

{
  "name": "jimp-webpack-repro",
  "private": true,
  "scripts": { "build": "webpack --mode production" },
  "dependencies": { "jimp": "1.6.0" },
  "devDependencies": {
    "@babel/core": "^7.24.0",
    "@babel/preset-env": "^7.24.0",
    "babel-loader": "^9.1.3",
    "webpack": "^5.91.0",
    "webpack-cli": "^5.1.4"
  }
}

webpack.config.js

const path = require("path");
module.exports = {
    target: "web",
    entry: "./src/index.js",
    output: { path: path.resolve(__dirname, "dist"), filename: "bundle.js" },
    module: {
        rules: [{
            test: /\.m?js$/,
            exclude: /node_modules\/(?!crypto-api|bootstrap)/,
            loader: "babel-loader",
            options: { presets: ["@babel/preset-env"], cacheDirectory: true },
            type: "javascript/auto",
        }],
    },
};

src/index.js

import { Jimp, JimpMime } from "jimp";

async function blurImage(arrayBuffer) {
    const image = await Jimp.fromBuffer(arrayBuffer);
    image.blur(5);
    return image.getBuffer(JimpMime.png);
}

export { blurImage };
npm install && npm run build

Failure Output

ERROR in ./node_modules/jimp/dist/browser/index.js 199:9979
Module parse failed: Identifier 'e' has already been declared (199:9979)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|   return t < 0 && (t = e.length + t), e.substr(t, i);
| };
> function e(e) {
|   return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
| }

Note: The column number varies across builds (line 199 in this repro vs. line 31135 in multi-line builds). This is expected — dist/browser/index.js is a single-line bundle, so all positions are on line 1 or 199 depending on how the bundler counts. More importantly, the collision is not isolated to one location — the rollup getDefaultExportFromCjs helper is emitted multiple times throughout the file, so there are multiple instances of function e(e) in the bundle.

Root Cause

dist/browser/index.js is produced by rollup as a pre-bundled file for direct browser/CDN use. Rollup inlines a getDefaultExportFromCjs helper using a minified identifier, but the minified output collides with a surrounding scope — producing function e(e) { ... } (a function named e whose parameter is also e).

This pattern is valid in sloppy mode (classic scripts) but not in strict mode. Because:

  • jimp/package.json declares "type": "module", and
  • dist/browser/index.js itself ends with export { Jimp, JimpMime, ... }

...every JavaScript engine and bundler is required to parse the file in strict mode, where the duplicate binding is a syntax error.

The @jimp/... sub-packages (e.g. @jimp/js-bmp) are unaffected — they only expose "import" and "require" export conditions with clean ESM source files.

Workaround

Alias jimp to its ESM build in your bundler config to bypass the broken browser bundle. In webpack:

resolve: {
    alias: {
        jimp: require("path").resolve(__dirname, "node_modules/jimp/dist/esm/index.js")
    }
}

The ESM build (dist/esm/index.js) imports from the @jimp/... sub-packages, which have clean, valid ES module sources and are already installed as transitive dependencies of jimp.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions