Files
bun.sh/test/bundler/bundler_npm.test.ts
Dylan Conway de4a5a07b1 fix(bundler): import.meta.url and esm wrapper fixes (#23803)
### What does this PR do?
Fixes printing `import.meta.url` and others with `--bytecode`. Fixes
#14954.

Fixes printing `__toESM` when output module format is CJS and input
module format is ESM.

The key change is that `__toESM`'s `isNodeMode` parameter now depends on
the **input module type** (whether the importing file uses ESM syntax
like `import`/`export`) rather than the output format. This matches
Node.js ESM behavior where importing CommonJS from `.mjs` files always
wraps the entire `module.exports` object as the default export, ignoring
`__esModule` markers.

### How did you verify your code works?

Added comprehensive test suite in `test/bundler/bundler_cjs.test.ts`
with **23 tests** covering:

#### Core Behaviors:
-  Files using `import` syntax always get `isNodeMode=1`, which
**ignores `__esModule`** markers and wraps the entire CJS module as
default
-  This matches Node.js ESM semantics for importing CJS from `.mjs`
files
-  Different CJS export patterns (`exports.x`, `module.exports = ...`,
functions, primitives)
-  Named, default, and namespace (`import *`) imports
-  Different targets (node, browser, bun) - all behave the same
-  Different output formats (esm, cjs) - format doesn't affect the
behavior
-  `.mjs` files re-exporting from `.cjs`
-  Deep re-export chains
-  Edge cases (non-boolean `__esModule`, `__esModule=false`, etc.)

#### Test Results:
- **With this PR's changes**: All 23 tests pass 
- **Without this PR (system bun)**: 22 pass, 1 fails (the one testing
that `__esModule` is ignored with import syntax + CJS format)

The failing test with system bun demonstrates the bug being fixed:
currently, format=cjs with import syntax still respects `__esModule`,
but it should ignore it (matching Node.js behavior).

---------

Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
2025-10-18 20:49:57 -07:00

102 lines
3.3 KiB
TypeScript

import { describe } from "bun:test";
import { isWindows } from "harness";
import { itBundled } from "./expectBundled";
describe("bundler", () => {
itBundled("npm/ReactSSR", {
todo: isWindows, // TODO(@paperclover)
install: ["react@18.3.1", "react-dom@18.3.1"],
files: {
"/entry.tsx": /* tsx */ `
import React from "react";
import { renderToReadableStream } from "react-dom/server";
const headers = {
headers: {
"Content-Type": "text/html",
},
};
const App = () => (
<html>
<body>
<h1>Hello World</h1>
<p>This is an example.</p>
</body>
</html>
);
const port = 0;
using server = Bun.serve({
port,
async fetch(req) {
return new Response(await renderToReadableStream(<App />), headers);
},
});
const res = await fetch("http://localhost:" + server.port);
if (res.status !== 200) throw "status error";
console.log(await res.text());
`,
},
// this test serves two purposes
// - does react work when bundled
// - do sourcemaps on a real-world library work
sourceMap: "external",
outdir: "out/",
minifySyntax: true,
minifyWhitespace: true,
minifyIdentifiers: true,
snapshotSourceMap: {
"entry.js.map": {
files: [
"../node_modules/react/cjs/react.development.js",
"../node_modules/react/cjs/react-jsx-dev-runtime.development.js",
"../node_modules/react-dom/cjs/react-dom-server-legacy.browser.development.js",
"../node_modules/react-dom/cjs/react-dom-server.browser.development.js",
"../node_modules/react-dom/server.browser.js",
"../entry.tsx",
],
mappings: [
["react.development.js:524:'getContextName'", "1:5412:Y1"],
["react.development.js:2495:'actScopeDepth'", "23:4082:GJ++"],
["react.development.js:696:''Component'", '1:7474:\'Component "%s"'],
["entry.tsx:6:'\"Content-Type\"'", '100:18809:"Content-Type"'],
["entry.tsx:11:'<html>'", "100:19063:void"],
["entry.tsx:23:'await'", "100:19163:await"],
],
},
},
expectExactFilesize: {
"out/entry.js": 221720,
},
run: {
stdout: "<!DOCTYPE html><html><body><h1>Hello World</h1><p>This is an example.</p></body></html>",
},
});
itBundled("npm/LodashES", {
install: ["lodash-es"],
files: {
"/entry.ts": /* tsx */ `
import { isEqual, isBuffer } from "lodash-es";
// https://github.com/oven-sh/bun/issues/3206
if(!isEqual({a: 1}, {a: 1})) throw "error 1";
if(isEqual({a: 1}, {a: 2})) throw "error 2";
// Uncomment when https://github.com/lodash/lodash/issues/5660 is fixed
// It prevents isBuffer from working at all since it evaluates to 'stubFalse'
// if(!isBuffer(Buffer.from("hello"))) throw "error 3";
// if(isBuffer("hello")) throw "error 4";
// if(isBuffer({})) throw "error 5";
// if(isBuffer(new Uint8Array([1]))) throw "error 6";
// if(isBuffer(new ArrayBuffer(1))) throw "error 7";
console.log('pass')
`,
},
run: {
stdout: "pass",
},
});
});