fix(app): avoid unsupported Android array sorting (#3241)
Hermes in the production Android app does not provide Array.prototype.toSorted. Multi-host project selection and provider cache eviction could therefore crash when they reached deterministic sorting paths.
This commit is contained in:
@@ -136,7 +136,7 @@ export function createProviderSnapshotCache(
|
||||
}
|
||||
|
||||
let totalBytes = entries.reduce((total, entry) => total + entry.bytes, 0);
|
||||
const retainedEntries = entries.toSorted(oldestFirst);
|
||||
const retainedEntries = [...entries].sort(oldestFirst);
|
||||
while (totalBytes > maxBytes) {
|
||||
const evicted = retainedEntries.shift();
|
||||
if (!evicted) break;
|
||||
@@ -186,7 +186,7 @@ export function createProviderSnapshotCache(
|
||||
if (canStoreIncoming) projectedBytes += incomingBytes;
|
||||
|
||||
const keysToRemove: string[] = [];
|
||||
for (const candidate of retainedEntries.toSorted(oldestFirst)) {
|
||||
for (const candidate of [...retainedEntries].sort(oldestFirst)) {
|
||||
if (projectedBytes <= maxBytes) break;
|
||||
projectedBytes -= candidate.bytes;
|
||||
keysToRemove.push(candidate.key);
|
||||
|
||||
@@ -194,7 +194,7 @@ export function resolveEquivalentHostProjectCandidate(input: {
|
||||
(project) => project.projectKey === input.candidate.projectKey,
|
||||
);
|
||||
if (equivalents.length === 0) return null;
|
||||
return equivalents.toSorted((left, right) =>
|
||||
return equivalents.sort((left, right) =>
|
||||
compareHostProjectsForServer(left, right, input.serverId),
|
||||
)[0]!;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getWorktreeSupportForHostProject,
|
||||
hostProjectFromRoute,
|
||||
hostProjectFromWorkspace,
|
||||
resolveEquivalentHostProjectCandidate,
|
||||
} from "./host-project-model";
|
||||
import { normalizeWorkspaceDescriptor } from "@/stores/session-store";
|
||||
|
||||
@@ -36,6 +37,31 @@ function project(): HostProjectListItem {
|
||||
}
|
||||
|
||||
describe("host project lookups", () => {
|
||||
test("resolves equivalent projects without Array.prototype.toSorted", () => {
|
||||
const descriptor = Object.getOwnPropertyDescriptor(Array.prototype, "toSorted");
|
||||
Reflect.deleteProperty(Array.prototype, "toSorted");
|
||||
const first = project();
|
||||
first.viewKey = "view:first";
|
||||
first.projectName = "First";
|
||||
const second = project();
|
||||
second.viewKey = "view:second";
|
||||
second.projectName = "Second";
|
||||
const projects = [second, first];
|
||||
|
||||
try {
|
||||
expect(
|
||||
resolveEquivalentHostProjectCandidate({
|
||||
candidate: first,
|
||||
projects,
|
||||
serverId: "host-a",
|
||||
}),
|
||||
).toBe(first);
|
||||
expect(projects).toEqual([second, first]);
|
||||
} finally {
|
||||
if (descriptor) Reflect.defineProperty(Array.prototype, "toSorted", descriptor);
|
||||
}
|
||||
});
|
||||
|
||||
test("returns host-local ids and roots without falling back to the grouping key", () => {
|
||||
expect(getHostProjectId(project(), "host-b")).toBe("prj_b");
|
||||
expect(getHostProjectSourceDirectory(project(), "host-b")).toBe("/repo/b");
|
||||
|
||||
Reference in New Issue
Block a user