Conversation
- Esm.resolve_reexport: error out on missing export names and cyclic
re-export chains instead of looping forever (a typo in
[export { y } from ...] used to hang the compiler)
- Support [export * as ns from]: desugar into a synthetic namespace
import plus a plain export so the namespace object is materialized
- Rewrite exports of imported bindings into proper re-exports; the
bundled output used to reference the erased import binding
([import { x } ...; export { x }] and chains through middle modules)
- Esm_bundle: never optimize a namespace import that is itself exported
- Esm_bundle.merge_modules: substitute import bindings in export
statements and deduplicate conflicting export names (duplicate
exports are a JavaScript syntax error)
- Esm_tree_shake: count [var]s hoisted out of compound statements as
definitions ([if (c) var x = 1] used to be dropped while live code
referenced [x])
- Esm_tree_shake: class expressions with side-effecting extends
clauses, computed names or static blocks are no longer dropped
- Esm_tree_shake: mark modules traversed while resolving imports and
re-export chains as reached so their side effects are preserved
(re-exporting "barrel" modules), keep intermediate re-export entries
and pure re-export modules needed for bundle-time resolution
- Linker: align exported types of Fragment.attach_annot and
Fragment.script_to_module with what Parse_js.parse' produces
- Esm: drop the unused has_default_export field and the duplicated
topological sort
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
ppx_expect is not a dependency of this repo; CI fails with 'Library "ppx_expect" not found' on every Tests job. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Lexer.of_file keeps the input channel open, which prevents the test cleanup from deleting the file on Windows (Permission denied); read the file and use Lexer.of_string instead - Normalize path separators when printing bundler error messages so the expected output is stable across platforms Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
normalize_path only split on '/', but Filename.concat joins with '\\' on Windows, so '.' components stayed glued to the previous segment. In the cyclic-dependency tests each lap around the cycle then produced a new module id with an extra '\.' segment, growing the path until it exceeded MAX_PATH and resolution failed. Unify separators before splitting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Module ids are raw path strings. After the previous fix, resolved module
paths use '/' on Windows but entry points still used the '\\'-joined path
from Filename.concat, so entry ids sorted differently relative to their
dependencies than on Unix ('/' < '\\'). The SCC-based topological sort
then ordered independent sibling modules differently, breaking the
'import alias collision' expect test on Windows. Return normalized paths
from the test [write] helper so all module ids agree.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The bundler ordered modules with an SCC topological sort whose tie-break is the module id (a path): independent sibling modules came out in alphabetical order instead of the evaluation order mandated by the spec (post-order depth-first traversal following import declarations). Add [Esm.evaluation_order] and use it in [Esm_bundle.bundle]; the affected expect tests change to the ES-correct order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Import specifiers that [resolve] cannot resolve (e.g. "node:module") used to fail graph construction. They are now external: the import takes no part in the module graph and the statement is kept verbatim in the module body, so it survives bundling. Re-exporting from an external module remains an error. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tree shaking seeded liveness only from entry exports: an entry module that exports nothing was shaken away entirely, side effects included. Entry modules are evaluated by definition; mark them as reached so their side-effecting statements (and, transitively, the modules they import) survive. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A namespace import marks every export of the imported module live, so tree shaking kept modules whole even when only a few fields were used. Run the ns.field -> named-import optimization on the graph before shaking; the bundler's own pass remains for the no-shaking path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Member
Author
|
Pushed four
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds initial compiler tooling for working with ECMAScript modules.
New compiler support:
Esmmodule (compiler/lib/esm.ml): parses ES modules, extracts imports/exports, builds a module dependency graph (with cycle support), resolves star re-exports, and topologically sorts modules.Esm_bundlemodule (compiler/lib/esm_bundle.ml): bundles a module graph into a single program — rewrites imports to direct references, generates namespace bindings, optimizesns.fieldaccesses into named imports, and supports tree shaking from entry-point exports.Supporting changes:
js_assign.ml: the program top level is now recorded as aParamsblock instead ofVar_scope, so that under thePreservenaming strategy top-levelvardeclarations (which ESM output places directly at the top level, e.g. vars hoisted by tree shaking) get names allocated.compiler/tests-esm/(38 tests) using the vendoredppx_expect_light.Preliminary work for: #1532, #1161, #551