File size: 2,029 Bytes
4e23b01 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | import { ErrorCodes, Error2 } from '#/errors';
import { getShellPathBridge } from '#/_base/execEnv/shellPathBridge';
import type { Runtime, RuntimeBinding, RuntimeWorkspaceRoots } from './runtime';
export type { RuntimeWorkspaceRoots } from './runtime';
export class RuntimeWorkspaceView {
readonly binding: RuntimeBinding;
readonly generation: string;
readonly workDir: string;
readonly additionalDirs: readonly string[];
readonly roots: readonly string[];
constructor(
readonly runtime: Runtime,
roots: RuntimeWorkspaceRoots,
) {
this.binding = {
workspaceId: runtime.identity.workspaceId,
runtimeId: runtime.identity.runtimeId,
};
this.generation = runtime.identity.generation;
const mapped = runtime.workspace.mapRoots(roots);
this.workDir = runtime.path.resolve(mapped.workDir);
this.additionalDirs = [...new Set((mapped.additionalDirs ?? []).map((root) => runtime.path.resolve(root)))];
this.roots = [this.workDir, ...this.additionalDirs];
}
resolve(path: string, cwd = this.workDir): string {
const env = this.runtime.environment;
const bridged = env.pathClass === 'win32' ? getShellPathBridge(env).fromShellPath(path) : path;
return this.runtime.path.isAbsolute(bridged)
? this.runtime.path.resolve(bridged)
: this.runtime.path.resolve(cwd, bridged);
}
assertAllowed(path: string): string {
const resolved = this.runtime.path.resolve(path);
if (this.roots.some((root) => contains(this.runtime, root, resolved))) return resolved;
throw new Error2(
ErrorCodes.FS_PATH_ESCAPES,
`path ${path} is outside runtime workspace ${this.binding.runtimeId}`,
{ details: { path: resolved } },
);
}
}
function contains(runtime: Runtime, root: string, candidate: string): boolean {
const relative = runtime.path.relative(root, candidate);
if (relative === '') return true;
return relative !== '..' && !relative.startsWith(`..${runtime.path.separator}`) && !runtime.path.isAbsolute(relative);
}
|