mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
Link scr_bytes_dyn.c into libraries (#1693)
This commit is contained in:
@@ -33,6 +33,7 @@ export async function compilePackedLibrary(
|
||||
assert: options.assert ?? false,
|
||||
inspect: options.inspect ?? false,
|
||||
dynInvoke: options.dynInvoke ?? false,
|
||||
...(options.dynBuffer === true ? { dynBuffer: true } : {}),
|
||||
...(options.dynTier === true ? { dynTier: true } : {}),
|
||||
dc: false,
|
||||
dynAsync: false,
|
||||
|
||||
@@ -321,6 +321,9 @@ export interface LibArchiveOptions {
|
||||
threadInstances?: boolean;
|
||||
/** IR-detected link gates (the compileC precedent, refusal-narrowed). */
|
||||
dynInvoke?: boolean;
|
||||
/** Buffer.prototype methods on checked-dynamic values: scr_bytes_dyn.c,
|
||||
* with dynInvoke. */
|
||||
dynBuffer?: boolean;
|
||||
/** See CompileOptions.dynTier: the scr_js_* units. */
|
||||
dynTier?: boolean;
|
||||
regex?: boolean;
|
||||
|
||||
@@ -112,6 +112,7 @@ export async function compileLibArchive(opts: LibArchiveOptions): Promise<void>
|
||||
...(opts.assert && opts.bigint ? ["scr_bigint_assert.c"] : []),
|
||||
...(opts.emitter ? ["scr_events_emitter.c", "scr_dyn_handle.c"] : []),
|
||||
...(opts.dynInvoke ? ["scr_dyn_invoke.c"] : []),
|
||||
...(opts.dynInvoke && opts.dynBuffer ? ["scr_bytes_dyn.c"] : []),
|
||||
...(opts.dynTier === true ? ["scr_js_value.c", "scr_js_object.c"] : []),
|
||||
...(opts.zlib ? ["scr_zlib.c"] : []),
|
||||
...(opts.copying ? ["scr_copying.c"] : []),
|
||||
|
||||
@@ -1706,6 +1706,7 @@ function libraryNativeFeatures(mod: IrModule, backend: "llvm"): EarlyLibraryNati
|
||||
copying: features.copying,
|
||||
textDecoderLegacy: features.legacyTextDecoder,
|
||||
dynInvoke: features.dynInvoke,
|
||||
...(features.dynBuffer ? { dynBuffer: true } : {}),
|
||||
...(features.dynTier ? { dynTier: true } : {}),
|
||||
...(mod.lib?.identity !== undefined ? { buildId: mod.lib.identity.buildId } : {}),
|
||||
};
|
||||
@@ -1800,6 +1801,7 @@ async function compileLibraryNative(
|
||||
copying: features.copying,
|
||||
textDecoderLegacy: features.textDecoderLegacy,
|
||||
dynInvoke: features.dynInvoke,
|
||||
...(features.dynBuffer === true ? { dynBuffer: true } : {}),
|
||||
...(features.dynTier === true ? { dynTier: true } : {}),
|
||||
};
|
||||
if (packTarget !== null) await compilePackedLibrary(archiveOptions, packTarget);
|
||||
|
||||
@@ -63,6 +63,8 @@ interface EarlyLibraryCacheStamp {
|
||||
export interface EarlyLibraryNativeFeatures {
|
||||
backend: "llvm";
|
||||
dynInvoke: boolean;
|
||||
/** Buffer.prototype methods on checked-dynamic values (scr_bytes_dyn.c). */
|
||||
dynBuffer?: boolean;
|
||||
dynTier?: boolean;
|
||||
regex: boolean;
|
||||
assert: boolean;
|
||||
|
||||
@@ -15,6 +15,7 @@ export function withLibraryRuntimeFlavors(matrix) {
|
||||
"scr_zlib.c",
|
||||
"scr_copying.c",
|
||||
"scr_dyn_invoke.c",
|
||||
"scr_bytes_dyn.c",
|
||||
"scr_js_value.c",
|
||||
"scr_js_object.c",
|
||||
]);
|
||||
|
||||
@@ -3957,3 +3957,63 @@ ScrStr *scr_bytes_join(const ScrBytes *b, const ScrStr *separator) {
|
||||
scr_arr_release(values);
|
||||
return out;
|
||||
}
|
||||
|
||||
/* ── the checked-dynamic Buffer compare/equals validators ──────────────
|
||||
* Node's argument ladders for buf.equals / buf.compare / Buffer.compare
|
||||
* over dyn-boxed arguments (the invalid-input probes: string needles,
|
||||
* '0' offsets, null/object range args). A well-typed dyn still computes
|
||||
* the real answer — validation, not a constant fence. */
|
||||
|
||||
/* A bytes payload or the API's own ERR_INVALID_ARG_TYPE (borrowed). */
|
||||
static ScrBytes *scr_bytes_chk_u8(const ScrDyn *d, const char *argname) {
|
||||
if (!scr_dyn_bytes_is(d, SCR_BYTES_U8)) {
|
||||
scr_dyn_arg_type_fail(argname, "an instance of Buffer or Uint8Array", d);
|
||||
return NULL;
|
||||
}
|
||||
return d->v.bytes;
|
||||
}
|
||||
|
||||
double scr_buffer_compare_chk(const ScrDyn *a, const ScrDyn *b) {
|
||||
ScrBytes *b1 = scr_bytes_chk_u8(a, "buf1");
|
||||
if (!b1) return 0;
|
||||
ScrBytes *b2 = scr_bytes_chk_u8(b, "buf2");
|
||||
if (!b2) return 0;
|
||||
return scr_bytes_compare(b1, b2, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
bool scr_bytes_equals_chk(const ScrBytes *recv, const ScrDyn *other) {
|
||||
ScrBytes *o = scr_bytes_chk_u8(other, "otherBuffer");
|
||||
if (!o) return false;
|
||||
return scr_bytes_equals(recv, o);
|
||||
}
|
||||
|
||||
/* One offset slot: undefined takes the Node default, non-numbers throw
|
||||
* ERR_INVALID_ARG_TYPE "of type number", numbers run validateOffset. */
|
||||
static bool scr_bytes_chk_off(const ScrDyn *d, const char *name, double max,
|
||||
double dflt, double *out) {
|
||||
if (d->kind == SCR_DYN_UNDEF) {
|
||||
*out = dflt;
|
||||
return true;
|
||||
}
|
||||
if (d->kind != SCR_DYN_NUM) {
|
||||
scr_dyn_arg_type_fail(name, "of type number", d);
|
||||
return false;
|
||||
}
|
||||
*out = d->v.num;
|
||||
return scr_bytes_validate_off(name, *out, max);
|
||||
}
|
||||
|
||||
double scr_bytes_compare_chk(const ScrBytes *src, const ScrDyn *target,
|
||||
const ScrDyn *ts, const ScrDyn *te,
|
||||
const ScrDyn *ss, const ScrDyn *se) {
|
||||
ScrBytes *t = scr_bytes_chk_u8(target, "target");
|
||||
if (!t) return 0;
|
||||
double tsv, tev, ssv, sev;
|
||||
if (!scr_bytes_chk_off(ts, "targetStart", 9007199254740991.0, 0, &tsv)) return 0;
|
||||
if (!scr_bytes_chk_off(te, "targetEnd", (double)t->len, (double)t->len, &tev)) return 0;
|
||||
if (!scr_bytes_chk_off(ss, "sourceStart", 9007199254740991.0, 0, &ssv)) return 0;
|
||||
if (!scr_bytes_chk_off(se, "sourceEnd", (double)src->len, (double)src->len, &sev)) return 0;
|
||||
/* Every slot validated or defaulted above; nargs 4 revalidates the
|
||||
* now-known-good numbers (a no-op) and keeps one comparison core. */
|
||||
return scr_bytes_compare(src, t, 4, tsv, tev, ssv, sev);
|
||||
}
|
||||
|
||||
@@ -1368,66 +1368,6 @@ ScrBytes *scr_buffer_from_dyn_ref_pooled(const ScrDyn *value, const ScrStr *enco
|
||||
return scr_buffer_from_dyn_pooled(value, encoding);
|
||||
}
|
||||
|
||||
/* ── the checked-dynamic Buffer compare/equals validators ──────────────
|
||||
* Node's argument ladders for buf.equals / buf.compare / Buffer.compare
|
||||
* over dyn-boxed arguments (the invalid-input probes: string needles,
|
||||
* '0' offsets, null/object range args). A well-typed dyn still computes
|
||||
* the real answer — validation, not a constant fence. */
|
||||
|
||||
/* A bytes payload or the API's own ERR_INVALID_ARG_TYPE (borrowed). */
|
||||
static ScrBytes *scr_bytes_chk_u8(const ScrDyn *d, const char *argname) {
|
||||
if (!scr_dyn_bytes_is(d, SCR_BYTES_U8)) {
|
||||
scr_dyn_arg_type_fail(argname, "an instance of Buffer or Uint8Array", d);
|
||||
return NULL;
|
||||
}
|
||||
return d->v.bytes;
|
||||
}
|
||||
|
||||
double scr_buffer_compare_chk(const ScrDyn *a, const ScrDyn *b) {
|
||||
ScrBytes *b1 = scr_bytes_chk_u8(a, "buf1");
|
||||
if (!b1) return 0;
|
||||
ScrBytes *b2 = scr_bytes_chk_u8(b, "buf2");
|
||||
if (!b2) return 0;
|
||||
return scr_bytes_compare(b1, b2, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
bool scr_bytes_equals_chk(const ScrBytes *recv, const ScrDyn *other) {
|
||||
ScrBytes *o = scr_bytes_chk_u8(other, "otherBuffer");
|
||||
if (!o) return false;
|
||||
return scr_bytes_equals(recv, o);
|
||||
}
|
||||
|
||||
/* One offset slot: undefined takes the Node default, non-numbers throw
|
||||
* ERR_INVALID_ARG_TYPE "of type number", numbers run validateOffset. */
|
||||
static bool scr_bytes_chk_off(const ScrDyn *d, const char *name, double max,
|
||||
double dflt, double *out) {
|
||||
if (d->kind == SCR_DYN_UNDEF) {
|
||||
*out = dflt;
|
||||
return true;
|
||||
}
|
||||
if (d->kind != SCR_DYN_NUM) {
|
||||
scr_dyn_arg_type_fail(name, "of type number", d);
|
||||
return false;
|
||||
}
|
||||
*out = d->v.num;
|
||||
return scr_bytes_validate_off(name, *out, max);
|
||||
}
|
||||
|
||||
double scr_bytes_compare_chk(const ScrBytes *src, const ScrDyn *target,
|
||||
const ScrDyn *ts, const ScrDyn *te,
|
||||
const ScrDyn *ss, const ScrDyn *se) {
|
||||
ScrBytes *t = scr_bytes_chk_u8(target, "target");
|
||||
if (!t) return 0;
|
||||
double tsv, tev, ssv, sev;
|
||||
if (!scr_bytes_chk_off(ts, "targetStart", 9007199254740991.0, 0, &tsv)) return 0;
|
||||
if (!scr_bytes_chk_off(te, "targetEnd", (double)t->len, (double)t->len, &tev)) return 0;
|
||||
if (!scr_bytes_chk_off(ss, "sourceStart", 9007199254740991.0, 0, &ssv)) return 0;
|
||||
if (!scr_bytes_chk_off(se, "sourceEnd", (double)src->len, (double)src->len, &sev)) return 0;
|
||||
/* Every slot validated or defaulted above; nargs 4 revalidates the
|
||||
* now-known-good numbers (a no-op) and keeps one comparison core. */
|
||||
return scr_bytes_compare(src, t, 4, tsv, tev, ssv, sev);
|
||||
}
|
||||
|
||||
/* new Buffer(number, encoding) — the deprecated ctor's string arm with a
|
||||
* non-string first argument: Node's exact ERR_INVALID_ARG_TYPE (the
|
||||
* throwing path never fires DEP0005, so compiled silence matches). */
|
||||
|
||||
Reference in New Issue
Block a user