Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#### :bug: Bug fix

- Make rewatch compile independent modules after an unrelated failure and recompile blocked dependents when a changed interface survives a failed implementation, including across full watcher rebuilds. https://github.com/rescript-lang/rescript/pull/8667
- Fix `RescriptTools.binaryPath` failing with `ERR_PACKAGE_IMPORT_NOT_DEFINED` when used from a user project. https://github.com/rescript-lang/rescript/pull/8694
- GenType: type inline-record cases of untagged variants as objects instead of their single field's type. https://github.com/rescript-lang/rescript/pull/8693
- Keep comments on labelled parameters with default values, and before `=?` in optional arrow-type arguments, when formatting. https://github.com/rescript-lang/rescript/pull/8690
- Fix invalid JavaScript that exported names left unbound when a module's toplevel always throws. https://github.com/rescript-lang/rescript/pull/8692
Expand Down
73 changes: 73 additions & 0 deletions cli/common/bins.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// @ts-check

// Paths of the compiler binaries in the platform package (@rescript/<target>).
// The lookup is synchronous so that tools.cjs, the CommonJS entry of
// `rescript/tools`, can load it; bins.js re-exports these values for ES modules.

const path = require("node:path");

const minimumNodeVersion = "20.11.0";

const target = `${process.platform}-${process.arch}`;

const supportedPlatforms = [
"darwin-arm64",
"darwin-x64",
"linux-arm64",
"linux-x64",
"win32-x64",
];

if (!supportedPlatforms.includes(target)) {
throw new Error(`Platform ${target} is not supported!`);
}

const binPackageName = `@rescript/${target}`;

/** @type {string} */
let binPackageEntry;
try {
binPackageEntry = require.resolve(binPackageName);
} catch {
// First check if we are on an unsupported node version, as that may be the cause for the error.
checkNodeVersionSupported();

throw new Error(
`Package ${binPackageName} not found. Make sure the rescript package is installed correctly.`,
);
}

// The platform package's entry (bin.js) sits next to its bin directory.
const binDir = path.join(path.dirname(binPackageEntry), "bin");

exports.binDir = binDir;
exports.bsc_exe = path.join(binDir, "bsc.exe");
exports.rescript_editor_analysis_exe = path.join(
binDir,
"rescript-editor-analysis.exe",
);
exports.rescript_tools_exe = path.join(binDir, "rescript-tools.exe");
exports.rescript_exe = path.join(binDir, "rescript.exe");

function checkNodeVersionSupported() {
if (
typeof process !== "undefined" &&
process.versions != null &&
process.versions.node != null
) {
const currentVersion = process.versions.node;
const required = minimumNodeVersion.split(".").map(Number);
const current = currentVersion.split(".").map(Number);
if (
current[0] < required[0] ||
(current[0] === required[0] && current[1] < required[1]) ||
(current[0] === required[0] &&
current[1] === required[1] &&
current[2] < required[2])
) {
throw new Error(
`ReScript requires Node.js >=${minimumNodeVersion}, but found ${currentVersion}.`,
);
}
}
}
73 changes: 7 additions & 66 deletions cli/common/bins.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,11 @@
// @ts-check

const minimumNodeVersion = "20.11.0";
// ES module entry for the binary paths computed in bins.cjs.

/**
* @typedef {import("@rescript/linux-x64")} BinaryModuleExports
*/

const target = `${process.platform}-${process.arch}`;

const supportedPlatforms = [
"darwin-arm64",
"darwin-x64",
"linux-arm64",
"linux-x64",
"win32-x64",
];

/** @type {BinaryModuleExports} */
let mod;

if (supportedPlatforms.includes(target)) {
const binPackageName = `@rescript/${target}`;

try {
mod = await import(binPackageName);
} catch {
// First check if we are on an unsupported node version, as that may be the cause for the error.
checkNodeVersionSupported();

throw new Error(
`Package ${binPackageName} not found. Make sure the rescript package is installed correctly.`,
);
}
} else {
throw new Error(`Platform ${target} is not supported!`);
}

