developit / microbundle

📦 Zero-configuration bundler for tiny modules.
https://npm.im/microbundle
MIT License
7.99k stars 361 forks source link

Generates Broken CommonJS From Typescript #1079

Open luxo-ai opened 1 month ago

luxo-ai commented 1 month ago

Microbundle creates broken CommonJS code when compiling from Typescript.

The continue keyword in the following code is not respected in the compiled CommonJS code.

async function brokenContinue() {
  let j = 0;

  while (j <= 3) {
    j++;
    console.log("AT THE TOP");

    if (j === 1) {
      console.log("\t- j === 1");
      console.log("\t- waiting for 100ms");
      await new Promise((resolve) => setTimeout(resolve, 100));
      console.log('\t- continue, next log will be "AT THE TOP"');
      continue;
    }

    console.log("AT THE BOTTOM");
  }
}

void brokenContinue();

The output is:

$ node dist/index.cjs
AT THE TOP
    - j === 1
    - waiting for 100ms
    - continue, next log will be "AT THE TOP"
AT THE BOTTOM           <------- THIS SHOULD READ "AT THE TOP"
AT THE TOP
AT THE BOTTOM
AT THE TOP
AT THE BOTTOM
AT THE TOP
AT THE BOTTOM

The problem is caused by the usage of async/await within the while loop. Commenting out: await new Promise((resolve) => setTimeout(resolve, 100)); produces the expected result.

Notes:

Here's a repo containing the setup that caused the issue: https://github.com/luxo-ai/breakjs

rschristian commented 1 month ago

I'm not sure this has anything to do with TypeScript really -- likely a side effect of the async/await transpilation.

This unfortunately might be a "acceptable issue" for us, as Microbundle does choose to focus on a tiny output for the majority of modules. Some cases might not be fully supported.

luxo-ai commented 1 month ago

Yea, I figured it had to do with compatability transpilation / minification process since the .cjs output looked pretty gnarly.

If it's not something you think is worth fixing, that's all good with me. I just figured i'd report it. I was so confused when it happened because I thought it was my code.

rschristian commented 1 month ago

This shouldn't only affect the CJS output -- everything except modern is probably going to be borked.

Unfortunately you might need to refactor a tad in order to get working transpiled output. Correctly transpiling async/await results in huge outputs as there's all sorts of different edge cases. We try to take shortcuts here as, in the majority of situations, it won't cause issues and will result in smaller & faster outputs, at the expense of some correctness issues.