|
|
@@ -1,6 +1,9 @@
|
|
|
|
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", 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. */
|
|
|
@@ -116,8 +119,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);
|
|
|
|