export const {
export {
binDir,
binPaths: {
bsc_exe,
rescript_editor_analysis_exe,
rescript_tools_exe,
rescript_exe,
},
} = mod;

function checkNodeVersionSupported() {
if (
typeof process !== "undefined" &&
process.versions != null &&
process.versions.node != null
) {
const currentVersion = process.versions.node;
const required = minimumNodeVersion.split(".").map(Number);
const current = currentVersion.split(".").map(Number);
if (
current[0] < required[0] ||
(current[0] === required[0] && current[1] < required[1]) ||
(current[0] === required[0] &&
current[1] === required[1] &&
current[2] < required[2])
) {
throw new Error(
`ReScript requires Node.js >=${minimumNodeVersion}, but found ${currentVersion}.`,
);
}
}
}
bsc_exe,
rescript_editor_analysis_exe,
rescript_exe,
rescript_tools_exe,
} from "./bins.cjs";
6 changes: 6 additions & 0 deletions cli/common/tools.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @ts-check

// Public entry point `rescript/tools` for CommonJS: the path of the
// rescript-tools binary, which RescriptTools.binaryPath binds to.

exports.binaryPath = require("./bins.cjs").rescript_tools_exe;
6 changes: 6 additions & 0 deletions cli/common/tools.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// @ts-check

// Public entry point `rescript/tools` for ES modules: the path of the
// rescript-tools binary, which RescriptTools.binaryPath binds to.

export { rescript_tools_exe as binaryPath } from "./bins.cjs";
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@
"exports": {
"./lib/es6/*": "./lib/es6/*",
"./lib/js/*": "./lib/js/*",
"./tools": {
"require": "./cli/common/tools.cjs",
"default": "./cli/common/tools.js"
},
"./package.json": "./package.json"
},
"imports": {
Expand Down
4 changes: 2 additions & 2 deletions packages/@rescript/runtime/RescriptTools.res
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ You can use this when you're already running a JS process and want to avoid the
let stringifiedJson = ChildProcess.execFileSync(RescriptTools.binaryPath, ["-v"])
```
*/
@module("#cli/bins")
external binaryPath: string = "rescript_tools_exe"
@module("rescript/tools")
external binaryPath: string = "binaryPath"
3 changes: 3 additions & 0 deletions packages/artifacts.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
"LICENSE.MIT",
"README.md",
"cli/bsc.js",
"cli/common/bins.cjs",
"cli/common/bins.js",
"cli/common/runtime.js",
"cli/common/tools.cjs",
"cli/common/tools.js",
"cli/rescript-tools.js",
"cli/rescript.js",
"docs/docson/build-schema.json",
Expand Down
2 changes: 2 additions & 0 deletions tests/build_tests/rescript_tools_binary_path/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
src/**/*.mjs
src/**/*.cjs
30 changes: 30 additions & 0 deletions tests/build_tests/rescript_tools_binary_path/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// @ts-check

import * as assert from "node:assert";
import * as fs from "node:fs/promises";
import * as path from "node:path";
import { rescript_tools_exe } from "#cli/bins";
import { setup } from "#dev/process";

const { execBuildOrThrow, execClean, node } = setup(import.meta.dirname);

const repoRoot = path.resolve(import.meta.dirname, "..", "..", "..");
const nodeModules = path.join(import.meta.dirname, "node_modules");

await execBuildOrThrow();

// The project depends on the rescript package, as a user project does.
await fs.mkdir(nodeModules, { recursive: true });
await fs.symlink(repoRoot, path.join(nodeModules, "rescript"), "junction");

try {
// The project emits both ES module and CommonJS output.
for (const output of ["Main.mjs", "Main.cjs"]) {
const out = await node(path.join("src", output));
assert.equal(out.stderr, "", output);
assert.equal(out.stdout.trim(), rescript_tools_exe, output);
}
} finally {
await fs.rm(nodeModules, { recursive: true, force: true });
await execClean();
}
16 changes: 16 additions & 0 deletions tests/build_tests/rescript_tools_binary_path/rescript.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "rescript-tools-binary-path",
"sources": "src",
"package-specs": [
{
"module": "esmodule",
"in-source": true,
"suffix": ".mjs"
},
{
"module": "commonjs",
"in-source": true,
"suffix": ".cjs"
}
]
}
1 change: 1 addition & 0 deletions tests/build_tests/rescript_tools_binary_path/src/Main.res
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Console.log(RescriptTools.binaryPath)
Loading