oven-sh / bun

Incredibly fast JavaScript runtime, bundler, test runner, and package manager – all in one
https://bun.sh
Other
73.27k stars 2.69k forks source link

Auto import jsx-runtime to fix: Can't find variable: jsxDEV #7499

Open aralroca opened 9 months ago

aralroca commented 9 months ago

What version of Bun is running?

1.0.15+b3bdf22eb

What platform is your computer?

Darwin 23.1.0 arm64 arm

What steps can reproduce the bug?

If you make a simple plugin where you parse the code and then re-generate it (without touching the AST) the error occurs.

An example how to reproduce it:

Some AST util file with meriyah and astring:

import { generate } from "astring";
import { JavaScriptLoader } from "bun";
import { ESTree, parseScript } from "meriyah";

export default function AST(loader: JavaScriptLoader = "tsx") {
  const transpiler = new Bun.Transpiler({ loader });

  return {
    parseCodeToAST(code: string): ESTree.Program {
      return parseScript(transpiler.transformSync(code), {
        jsx: true,
        module: true,
      });
    },
    generateCodeFromAST(ast: ESTree.Program) {
      return generate(ast, { indent: "  " });
    },
  };
}

Example of Bun.build:

const { parseCodeToAST, generateCodeFromAST } = AST();

 await Bun.build({
    entrypoints,
    outdir,
    root,
    minify: true,
    splitting: true,
    target: 'bun',
    plugins: [
      {
        name: "example-of-bug",
        setup(build) {
          build.onLoad(
            { filter: /\.(tsx|jsx)$/ },
            async ({ path, loader }) => {          
              return {
                contents: generateCodeFromAST(parseCodeToAST(await Bun.file(path).text())),
                loader,
              };
            }
          );
        },
      },
    ],
  });

It does the build well. But when loading the file that has made build with bun, then it jumps this error:

ReferenceError: Can't find variable: jsxDEV

What is the expected behavior?

The expected behavior is that Bun auto imports the jsx-runtime in case the JSX or TSX instead of being <FromThisWay />, this jsxDev(FromThisWay).

What do you see instead?

I see that the file cannot be executed, it gives an error and the bun runtime closes.

Screenshot 2023-12-07 at 01 26 52

Additional information

No response

Enalmada commented 8 months ago

Just before giving up completely on bundling react libraries with Bun, I happened to find that changing external from ['*'] to a manual list of packages in my dependencies works. I hope this helps someone with a workaround and possibly helps narrow down the bug so it can be fixed.

  import getExternalDependenciesFromPackageJson from '@enalmada/bun-externals'
  const externalDeps = await getExternalDependenciesFromPackageJson();

  await Bun.build({
    entrypoints: ['./src/client/urql/UrqlWrapper.tsx'],
    outdir: './dist/client',
    target: 'node',
    external: [...externalDeps, './src/client/urql/UrqlWrapper'],
    root: './src/client',
  });
aralroca commented 6 months ago

The bug is related to Bun.Transpiler that it's replacing <div /> to jsxDEV('div', ...) without adding the import of the jsx-runtime. Then it's impossible for the builder. How can this be solved? 🤔

Should the transpiler add the jsx-runtime import? How can we do this from a plugin to know what jsx-runtime import is needed to add it? Or could we support preserve in the transpiler to keep the JSX? Or should the builder see if there are jsxDEV/jsx without an import and then add it?

@Jarred-Sumner @paperdave

HairyRabbit commented 5 months ago

any update?