mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-05 08:13:06 +08:00
Keep the reply scanner in a constant object
A native build of a program that installs the C scanner but decodes no reply, such as the self-hosted source parser and CommonJS checks, failed at startup with "Cannot access 'valueEnd' before initialization": the build left the module variable uninitialized because its only other use was the assignment in useNativeJsonValueEnd, which checks it first. The scanner is now a property of a constant object that the decoders and useNativeJsonValueEnd read, so it is initialized in every program.
This commit is contained in:
@@ -104,15 +104,20 @@ export function jsonValueEnd(bytes: Uint8Array, start: number): number {
|
||||
}
|
||||
|
||||
/** The scanner the decoders find value ends with: jsonValueEnd, or the
|
||||
* native compiler's scanner (useNativeJsonValueEnd). */
|
||||
let valueEnd: (bytes: Uint8Array, start: number) => number = jsonValueEnd;
|
||||
* native compiler's scanner (useNativeJsonValueEnd). It is a property of a
|
||||
* constant object: a program that installs the scanner but decodes no
|
||||
* reply must still initialize it, and an assigned module variable with no
|
||||
* other reader would be left uninitialized by a native build. */
|
||||
const scanner: { valueEnd: (bytes: Uint8Array, start: number) => number } = {
|
||||
valueEnd: jsonValueEnd,
|
||||
};
|
||||
|
||||
/** Has the decoders find value ends with `scan`, which returns what
|
||||
* jsonValueEnd returns, or -1 where jsonValueEnd throws. The native compiler
|
||||
* installs its C scanner (native/ts7-process.c), which skips the strings that
|
||||
* make up most reply bytes with memchr. */
|
||||
export function useNativeJsonValueEnd(scan: (bytes: Uint8Array, start: number) => number): void {
|
||||
valueEnd = (bytes, start) => {
|
||||
scanner.valueEnd = (bytes, start) => {
|
||||
const end = scan(bytes, start);
|
||||
if (end < 0) malformedReply();
|
||||
return end;
|
||||
@@ -174,7 +179,7 @@ export function decodeSemanticObject<T extends { id: number }, R>(
|
||||
): R | null {
|
||||
const start = skipJsonSpace(bytes, 0);
|
||||
if (start === bytes.length) return null;
|
||||
const end = valueEnd(bytes, start);
|
||||
const end = scanner.valueEnd(bytes, start);
|
||||
if (skipJsonSpace(bytes, end) !== bytes.length) malformedReply();
|
||||
return replyElement(bytes, start, end, cached, build);
|
||||
}
|
||||
@@ -190,7 +195,7 @@ export function decodeSemanticObjects<T extends { id: number }, R>(
|
||||
let index = skipJsonSpace(bytes, 0);
|
||||
if (index === bytes.length) return null;
|
||||
if (bytes[index] !== OPEN_BRACKET) {
|
||||
const end = valueEnd(bytes, index);
|
||||
const end = scanner.valueEnd(bytes, index);
|
||||
if (
|
||||
skipJsonSpace(bytes, end) !== bytes.length ||
|
||||
parseJsonSlice<null>(bytes, index, end) !== null
|
||||
@@ -205,7 +210,7 @@ export function decodeSemanticObjects<T extends { id: number }, R>(
|
||||
return result;
|
||||
}
|
||||
for (;;) {
|
||||
const end = valueEnd(bytes, index);
|
||||
const end = scanner.valueEnd(bytes, index);
|
||||
if (end === index) malformedReply();
|
||||
result.push(replyElement(bytes, index, end, cached, build));
|
||||
index = skipJsonSpace(bytes, end);
|
||||
|
||||
Reference in New Issue
Block a user