mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
### 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>
102 lines
3.3 KiB
TypeScript
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",
|
|
},
|
|
});
|
|
});
|