Skip to content

Add bundler integration tests verifying EXPORT_ES6 output has no requ…#26419

Open
vogel76 wants to merge 1 commit intoemscripten-core:mainfrom
vogel76:bw_bundler_require_test
Open

Add bundler integration tests verifying EXPORT_ES6 output has no requ…#26419
vogel76 wants to merge 1 commit intoemscripten-core:mainfrom
vogel76:bw_bundler_require_test

Conversation

@vogel76
Copy link

@vogel76 vogel76 commented Mar 9, 2026

Summary

Adds two integration tests to test_other.py that demonstrate how require() calls in EXPORT_ES6 output break bundlers. Both tests fail on main and are intended to pass after the require() elimination changes from #26384.

This addresses the review comment requesting concrete test cases showing bundler breakage.

Tests added

test_webpack_esm_output_clean

Compiles with -sEXPORT_ES6 and default environment (web+node), then builds with webpack.

Failure on main:

ERROR in node:module
Module build failed: UnhandledSchemeError: Reading from "node:module" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.

 @ ./src/hello.mjs 83:34-55
 @ ./src/index.mjs 14:0-33 15:0-6

webpack 5.105.2 compiled with 1 error

Why it fails: Emscripten's EXPORT_ES6 output uses import { createRequire } from 'node:module' to polyfill require() for loading Node.js built-ins (fs, path, url). Webpack targeting web cannot resolve node: URI schemes — it hard-errors and produces no bundle at all. This breaks any webpack-based project (including Next.js, Nuxt, and Create React App) that tries to use emscripten's ESM output.

test_vite_esm_output_clean

Compiles with -sEXPORT_ES6 using default environment (web+node), then runs vite build and checks for externalization warnings.

Failure on main:

[plugin vite:resolve] Module "node:module" has been externalized for browser
compatibility, imported by "/src/out/test/hello.mjs".

AssertionError: Expected to NOT find 'externalized for browser compatibility'

Why it fails: Vite encounters import { createRequire } from 'node:module' in the ESM input. Since vite targets browsers, it can't bundle Node.js built-in modules. Instead of erroring, vite externalizes node:module — the build succeeds but the resulting bundle contains code that references modules unavailable in browsers. While the hello_world test case works by accident (the node code path is guarded by if (ENVIRONMENT_IS_NODE) which is false in browsers), any application with more complex node/web interop would silently break.

Rollup (not tested, for reference)

Rollup is the most lenient bundler — it warns about the unresolved dependency but still produces a bundle (exit code 0). The require() calls are passed through as-is into the output:

(!) Unresolved dependencies
https://rollupjs.org/troubleshooting/#warning-treating-module-as-external-dependency
node:module (imported by "hello.mjs")
created dist/bundle.mjs in 35ms
EXIT_CODE=0

The resulting bundle contains 4 require() calls. In Node.js this works because createRequire provides a working require function. In browsers the node code path is guarded by if (ENVIRONMENT_IS_NODE) so it's never reached — the bundle runs without error but carries dead node code. Because rollup doesn't error or even fail the build, it's a weaker test case and was not included in the test suite.

Bundler behavior summary

Bundler Behavior on main Exit code Test
webpack Hard error: UnhandledSchemeError on node:module 1 test_webpack_esm_output_clean
vite Warning: externalizes node:module for browser compat 0 test_vite_esm_output_clean
rollup Warning: unresolved dependency, passes require() through 0 (not tested)

Relationship to #26384

These tests validate the fix in #26384 which replaces require() with await import() in EXPORT_ES6 output. After cherry-picking this commit onto that branch, both tests should pass.

…ire()

Add two tests that verify EXPORT_ES6 output is valid ESM and works with
bundlers:

- test_webpack_esm_output_clean: Compiles with EXPORT_ES6 and default
  environment (web+node), then builds with webpack. On main, webpack
  hard-fails because it cannot resolve 'node:module' (used by emscripten's
  createRequire polyfill). This breaks any webpack/Next.js/Nuxt project.

- test_vite_esm_output_clean: Compiles with EXPORT_ES6 and default
  environment, then builds with vite. On main, vite externalizes
  'node:module' for browser compatibility, emitting a warning. The
  resulting bundle contains code referencing unavailable node modules.

These tests are expected to fail on main and pass after eliminating
require() from EXPORT_ES6 output.
@vogel76 vogel76 force-pushed the bw_bundler_require_test branch from dbc3947 to de21f1e Compare March 9, 2026 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants