Expose bounded post-build Source Check failures to authors (#641)
This commit is contained in:
parent
6f5b5265b6
commit
94ddc8bedf
@@ -1,6 +1,13 @@
|
|||||||
import { constants } from "node:fs";
|
import { constants } from "node:fs";
|
||||||
import { open } from "node:fs/promises";
|
import { open } from "node:fs/promises";
|
||||||
|
|
||||||
|
const admissionFailure = (
|
||||||
|
code: string,
|
||||||
|
kind: "file-bytes" | "total-bytes" | "owner-bytes" | "candidates",
|
||||||
|
measured: number,
|
||||||
|
limit: number,
|
||||||
|
) => Object.assign(Error(code), { metadataAdmission: { kind, measured, limit } });
|
||||||
|
|
||||||
/** Admission estimates, not a hard V8 heap limit. A process/cgroup ceiling is
|
/** Admission estimates, not a hard V8 heap limit. A process/cgroup ceiling is
|
||||||
* still required. Charge input, parse trees and derived indexes before reading
|
* still required. Charge input, parse trees and derived indexes before reading
|
||||||
* or parsing. Each live candidate retains its reservation until explicit close. */
|
* or parsing. Each live candidate retains its reservation until explicit close. */
|
||||||
@@ -27,7 +34,8 @@ export class CandidateMetadataBudget {
|
|||||||
}
|
}
|
||||||
acquire(owner: string) {
|
acquire(owner: string) {
|
||||||
if (!owner || owner.length > 4096) throw Error("INVALID_CANDIDATE_METADATA_OWNER");
|
if (!owner || owner.length > 4096) throw Error("INVALID_CANDIDATE_METADATA_OWNER");
|
||||||
if (this.scopes >= this.limits.candidates) throw Error("CANDIDATE_METADATA_LIMIT");
|
if (this.scopes >= this.limits.candidates)
|
||||||
|
throw admissionFailure("CANDIDATE_METADATA_LIMIT", "candidates", this.scopes + 1, this.limits.candidates);
|
||||||
this.scopes++;
|
this.scopes++;
|
||||||
let bytes = 0,
|
let bytes = 0,
|
||||||
closed = false;
|
closed = false;
|
||||||
@@ -35,8 +43,10 @@ export class CandidateMetadataBudget {
|
|||||||
if (closed) throw Error("CANDIDATE_METADATA_CLOSED");
|
if (closed) throw Error("CANDIDATE_METADATA_CLOSED");
|
||||||
if (!Number.isSafeInteger(amount) || amount < 0) throw Error("INVALID_CANDIDATE_METADATA_CHARGE");
|
if (!Number.isSafeInteger(amount) || amount < 0) throw Error("INVALID_CANDIDATE_METADATA_CHARGE");
|
||||||
const owned = this.owners.get(owner) ?? 0;
|
const owned = this.owners.get(owner) ?? 0;
|
||||||
if (this.bytes + amount > this.limits.bytes || owned + amount > this.limits.ownerBytes)
|
if (this.bytes + amount > this.limits.bytes)
|
||||||
throw Error("CANDIDATE_METADATA_LIMIT");
|
throw admissionFailure("CANDIDATE_METADATA_LIMIT", "total-bytes", this.bytes + amount, this.limits.bytes);
|
||||||
|
if (owned + amount > this.limits.ownerBytes)
|
||||||
|
throw admissionFailure("CANDIDATE_METADATA_LIMIT", "owner-bytes", owned + amount, this.limits.ownerBytes);
|
||||||
bytes += amount;
|
bytes += amount;
|
||||||
this.bytes += amount;
|
this.bytes += amount;
|
||||||
this.owners.set(owner, owned + amount);
|
this.owners.set(owner, owned + amount);
|
||||||
@@ -116,8 +126,8 @@ export async function readCandidateMetadata(
|
|||||||
let releaseInput: (() => void) | undefined;
|
let releaseInput: (() => void) | undefined;
|
||||||
try {
|
try {
|
||||||
const stat = await handle.stat();
|
const stat = await handle.stat();
|
||||||
if (!stat.isFile() || !Number.isSafeInteger(stat.size) || stat.size > limit)
|
if (!stat.isFile() || !Number.isSafeInteger(stat.size)) throw Error("CANDIDATE_METADATA_FILE_LIMIT");
|
||||||
throw Error("CANDIDATE_METADATA_FILE_LIMIT");
|
if (stat.size > limit) throw admissionFailure("CANDIDATE_METADATA_FILE_LIMIT", "file-bytes", stat.size, limit);
|
||||||
// Reserve the input buffer and UTF-16 decoding before allocating either.
|
// Reserve the input buffer and UTF-16 decoding before allocating either.
|
||||||
releaseInput = scope.reserve((stat.size + 1) * 3);
|
releaseInput = scope.reserve((stat.size + 1) * 3);
|
||||||
const bytes = Buffer.alloc(stat.size + 1);
|
const bytes = Buffer.alloc(stat.size + 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user