Skip to content

Resolve RescriptTools.binaryPath in user projects - #8694

Open
cristianoc wants to merge 5 commits into
masterfrom
cristianoc/fix-rescript-tools-binary-path
Open

cristianoc wants to merge 5 commits into
masterfrom
cristianoc/fix-rescript-tools-binary-path

Conversation

@cristianoc

@cristianoc cristianoc commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #8712.

Summary

  • Resolve RescriptTools.binaryPath through a rescript package export. RescriptTools.binaryPath was @module("#cli/bins"). An external is emitted at its use site, so the import ... from "#cli/bins" lands in the user's compiled module, and Node resolves a # specifier against the "imports" field of the package.json closest to that module. Only the rescript package defines #cli/*, so in a user project the import fails with ERR_PACKAGE_IMPORT_NOT_DEFINED. A scratch project linking the workspace's rescript, @rescript/runtime and @rescript/darwin-arm64 packages reproduced this.

Test plan

  • dune build
  • dune build @fmt
  • dune build --profile browser @check
  • make
  • make lib
  • no change in the runtime and Belt lib/ outputs
  • make test
  • yarn apidocs:generate
  • make playground
  • yarn workspace playground test
  • make checkformat
  • npm run check

🤖 Generated with Claude Code

@cristianoc
cristianoc requested a review from cknitt October 2, 2026 06:30
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-02T06:32:42.382721Z 402ca04 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@cristianoc cristianoc mentioned this pull request Oct 2, 2026
21 of 22 tasks

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 402ca04450

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread package.json Outdated
"exports": {
"./lib/es6/*": "./lib/es6/*",
"./lib/js/*": "./lib/js/*",
"./cli/bins": "./cli/common/bins.js",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the user-facing fix to the unreleased changelog

This changes the behavior of a published runtime API and fixes a user-visible failure, but the commit does not add the required entry under the current (Unreleased) bug-fix section of CHANGELOG.md. Add an entry ending with the PR link so the fix is included in the release notes.

AGENTS.md reference: AGENTS.md:L93-L95

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in d46ee1d, under the Unreleased section with the PR link.

```
*/
@module("#cli/bins")
@module("rescript/cli/bins")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve binaryPath for CommonJS consumers

When a consumer uses the supported package-specs.module: "commonjs" output, this external is emitted as require("rescript/cli/bins"). That export resolves to cli/common/bins.js, which is an ES module containing top-level await, so Node throws ERR_REQUIRE_ASYNC_MODULE; the added test only exercises esmodule output and misses this case. Provide a CommonJS-compatible/conditional entry point or otherwise avoid synchronously requiring the top-level-await module.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed: with module: commonjs, require("rescript/cli/bins") loaded cli/common/bins.js, and its top-level await made Node throw ERR_REQUIRE_ASYNC_MODULE. 629d9dd adds cli/common/bins.cjs, which finds the platform package with require.resolve and builds the same paths synchronously. The ./cli/bins export now sends the require condition there and keeps bins.js as the default for imports. tests/build_tests/rescript_tools_binary_path now emits both ES module (.mjs) and CommonJS (.cjs) output and checks that both print the tools binary path. Before the fix the CommonJS run fails with ERR_REQUIRE_ASYNC_MODULE.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up in 3af68e8: cli/common/bins.cjs is now the only implementation of the platform lookup, and bins.js re-exports the same names from it, so the ESM and CommonJS entries cannot drift. The exported names and values are identical to before, and rescript_tools_binary_path still passes for both outputs.

@pkg-pr-new

pkg-pr-new Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

rescript

npm i https://pkg.pr.new/rescript@8694

@rescript/belt

npm i https://pkg.pr.new/@rescript/belt@8694

@rescript/darwin-arm64

npm i https://pkg.pr.new/@rescript/darwin-arm64@8694

@rescript/darwin-x64

npm i https://pkg.pr.new/@rescript/darwin-x64@8694

@rescript/linux-arm64

npm i https://pkg.pr.new/@rescript/linux-arm64@8694

@rescript/linux-x64

npm i https://pkg.pr.new/@rescript/linux-x64@8694

@rescript/runtime

npm i https://pkg.pr.new/@rescript/runtime@8694

@rescript/win32-x64

npm i https://pkg.pr.new/@rescript/win32-x64@8694

commit: d01a4f5

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

@cknitt

cknitt commented Oct 4, 2026

Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

Reviewed commit: d01a4f5fb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

cknitt commented Oct 4, 2026

Copy link
Copy Markdown
Member

The RescriptTools.binaryPath fix makes sense, but exporting rescript/cli/bins also makes all binary paths public API. bins.js is currently an internal helper, and fixing this one binding doesn’t require exposing its full interface.

Could we instead add a small rescript/tools entry point exposing only binaryPath, and point the ReScript external there? We can keep the synchronous shared implementation and ESM/CommonJS support from this PR, with bins remaining private. That fixes the user-project failure while keeping the public API focused on the functionality we intend to support.

cristianoc and others added 5 commits October 4, 2026 09:10
RescriptTools.binaryPath was `@module("#cli/bins")`. An external is
emitted at its use site, so the `import ... from "#cli/bins"` lands in
the user's compiled module, and Node resolves a `#` specifier against
the "imports" field of the package.json closest to that module. Only
the rescript package defines `#cli/*`, so in a user project the import
fails with ERR_PACKAGE_IMPORT_NOT_DEFINED. A scratch project linking
the workspace's rescript, @rescript/runtime and @rescript/darwin-arm64
packages reproduced this.

The rescript package now exports "./cli/bins" (cli/common/bins.js) and
binaryPath imports "rescript/cli/bins", which resolves from any
project that depends on rescript.

tests/build_tests/rescript_tools_binary_path compiles a module that
prints RescriptTools.binaryPath into a src/ with its own package.json,
links node_modules/rescript to the repository and runs it. It fails
with ERR_PACKAGE_IMPORT_NOT_DEFINED before this change and prints the
rescript-tools path after it; node scripts/test.js -build passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
CommonJS output compiles RescriptTools.binaryPath to
require("rescript/cli/bins"). cli/common/bins.js uses top-level await,
so require fails with ERR_REQUIRE_ASYNC_MODULE. The export now maps the
require condition to cli/common/bins.cjs, which resolves the platform
package synchronously, and keeps bins.js for imports. The build test
emits both ES module and CommonJS output and runs each.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
bins.js re-exports the paths from bins.cjs, so ES module and CommonJS
consumers share one platform lookup. bins.cjs now also reports an
unsupported Node.js version when the platform package is missing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Cristiano Calcagno <cristianoc@users.noreply.github.com>
@cristianoc
cristianoc force-pushed the cristianoc/fix-rescript-tools-binary-path branch from d01a4f5 to 4108171 Compare October 4, 2026 08:12
@cristianoc

Copy link
Copy Markdown
Collaborator Author

@cknitt Done in 4108171: rescript/tools is now the only public entry, exporting just binaryPath (cli/common/tools.cjs for require, cli/common/tools.js for imports), and RescriptTools.binaryPath binds to it. bins is private again: rescript/cli/bins fails with ERR_PACKAGE_PATH_NOT_EXPORTED. The shared synchronous lookup in bins.cjs and the ESM/CommonJS test are unchanged. I also rebased on master.

@cknitt

cknitt commented Oct 4, 2026

Copy link
Copy Markdown
Member

@codex review

This branch has not been deployed

No deployments
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.

Repairs from semantic drift analysis

2 participants