mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(browser): report an out-of-range script_index as a selection fault (#6979)
* fix(browser): report an out-of-range script_index as a selection fault A valid export_web_scripts manifest without the selected script_index was reported as an invalid_format input issue, as if the manifest file were malformed. It is now an out_of_range issue on script_index with the valid bounds, or invalid_value when the manifest has no scripts. * test(browser): keep the out-of-range index case in its own block --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
1 parent
e9b21aadc5
commit
046ec56d16
2 files changed
+76
-4
No files matched your search
@@ -6,7 +6,10 @@ import { readStableArtifact } from "../../artifacts/readStableArtifact.js";
|
|||||||
import { normalizeArtifactPath } from "../../artifacts/ArtifactPaths.js";
|
import { normalizeArtifactPath } from "../../artifacts/ArtifactPaths.js";
|
||||||
import type { WebScriptArtifactPort } from "../../application/WebScriptArtifactPort.js";
|
import type { WebScriptArtifactPort } from "../../application/WebScriptArtifactPort.js";
|
||||||
import type { ExecutionOptions } from "../../application/AnalysisProvider.js";
|
import type { ExecutionOptions } from "../../application/AnalysisProvider.js";
|
||||||
import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
|
import {
|
||||||
|
AnalysisCapabilityUnavailableError,
|
||||||
|
AnalysisInputError,
|
||||||
|
} from "../../domain/analysisErrorCore.js";
|
||||||
import { isPathWithinRoot } from "../../domain/localPath.js";
|
import { isPathWithinRoot } from "../../domain/localPath.js";
|
||||||
import { err, ok } from "../../domain/result.js";
|
import { err, ok } from "../../domain/result.js";
|
||||||
import type { SelectedWebScriptInput } from "../../domain/webScriptArtifacts.js";
|
import type { SelectedWebScriptInput } from "../../domain/webScriptArtifacts.js";
|
||||||
@@ -15,7 +18,6 @@ import {
|
|||||||
decodeWebArtifact,
|
decodeWebArtifact,
|
||||||
readWebArtifactJson,
|
readWebArtifactJson,
|
||||||
webArtifactReadError,
|
webArtifactReadError,
|
||||||
WebArtifactFormatFailure,
|
|
||||||
type WebArtifactReadContext,
|
type WebArtifactReadContext,
|
||||||
} from "./WebArtifactReads.js";
|
} from "./WebArtifactReads.js";
|
||||||
|
|
||||||
@@ -64,9 +66,24 @@ export class LocalWebScriptArtifacts implements WebScriptArtifactPort {
|
|||||||
const manifest = webScriptExportManifestSchema.parse(manifestBytes.value);
|
const manifest = webScriptExportManifestSchema.parse(manifestBytes.value);
|
||||||
field = ["script_index"];
|
field = ["script_index"];
|
||||||
const selected = manifest.scripts[input.script_index];
|
const selected = manifest.scripts[input.script_index];
|
||||||
|
// A valid manifest without this index is a caller selection fault.
|
||||||
if (selected === undefined)
|
if (selected === undefined)
|
||||||
throw new WebArtifactFormatFailure(
|
return err(
|
||||||
`No script at index ${String(input.script_index)}; manifest contains ${String(manifest.scripts.length)} scripts.`,
|
new AnalysisInputError(this.operation, undefined, [
|
||||||
|
manifest.scripts.length === 0
|
||||||
|
? {
|
||||||
|
path: ["script_index"],
|
||||||
|
reason: "invalid_value",
|
||||||
|
message: "The selected manifest contains no scripts.",
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
path: ["script_index"],
|
||||||
|
reason: "out_of_range",
|
||||||
|
minimum: 0,
|
||||||
|
maximum: manifest.scripts.length - 1,
|
||||||
|
message: `No script at index ${String(input.script_index)}; the manifest contains ${String(manifest.scripts.length)} scripts.`,
|
||||||
|
},
|
||||||
|
]),
|
||||||
);
|
);
|
||||||
if (selected.content.state !== "exported")
|
if (selected.content.state !== "exported")
|
||||||
return err(
|
return err(
|
||||||
|
|||||||
@@ -294,3 +294,58 @@ describe("caller-selected web module files", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("selected captured script index", () => {
|
||||||
|
it("reports an index past the manifest's scripts as an out-of-range selection", async () => {
|
||||||
|
const f = await fixture();
|
||||||
|
const response = await new LocalWebModuleArtifacts().load({
|
||||||
|
manifest_path: f.manifestPath,
|
||||||
|
script_index: 5,
|
||||||
|
});
|
||||||
|
if (response.ok) throw new Error("expected an out-of-range index");
|
||||||
|
expect(projectAnalysisError(response.error)).toMatchObject({
|
||||||
|
code: "invalid_request",
|
||||||
|
details: {
|
||||||
|
issues: [
|
||||||
|
{
|
||||||
|
path: ["script_index"],
|
||||||
|
reason: "out_of_range",
|
||||||
|
minimum: 0,
|
||||||
|
maximum: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("distinguishes an empty valid manifest from a malformed manifest", async () => {
|
||||||
|
const f = await fixture();
|
||||||
|
const parsed: unknown = JSON.parse(await readFile(f.manifestPath, "utf8"));
|
||||||
|
const manifest = webScriptExportResultSchema
|
||||||
|
.omit({ manifest: true })
|
||||||
|
.parse(parsed);
|
||||||
|
manifest.scripts = [];
|
||||||
|
await writeFile(f.manifestPath, JSON.stringify(manifest));
|
||||||
|
|
||||||
|
const artifacts = new LocalWebModuleArtifacts();
|
||||||
|
const input = { manifest_path: f.manifestPath, script_index: 0 };
|
||||||
|
const empty = await artifacts.load(input);
|
||||||
|
if (empty.ok) throw new Error("expected an empty-manifest selection fault");
|
||||||
|
expect(projectAnalysisError(empty.error)).toMatchObject({
|
||||||
|
code: "invalid_request",
|
||||||
|
details: {
|
||||||
|
issues: [{ path: ["script_index"], reason: "invalid_value" }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await writeFile(f.manifestPath, "{");
|
||||||
|
const malformed = await artifacts.load(input);
|
||||||
|
if (malformed.ok) throw new Error("expected a malformed manifest fault");
|
||||||
|
expect(projectAnalysisError(malformed.error)).toMatchObject({
|
||||||
|
code: "invalid_request",
|
||||||
|
details: {
|
||||||
|
issues: [{ path: ["manifest_path"], reason: "invalid_format" }],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in new issue
Block a user