mirror of
https://github.com/morluto/rea.git
synced 2026-11-15 19:23:24 +00:00
feat(javascript): make the member-mutation work allowance a runtime setting (#11181)
* feat(javascript): make the member-mutation work allowance a runtime setting The member-mutation alias-state allowance from #11144 was a fixed constant, so a refused source could not be admitted without a code change. Register javascript.member_mutation_alias_states (default 524288, 1 to 8388608 alias states) with the launch seed REA_JAVASCRIPT_MEMBER_MUTATION_ALIAS_STATES. The application, web bundle and reference-source boundaries resolve it from the accepted operation snapshot and launch environment, refuse a malformed seed before analysis, and send it to the workers with each source. A refusal names the setting, its effective value, source and range, and the recovery; worker parents rebuild it from the allowance they sent. Refs #8294 * fix(javascript): keep the setting and recovery of a refused web script A web bundle script refused by the member-mutation allowance kept only its reason and reported limits, so the public unknown lost the setting, value, source and recovery. Carry the refusal's structured limit and remediation on the per-script result and its javascript_analysis unknown, grouping scripts only when that recovery agrees. Assert structured limit facts and the owning formatter's recovery instead of fixed wording. * fix(browser): keep only registered setting limits on a refused web script * feat(javascript): keep syntax facts for a source whose member-mutation phase is refused (#11187) * feat(javascript): keep syntax facts for a source whose member-mutation phase is refused A source refused by the member-mutation work allowance during static analysis lost every fact, so the application graph counted it as skipped. Reference-source import failed outright on such a file. Checkpoint the parser, comment and text facts the static owner can still state, with parse status partial, examination not-examined and refused_phase member-mutations, before reporting the refusal; the semantic phase is not started because it indexes the same mutations. Reference-source import keeps the file's declaration-level imports and records that its CommonJS require calls were not examined. Refs #8294 * test(javascript): compare the reference-source refusal with its owning formatter * feat(javascript): keep a refused web script's parse and text facts A captured script whose member-mutation phase was refused lost every fact in analyze_web_bundle, so it was neither counted as parsed nor kept its vendor markers. The analyzer now returns the script as unavailable with partial facts: refused phase, parse status and the inferences read from script text alone. Findings gathered before the refusal are dropped, because they may have read an incomplete mutation index. The worker parent states the refusal and its setting recovery from the allowance it sent, through the same helper the isolated analyzer uses for every unavailable script. The bundle counts the script as parsed, keeps its text inferences, and its javascript_analysis unknown carries refused_phase. Refs #8294 * chore(mcp): record the member-mutation setting in the advertised summary * fix(javascript): rebuild a parked source worker when the member-mutation allowance changes A worker parked on a resource scope was reused when heap, timeout and precision matched, but its requests carry the allowance it was built with. After update_analysis_settings accepted a new allowance, the next analysis on that scope kept the old one. The reuse check now compares the allowance's value and source, so a changed setting gets a worker built with it. The web bundle worker already takes the allowance per script.
This commit is contained in:
1 parent
94c260017a
commit
0f53849160
54 files changed
+1490
-214
No files matched your search
@@ -15,10 +15,7 @@ import type { OwnedProcessGroup } from "../../../src/process/ProcessOwnership.js
|
||||
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
|
||||
import { ProviderCleanupError } from "../../../src/domain/providerCleanupError.js";
|
||||
import { AnalysisResourceConstraintError } from "../../../src/domain/analysisErrorCore.js";
|
||||
import {
|
||||
JAVASCRIPT_MEMBER_MUTATION_WORK_ALLOWANCE,
|
||||
JAVASCRIPT_MEMBER_MUTATION_WORK_LIMIT,
|
||||
} from "../../../src/domain/javascript/javascriptSemanticWorkAllowance.js";
|
||||
import { JAVASCRIPT_MEMBER_MUTATION_WORK_LIMIT } from "../../../src/domain/javascript/javascriptSemanticWorkAllowance.js";
|
||||
import { projectAnalysisError } from "../../../src/domain/analysisErrorProjection.js";
|
||||
import { spawnOwnedProviderProcess } from "../../../src/process/ProviderProcess.js";
|
||||
import { javaScriptWorkerMemoryLimitBytes } from "../../../src/process/JavaScriptWorkerMemoryLimit.js";
|
||||
@@ -115,6 +112,66 @@ it("reuses one real owned analyzer while retaining distinct source identities an
|
||||
}
|
||||
});
|
||||
|
||||
it("applies a changed member-mutation allowance to the next analysis on the same scope", async () => {
|
||||
const scope = new ArtifactResourceScope();
|
||||
// Four conditional self-selections before one member write (#8294).
|
||||
const file = source(
|
||||
"allowance.js",
|
||||
[
|
||||
"function probe(input, env) { var m; if (env.first) m = env.first.info;",
|
||||
...Array.from(
|
||||
{ length: 4 },
|
||||
(_, index) =>
|
||||
`if (/case${String(index)}/.test(input)) m = m[${String(index % 2)}];`,
|
||||
),
|
||||
"m[1] = input.length; return m; } module.exports = probe;",
|
||||
].join(" "),
|
||||
);
|
||||
try {
|
||||
for (const allowance of [
|
||||
undefined,
|
||||
{ aliasStates: 8, source: "runtime" } as const,
|
||||
undefined,
|
||||
]) {
|
||||
const worker = await createJavaScriptSourceAnalysis(
|
||||
{
|
||||
heapMb: 128,
|
||||
timeoutMs: 30_000,
|
||||
...(allowance === undefined
|
||||
? {}
|
||||
: { memberMutationAllowance: allowance }),
|
||||
},
|
||||
1,
|
||||
{ scope },
|
||||
);
|
||||
try {
|
||||
const result = await worker.analyze(file, {
|
||||
nodes: 100,
|
||||
unknowns: 100,
|
||||
});
|
||||
if (allowance === undefined) {
|
||||
if (!result.ok) throw result.error.error;
|
||||
continue;
|
||||
}
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok)
|
||||
throw new Error("Expected the lowered allowance to refuse");
|
||||
expect(result.error.error).toMatchObject({
|
||||
limit: {
|
||||
setting: "javascript.member_mutation_alias_states",
|
||||
effective_value: 8,
|
||||
source: "runtime",
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
await worker.close();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
await scope.close();
|
||||
}
|
||||
});
|
||||
|
||||
it("recovers finite primitive alternatives after changing precision on the same scope", async () => {
|
||||
const scope = new ArtifactResourceScope();
|
||||
const expression = Array.from(
|
||||
@@ -760,16 +817,26 @@ it("reports the worker heap limit only when the runtime enforces V8 heap flags",
|
||||
}
|
||||
});
|
||||
|
||||
it("names the fixed work allowance a worker refusal reports", async () => {
|
||||
const worker = resourceFailureWorker(
|
||||
'process.versions.bun === undefined ? require("node:v8").getHeapStatistics().heap_size_limit : null',
|
||||
it("sends the accepted member-mutation allowance and names its setting on refusal", async () => {
|
||||
// The fixture reports the allowance the parent sent, as the real worker does.
|
||||
const worker = new JavaScriptAnalysisWorker(
|
||||
{
|
||||
resource: "cpu",
|
||||
limits: {
|
||||
[JAVASCRIPT_MEMBER_MUTATION_WORK_LIMIT]:
|
||||
JAVASCRIPT_MEMBER_MUTATION_WORK_ALLOWANCE,
|
||||
},
|
||||
heapMb: 128,
|
||||
timeoutMs: 30_000,
|
||||
memberMutationAllowance: { aliasStates: 4096, source: "runtime" },
|
||||
},
|
||||
(request) =>
|
||||
spawnOwnedProviderProcess({
|
||||
...request,
|
||||
arguments: [
|
||||
"-e",
|
||||
`process.stdout.write(JSON.stringify({ kind: "ready", heap_limit_bytes: process.versions.bun === undefined ? require("node:v8").getHeapStatistics().heap_size_limit : null }) + "\\n");
|
||||
require("node:readline").createInterface({ input: process.stdin }).once("line", (line) => {
|
||||
const request = JSON.parse(line);
|
||||
process.stdout.write(JSON.stringify({ kind: "failure", id: request.id, reason: "resource", resource: "cpu", limits: { ${JAVASCRIPT_MEMBER_MUTATION_WORK_LIMIT}: request.member_mutation_allowance.alias_states, sent_source: request.member_mutation_allowance.source }, message: "fixture" }) + "\\n");
|
||||
});`,
|
||||
],
|
||||
}),
|
||||
);
|
||||
try {
|
||||
const result = await worker.analyze(
|
||||
@@ -783,13 +850,18 @@ it("names the fixed work allowance a worker refusal reports", async () => {
|
||||
expect(error).toMatchObject({
|
||||
resource: "cpu",
|
||||
retryable: false,
|
||||
remediationAction: undefined,
|
||||
fixedAllowance: {
|
||||
kind: "work",
|
||||
limit: JAVASCRIPT_MEMBER_MUTATION_WORK_ALLOWANCE,
|
||||
unit: "alias states",
|
||||
reportedLimits: {
|
||||
[JAVASCRIPT_MEMBER_MUTATION_WORK_LIMIT]: 4096,
|
||||
sent_source: "runtime",
|
||||
},
|
||||
limit: {
|
||||
setting: "javascript.member_mutation_alias_states",
|
||||
effective_value: 4096,
|
||||
source: "runtime",
|
||||
},
|
||||
});
|
||||
expect(error.fixedAllowance).toBeUndefined();
|
||||
expect(error.remediationAction).toContain("update_analysis_settings");
|
||||
} finally {
|
||||
await worker.close();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user