Skip to content

Commit 58e3d6a

Browse files
committed
chore: update
1 parent 4f1a7ee commit 58e3d6a

11 files changed

Lines changed: 99 additions & 14 deletions

File tree

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
"test:benchmark": "cd ./tests && pnpm run test:benchmark",
2121
"test:e2e": "pnpm run build:examples && cd tests && pnpm run test:e2e",
2222
"test:ecosystem-ci": "pnpm run test:unit && cross-env ECO_CI=1 pnpm run test:integration && pnpm run test:e2e",
23-
"test:integration": "rstest run --project integration --exclude tests/integration/exe/**",
24-
"test:integration:exe": "rstest run --project integration tests/integration/exe/**",
23+
"test:integration": "rstest run --project integration",
24+
"test:integration:exe": "rstest run --project integration-exe",
2525
"test:unit": "rstest run --project unit*",
2626
"testu": "pnpm run test:unit -u && pnpm run test:integration -u",
2727
"type-check": "pnpm -r run type-check",

packages/core/src/exe/download.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import fs from 'node:fs';
22
import path from 'node:path';
3+
import { Readable } from 'node:stream';
4+
import { pipeline } from 'node:stream/promises';
5+
import type { ReadableStream as WebReadableStream } from 'node:stream/web';
36
import type { ExeArch, ExePlatform } from '../types';
47
import type { NormalizedExeTarget, ResolvedExeTarget } from './types';
58
import { readBinaryVersion, runCommand } from './utils';
@@ -56,9 +59,23 @@ const downloadArchive = async (url: string, archivePath: string) => {
5659
);
5760
}
5861

59-
const arrayBuffer = await response.arrayBuffer();
62+
if (!response.body) {
63+
throw new Error(
64+
`Failed to download "${url}" for "experiments.exe": response body is empty.`,
65+
);
66+
}
67+
6068
await fs.promises.mkdir(path.dirname(archivePath), { recursive: true });
61-
await fs.promises.writeFile(archivePath, Buffer.from(arrayBuffer));
69+
70+
try {
71+
await pipeline(
72+
Readable.fromWeb(response.body as WebReadableStream<Uint8Array>),
73+
fs.createWriteStream(archivePath),
74+
);
75+
} catch (error) {
76+
await fs.promises.rm(archivePath, { force: true });
77+
throw error;
78+
}
6279
};
6380

