fix(natives): preserve workspace addons
This commit is contained in:
@@ -20,6 +20,10 @@
|
||||
|
||||
- Fixed the `computer` tool advertising Wayland support that never worked: on the default rootless XWayland (GNOME/KDE/sway) the X11 root window has no readable pixmap, so root `GetImage` failed on every screenshot with a raw `BadMatch` protocol dump. `Monitor::all` now probes root drawability at initialization and fails fast with an actionable `DESKTOP_BACKEND_UNAVAILABLE` message naming the rootless-XWayland constraint, and `docs/computer-use.md` now lists rootless XWayland as unsupported ([#7085](https://github.com/can1357/oh-my-pi/issues/7085)).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed workspace native addon loads preferring an installed leaf package over the workspace build ([#7059](https://github.com/can1357/oh-my-pi/pull/7059) by [@GratefulDave](https://github.com/GratefulDave)).
|
||||
|
||||
## [17.2.0] - 2026-07-30
|
||||
|
||||
### Changed
|
||||
@@ -29,7 +33,6 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed workspace native addon loads preferring an installed leaf package over the workspace build ([#7059](https://github.com/can1357/oh-my-pi/pull/7059) by [@GratefulDave](https://github.com/GratefulDave)).
|
||||
|
||||
## [17.1.8] - 2026-07-28
|
||||
|
||||
|
||||
+1
@@ -57,6 +57,7 @@ export function resolveLoaderCandidates(input: ResolveLoaderCandidatesInput): st
|
||||
|
||||
export interface InitLoaderContextOverrides {
|
||||
nativeDir?: string;
|
||||
platform?: NodeJS.Platform | string;
|
||||
isCompiledBinary?: boolean;
|
||||
leafPackageDir?: string | null;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,8 @@ export function shouldStageNodeModulesAddon({ platform, isCompiledBinary, native
|
||||
// Check both separators independently of the host's `path.sep`: this helper
|
||||
// is shared by the loader (running on Windows with `\`) and the test suite
|
||||
// (typically running on POSIX hosts when CI executes the regression test).
|
||||
return nativeDir.includes("\\node_modules\\") || nativeDir.includes("/node_modules/");
|
||||
const normalizedNativeDir = nativeDir.toLowerCase();
|
||||
return normalizedNativeDir.includes("\\node_modules\\") || normalizedNativeDir.includes("/node_modules/");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -699,17 +700,18 @@ function buildHelpMessage(ctx) {
|
||||
* helpers from this file doesn't trigger AVX2 detection or filesystem probes.
|
||||
*/
|
||||
/**
|
||||
* @param {{ nativeDir?: string; isCompiledBinary?: boolean; leafPackageDir?: string | null }} [overrides]
|
||||
* @param {{ nativeDir?: string; platform?: NodeJS.Platform | string; isCompiledBinary?: boolean; leafPackageDir?: string | null }} [overrides]
|
||||
*/
|
||||
export function initLoaderContext(overrides = {}) {
|
||||
const platformTag = `${process.platform}-${process.arch}`;
|
||||
const platform = overrides.platform ?? process.platform;
|
||||
const platformTag = `${platform}-${process.arch}`;
|
||||
const packageVersion = packageJson.version;
|
||||
const nativeDir = overrides.nativeDir ?? path.join(import.meta.dir, "..", "native");
|
||||
const execDir = path.dirname(process.execPath);
|
||||
const nativesDir = getNativesDir();
|
||||
const versionedDir = path.join(nativesDir, packageVersion);
|
||||
const userDataDir =
|
||||
process.platform === "win32"
|
||||
platform === "win32"
|
||||
? path.join(process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local"), "omp")
|
||||
: path.join(os.homedir(), ".local", "bin");
|
||||
|
||||
@@ -720,7 +722,7 @@ export function initLoaderContext(overrides = {}) {
|
||||
env: process.env,
|
||||
importMetaUrl: import.meta.url,
|
||||
});
|
||||
const normalizedNativeDir = nativeDir.toLowerCase();
|
||||
const normalizedNativeDir = platform === "win32" ? nativeDir.toLowerCase() : nativeDir;
|
||||
const isWorkspaceLoad =
|
||||
!isCompiledBinary &&
|
||||
!normalizedNativeDir.includes("\\node_modules\\") &&
|
||||
@@ -732,9 +734,9 @@ export function initLoaderContext(overrides = {}) {
|
||||
? resolveLeafPackageDir(platformTag)
|
||||
: overrides.leafPackageDir;
|
||||
const stageFromNodeModules = shouldStageNodeModulesAddon({
|
||||
platform: process.platform,
|
||||
platform,
|
||||
isCompiledBinary,
|
||||
nativeDir,
|
||||
nativeDir: normalizedNativeDir,
|
||||
});
|
||||
|
||||
const selectedVariant = resolveCpuVariant(getVariantOverride());
|
||||
|
||||
@@ -115,27 +115,39 @@ describe("windows native addon staging", () => {
|
||||
expect(candidates).not.toContain(userDataBaseline);
|
||||
});
|
||||
|
||||
it("omits leaf-package candidates only for workspace loads", () => {
|
||||
it("classifies only Windows node_modules paths case-insensitively", () => {
|
||||
const leafPackageDir = "/tmp/node_modules/@oh-my-pi/pi-natives-darwin-arm64";
|
||||
const uppercaseNodeModulesNativeDir = "/tmp/NODE_MODULES/@oh-my-pi/pi-natives/native";
|
||||
const variantCacheKey = "__PI_NATIVE_VARIANT_CACHE";
|
||||
const previousVariantCache = process.env[variantCacheKey];
|
||||
try {
|
||||
const workspace = initLoaderContext({
|
||||
platform: "linux",
|
||||
isCompiledBinary: false,
|
||||
nativeDir: "/tmp/oh-my-pi/packages/natives/native",
|
||||
leafPackageDir,
|
||||
});
|
||||
const installed = initLoaderContext({
|
||||
platform: "linux",
|
||||
isCompiledBinary: false,
|
||||
nativeDir: "/tmp/node_modules/@oh-my-pi/pi-natives/native",
|
||||
leafPackageDir,
|
||||
});
|
||||
const installedWithUppercaseNodeModules = initLoaderContext({
|
||||
const uppercaseWorkspace = initLoaderContext({
|
||||
platform: "linux",
|
||||
isCompiledBinary: false,
|
||||
nativeDir: "/tmp/NODE_MODULES/@oh-my-pi/pi-natives/native",
|
||||
nativeDir: uppercaseNodeModulesNativeDir,
|
||||
leafPackageDir,
|
||||
});
|
||||
const leafCandidate = path.join(leafPackageDir, workspace.addonFilenames[0]);
|
||||
const uppercaseWindowsInstall = initLoaderContext({
|
||||
platform: "win32",
|
||||
isCompiledBinary: false,
|
||||
nativeDir: uppercaseNodeModulesNativeDir,
|
||||
leafPackageDir,
|
||||
});
|
||||
const leafCandidate = path.join(leafPackageDir, installed.addonFilenames[0]);
|
||||
const windowsLeafCandidate = path.join(leafPackageDir, uppercaseWindowsInstall.addonFilenames[0]);
|
||||
const workspaceCandidate = path.join(uppercaseNodeModulesNativeDir, uppercaseWorkspace.addonFilenames[0]);
|
||||
|
||||
expect(workspace.isWorkspaceLoad).toBe(true);
|
||||
expect(workspace.leafPackageDir).toBeNull();
|
||||
@@ -143,9 +155,16 @@ describe("windows native addon staging", () => {
|
||||
expect(installed.isWorkspaceLoad).toBe(false);
|
||||
expect(installed.leafPackageDir).toBe(leafPackageDir);
|
||||
expect(installed.candidates).toContain(leafCandidate);
|
||||
expect(installedWithUppercaseNodeModules.isWorkspaceLoad).toBe(false);
|
||||
expect(installedWithUppercaseNodeModules.leafPackageDir).toBe(leafPackageDir);
|
||||
expect(installedWithUppercaseNodeModules.candidates).toContain(leafCandidate);
|
||||
expect(installed.candidates[0]).toBe(leafCandidate);
|
||||
|
||||
expect(uppercaseWorkspace.isWorkspaceLoad).toBe(true);
|
||||
expect(uppercaseWorkspace.leafPackageDir).toBeNull();
|
||||
expect(uppercaseWorkspace.candidates[0]).toBe(workspaceCandidate);
|
||||
|
||||
expect(uppercaseWindowsInstall.isWorkspaceLoad).toBe(false);
|
||||
expect(uppercaseWindowsInstall.leafPackageDir).toBe(leafPackageDir);
|
||||
expect(uppercaseWindowsInstall.stageFromNodeModules).toBe(true);
|
||||
expect(uppercaseWindowsInstall.candidates).toContain(windowsLeafCandidate);
|
||||
} finally {
|
||||
if (previousVariantCache === undefined) delete process.env[variantCacheKey];
|
||||
else process.env[variantCacheKey] = previousVariantCache;
|
||||
|
||||
Reference in New Issue
Block a user