jimp-dev / jimp-dev/jimp

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

Open
#1,405 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
14.7k
Forks
777
PR merge metrics
No merged PRs in 30d

Description

## 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`**
```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`**
```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`**
```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:

```js
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`.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.