6481
const extractArchive = async ({

packages/core/src/exe/index.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,9 @@ import {
1515
normalizeNodeVersion,
1616
} from './version';
1717

18-
const normalizeTargetsInput = (exe?: ExeOptions): ExeTargetInput[] => {
19-
if (!exe) {
20-
return [];
21-
}
18+
type EnabledExeOptions = Exclude<ExeOptions, false | undefined>;
2219

20+
const normalizeTargetsInput = (exe: EnabledExeOptions): ExeTargetInput[] => {
2321
if (exe === true) {
2422
return [{}];
2523
}
@@ -28,7 +26,7 @@ const normalizeTargetsInput = (exe?: ExeOptions): ExeTargetInput[] => {
2826
};
2927

3028
export const resolveExeTargets = (
31-
exe?: ExeOptions,
29+
exe: EnabledExeOptions,
3230
root: string = process.cwd(),
3331
): NormalizedExeTarget[] => {
3432
const currentPlatform = getCurrentExePlatform();
@@ -156,14 +154,14 @@ export const composeExeConfig = ({
156154
sourceEntry,
157155
target,
158156
}: ComposeExeConfigOptions): ComposedExeConfig => {
159-
const normalizedTargets = resolveExeTargets(exe, root);
160-
161-
if (normalizedTargets.length === 0) {
157+
if (!exe) {
162158
return {
163159
config: {},
164160
};
165161
}
166162

163+
const normalizedTargets = resolveExeTargets(exe, root);
164+
167165
validateExeTargets({
168166
bundle,
169167
targets: normalizedTargets,

packages/core/tests/exe.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,33 @@ const withSupportedNodeRuntime = async <T>(fn: () => Promise<T>) => {
4545
}
4646
};
4747

48+
const withUnsupportedExeHost = async <T>(fn: () => Promise<T>) => {
49+
const originalPlatform = process.platform;
50+
const originalArch = process.arch;
51+
52+
Object.defineProperty(process, 'platform', {
53+
value: 'freebsd',
54+
configurable: true,
55+
});
56+
Object.defineProperty(process, 'arch', {
57+
value: 'riscv64',
58+
configurable: true,
59+
});
60+
61+
try {
62+
return await fn();
63+
} finally {
64+
Object.defineProperty(process, 'platform', {
65+
value: originalPlatform,
66+
configurable: true,
67+
});
68+
Object.defineProperty(process, 'arch', {
69+
value: originalArch,
70+
configurable: true,
71+
});
72+
}
73+
};
74+
4875
describe('experiments.exe', () => {
4976
test('should detect supported Node.js versions', () => {
5077
expect(isExeSupportedNodeVersion('25.7.0')).toBe(true);
@@ -125,6 +152,16 @@ describe('experiments.exe', () => {
125152
);
126153
});
127154

155+
test('should not validate host exe capabilities when exe is disabled', async () => {
156+
await expect(
157+
withUnsupportedExeHost(() =>
158+
composeTestRslibConfig({
159+
format: 'esm',
160+
}),
161+
),
162+
).resolves.toBeTruthy();
163+
});
164+
128165
test('should resolve outputPath separately from fileName', () => {
129166
const resolved = resolveExecutableOutputPath({
130167
environment: {

rstest.config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,13 @@ export const shared: RstestConfig = {
3333
};
3434

3535
export default defineConfig({
36-
projects: ['packages/*', 'tests'],
36+
projects: [
37+
'packages/*',
38+
'tests/rstest.config.ts',
39+
// Keep exe tests in a separate project so eco CI can skip these slower SEA
40+
// cases, while the workflow can still run them in parallel as a dedicated job.
41+
'tests/rstest.exe.config.ts',
42+
],
3743
pool: {
3844
// Leave some workers available for DTS tests to spawn sub processes
3945
maxWorkers: '80%',

scripts/dictionary.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ pxtorem
103103
quxx
104104
rebranded
105105
reduxjs
106+
riscv
106107
rolldown
107108
rootdir
108109
rsbuild

tests/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"test": "rstest",
77
"test:benchmark": "rstest bench",
88
"test:e2e": "playwright test --pass-with-no-tests",
9+
"test:exe": "rstest -c rstest.exe.config.ts",
910
"type-check": "tsc --noEmit"
1011
},
1112
"dependencies": {

tests/rstest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default defineConfig({
77
name: 'integration',
88
setupFiles: ['./setupRstestTests.ts'],
99
include: ['./integration/**/*.test.ts'],
10-
exclude: ['**/node_modules/**'],
10+
exclude: ['**/node_modules/**', './integration/exe/*.test.ts'],
1111
// TODO: Support benchmark in Rstest.
1212
// benchmark: {
1313
// include: ['./benchmark/**/*.bench.ts'],

tests/rstest.exe.config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { defineConfig } from '@rstest/core';
2+
import { shared } from '../rstest.config';
3+
4+
export default defineConfig({
5+
...shared,
6+
name: 'integration-exe',
7+
setupFiles: ['./setupRstestTests.ts'],
8+
include: ['./integration/exe/*.test.ts'],
9+
});

website/docs/en/config/lib/experiments.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ For string targets, Rslib treats the value as a custom Node.js executable path.
175175

176176
This also means that when multiple targets are enabled, the version resolved from a custom binary path affects the suffix of the final output file name.
177177

178+
:::info macOS target signing
179+
180+
`darwin` targets are only signed automatically when the build itself runs on macOS.
181+
182+
If you generate a macOS executable on Linux or Windows, the output remains unsigned. In most cases, you need to sign it on macOS before it can run normally.
183+
184+
:::
185+
178186
Here is an example that generates executables for multiple platforms in a single build:
179187

180188
```ts title="rslib.config.ts"

0 commit comments

Comments
 (0)