Skip to content
Open
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
84 changes: 77 additions & 7 deletions lib/update-v8/updateCrates.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import semver from 'semver';
import * as TOML from 'smol-toml';
import { promises as fs } from 'node:fs';
import os from 'node:os';
import path from 'node:path';

import { removeDirectory } from './util.js';
Expand All @@ -15,6 +16,7 @@ export default function updateCrates() {
enumerateTemporalDependencies(),
removeExistingCrates(),
vendorCrates(),
fetchPlaceholderCrates(),
buildManifest(),
generateLockfile(),
updateGYP(),
Expand Down Expand Up @@ -78,15 +80,23 @@ function vendorCrates() {
await fs.mkdir(nodeVendor);

const subtasks = [];
const rustVersions = [];
ctx.rustVersions = [];
ctx.placeholderCrates = [];
for (const dir of await fs.readdir(chromiumVendor)) {
const crate = await getCrateInfo(dir);
if (!crate || !ctx.temporalCrates.has(`${crate.name}@${crate.version}`)) continue;
if (crate.name === 'temporal_capi') {
ctx.temporalCAPIDirectory = dir;
}
// Fetch replace_with placeholders from crates.io.
// This is a stop-gap fix that only works as long as the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems like an incomplete sentence.

// See https://chromium-review.googlesource.com/c/chromium/src/+/8527739
if (crate.metadata?.gnrt?.is_placeholder) {
ctx.placeholderCrates.push({ dir, name: crate.name, version: crate.version });
continue;
}
if (crate['rust-version']) {
rustVersions.push(crate['rust-version']);
ctx.rustVersions.push(crate['rust-version']);
}
subtasks.push({
title: dir,
Expand All @@ -100,11 +110,6 @@ function vendorCrates() {
});
}

if (rustVersions.length) {
const msrv = rustVersions.map(semver.coerce).reduce((a, b) => (semver.gt(a, b) ? a : b));
ctx.msrv = `${msrv.major}.${msrv.minor}`;
}

return task.newListr(subtasks, { concurrent: ctx.concurrent });

async function getCrateInfo(crate) {
Expand All @@ -121,10 +126,75 @@ function vendorCrates() {
};
}

// TODO(joyeecheung): Instead of fetching the crates from crates.io,
// generate the replacement crates from Chromium's data. e.g.
// For `replace_with = "//third_party/rust/icu4x_data:lib"`
// in gnrt_config.toml, copy the `.rs.data` files that the dependent
// crates use (`impl_<marker>!(Baked)` in their provider.rs) from
// third_party/rust/icu4x_data/src/data/common and generate a data/mod.rs in the
// upstream crate layout.
// See https://github.com/nodejs/node-core-utils/pull/1117
function fetchPlaceholderCrates() {
return {
title: 'Fetch placeholder crates from crates.io',
skip: (ctx) => ctx.placeholderCrates.length === 0 && 'No placeholder crates',
task: async(ctx) => {
const nodeVendor = path.join(ctx.nodeDir, nodeCratesDir, 'vendor');
const chromiumPatches = path.join(ctx.nodeDir, chromiumCratesDir, 'patches');
for (const { dir, name } of ctx.placeholderCrates) {
try {
await fs.access(path.join(chromiumPatches, dir));
} catch {
continue;
}
throw new Error(`Detected Chromium patches ${name} in ${chromiumPatches}/${dir}, ` +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

'the stop-gap fix of fetching crates from crates.io no longer work.');
}

// Vendor a temporary package that depends on on the crates to fetch them.
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), 'node-crates-'));
try {
const manifest = {
package: { name: 'placeholder_crates', version: '0.0.0', edition: '2021' },
dependencies: Object.fromEntries(ctx.placeholderCrates.map(({ name, version }) => (
[name, { version: `=${version}`, 'default-features': false }]
)))
};
await fs.writeFile(path.join(tmpDir, 'Cargo.toml'), TOML.stringify(manifest));
await fs.mkdir(path.join(tmpDir, 'src'));
await fs.writeFile(path.join(tmpDir, 'src/lib.rs'), '');
const vendorDir = path.join(tmpDir, 'vendor');
await forceRunAsync(ctx.cargo, ['vendor', '--quiet', '--versioned-dirs', vendorDir], {
ignoreFailure: false,
spawnArgs: { cwd: tmpDir }
});

for (const { dir, name, version } of ctx.placeholderCrates) {
const dest = path.join(nodeVendor, dir);
await fs.cp(path.join(vendorDir, `${name}-${version}`), dest, { recursive: true });
await fs.writeFile(path.join(dest, '.cargo-checksum.json'), '{"files":{}}\n');
const crate = TOML.parse(await fs.readFile(path.join(dest, 'Cargo.toml'), 'utf8'));
if (crate.package['rust-version']) {
ctx.rustVersions.push(crate.package['rust-version']);
}
}
} finally {
await removeDirectory(tmpDir);
}
}
};
}

function buildManifest() {
return {
title: 'Build new manifest',
task: async(ctx) => {
if (ctx.rustVersions.length) {
const msrv = ctx.rustVersions.map(semver.coerce)
.reduce((a, b) => (semver.gt(a, b) ? a : b));
ctx.msrv = `${msrv.major}.${msrv.minor}`;
}

const sourceManifest = TOML.parse(
await fs.readFile(path.join(ctx.nodeDir, chromiumCratesDir, 'Cargo.toml'), 'utf8')
);
Expand Down
Loading