Skip to content

Commit 8adebda

Browse files
gregmagolanalexeagle
authored andcommitted
fix(builtin): make linker deterministic when resolving from manifest & fix link_workspace_root with no runfiles
1 parent 11ce24c commit 8adebda

File tree

3 files changed

+40
-7
lines changed

3 files changed

+40
-7
lines changed

internal/linker/index.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
1212
const fs = require("fs");
1313
const path = require("path");
1414
const VERBOSE_LOGS = !!process.env['VERBOSE_LOGS'];
15+
const BAZEL_OUT_REGEX = /(\/bazel-out\/|\/bazel-~1\/x64_wi~1\/)/;
1516
function log_verbose(...m) {
1617
if (VERBOSE_LOGS)
1718
console.error('[link_node_modules.js]', ...m);
@@ -124,7 +125,7 @@ function resolveRoot(root, startCwd, isExecroot, runfiles) {
124125
if (isExecroot) {
125126
return root ? `${startCwd}/external/${root}` : `${startCwd}/node_modules`;
126127
}
127-
const match = startCwd.match(/(\/bazel-out\/|\/bazel-~1\/x64_wi~1\/)/);
128+
const match = startCwd.match(BAZEL_OUT_REGEX);
128129
if (!match) {
129130
if (!root) {
130131
return `${startCwd}/node_modules`;
@@ -176,14 +177,22 @@ class Runfiles {
176177
lookupDirectory(dir) {
177178
if (!this.manifest)
178179
return undefined;
180+
let result;
179181
for (const [k, v] of this.manifest) {
180182
if (k.startsWith(`${dir}/external`))
181183
continue;
182184
if (k.startsWith(dir)) {
183185
const l = k.length - dir.length;
184-
return v.substring(0, v.length - l);
186+
const maybe = v.substring(0, v.length - l);
187+
if (maybe.match(BAZEL_OUT_REGEX)) {
188+
return maybe;
189+
}
190+
else {
191+
result = maybe;
192+
}
185193
}
186194
}
195+
return result;
187196
}
188197
loadRunfilesManifest(manifestPath) {
189198
log_verbose(`using runfiles manifest ${manifestPath}`);
@@ -470,6 +479,13 @@ function main(args, runfiles) {
470479
}
471480
try {
472481
target = runfiles.resolve(runfilesPath);
482+
if (runfiles.manifest && root == 'execroot' && modulePath.startsWith(`${bin}/`)) {
483+
if (!target.includes(`/${bin}/`)) {
484+
const e = new Error(`could not resolve modulePath ${modulePath}`);
485+
e.code = 'MODULE_NOT_FOUND';
486+
throw e;
487+
}
488+
}
473489
}
474490
catch (_a) {
475491
target = '<runfiles resolution failed>';

internal/linker/link_node_modules.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import * as path from 'path';
99
// Run Bazel with --define=VERBOSE_LOGS=1 to enable this logging
1010
const VERBOSE_LOGS = !!process.env['VERBOSE_LOGS'];
1111

12+
// NB: on windows thanks to legacy 8-character path segments it might be like
13+
// c:/b/ojvxx6nx/execroot/build_~1/bazel-~1/x64_wi~1/bin/internal/npm_in~1/test
14+
const BAZEL_OUT_REGEX = /(\/bazel-out\/|\/bazel-~1\/x64_wi~1\/)/;
15+
1216
function log_verbose(...m: string[]) {
1317
if (VERBOSE_LOGS) console.error('[link_node_modules.js]', ...m);
1418
}
@@ -175,9 +179,7 @@ async function resolveRoot(
175179
// runfiles on rbe, bazel runs the process in a directory such as
176180
// `/b/f/w/bazel-out/k8-fastbuild/bin/path/to/pkg/some_test.sh.runfiles/my_wksp`. From here we can
177181
// determine the execroot `b/f/w` by finding the first instance of bazel-out.
178-
// NB: on windows thanks to legacy 8-character path segments it might be like
179-
// c:/b/ojvxx6nx/execroot/build_~1/bazel-~1/x64_wi~1/bin/internal/npm_in~1/test
180-
const match = startCwd.match(/(\/bazel-out\/|\/bazel-~1\/x64_wi~1\/)/);
182+
const match = startCwd.match(BAZEL_OUT_REGEX);
181183
if (!match) {
182184
// No execroot found. This can happen if we are inside a nodejs_image or a nodejs_binary is
183185
// run manually.
@@ -278,6 +280,7 @@ export class Runfiles {
278280
lookupDirectory(dir: string): string|undefined {
279281
if (!this.manifest) return undefined;
280282

283+
let result: string|undefined;
281284
for (const [k, v] of this.manifest) {
282285
// Account for Bazel --legacy_external_runfiles
283286
// which pollutes the workspace with 'my_wksp/external/...'
@@ -289,9 +292,15 @@ export class Runfiles {
289292
// calculate l = length(`/semver/LICENSE`)
290293
if (k.startsWith(dir)) {
291294
const l = k.length - dir.length;
292-
return v.substring(0, v.length - l);
295+
const maybe = v.substring(0, v.length - l);
296+
if (maybe.match(BAZEL_OUT_REGEX)) {
297+
return maybe;
298+
} else {
299+
result = maybe;
300+
}
293301
}
294302
}
303+
return result;
295304
}
296305

297306

@@ -731,6 +740,15 @@ export async function main(args: string[], runfiles: Runfiles) {
731740
}
732741
try {
733742
target = runfiles.resolve(runfilesPath);
743+
// if we're resolving from a manifest then make sure we don't resolve
744+
// into the source tree when we are expecting the output tree
745+
if (runfiles.manifest && root == 'execroot' && modulePath.startsWith(`${bin}/`)) {
746+
if (!target.includes(`/${bin}/`)) {
747+
const e = new Error(`could not resolve modulePath ${modulePath}`);
748+
(e as any).code = 'MODULE_NOT_FOUND';
749+
throw e;
750+
}
751+
}
734752
} catch {
735753
target = '<runfiles resolution failed>';
736754
}

internal/linker/test/workspace_link/BUILD.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ jasmine_node_test(
44
name = "test",
55
srcs = ["test.js"],
66
link_workspace_root = True,
7-
tags = ["fix-windows"],
87
templated_args = ["--nobazel_patch_module_resolver"],
98
deps = [
109
"//internal/linker/test/workspace_link/bar",

0 commit comments

Comments
 (0)