mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-27 06:43:19 +08:00
Read zlib options held in typed objects (#1316)
This commit is contained in:
+6
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"order": [
|
||||
"<repo>/tests/corpus/5633-zlib-typed-options.ts"
|
||||
],
|
||||
"diags": []
|
||||
}
|
||||
@@ -420,7 +420,22 @@ void scr_zlib_options_drop(ScrZlibOptions *o) {
|
||||
o->dict = NULL;
|
||||
}
|
||||
|
||||
static bool scr_zlib_options_parse_object(int mode, const ScrDyn *opts, ScrZlibOptions *out);
|
||||
|
||||
/* A typed options object (a record that crossed into a checked-dynamic
|
||||
* slot by reference) is read through its materialized view, as a plain
|
||||
* object is. */
|
||||
bool scr_zlib_options_parse(int mode, const ScrDyn *opts, ScrZlibOptions *out) {
|
||||
if (opts == NULL || opts->kind != SCR_DYN_TYPED_REF) return scr_zlib_options_parse_object(mode, opts, out);
|
||||
ScrDyn *view = scr_dyn_typed_ref_materialize(opts);
|
||||
bool ok = false;
|
||||
if (scr_exc_pending()) memset(out, 0, sizeof *out);
|
||||
else ok = scr_zlib_options_parse_object(mode, view, out);
|
||||
scr_dyn_release(view);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool scr_zlib_options_parse_object(int mode, const ScrDyn *opts, ScrZlibOptions *out) {
|
||||
memset(out, 0, sizeof *out);
|
||||
out->window_bits = 15;
|
||||
out->level = Z_DEFAULT_COMPRESSION;
|
||||
|
||||
@@ -431,6 +431,13 @@ static const char *scr_zs_class_name(int mode) {
|
||||
}
|
||||
|
||||
ScrStream *scr_zlib_stream_new(double mode_d, ScrDyn *opts) {
|
||||
/* A typed options object is read through its materialized view. */
|
||||
if (opts != NULL && opts->kind == SCR_DYN_TYPED_REF) {
|
||||
ScrDyn *view = scr_dyn_typed_ref_materialize(opts);
|
||||
ScrStream *stream = scr_exc_pending() ? NULL : scr_zlib_stream_new(mode_d, view);
|
||||
scr_dyn_release(view);
|
||||
return stream;
|
||||
}
|
||||
int mode = (int)mode_d;
|
||||
const ScrDyn *o = opts != NULL && scr_dyn_truthy(opts) ? opts : NULL;
|
||||
ScrZlibOptions zo;
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// zlib options held in a typed object (a cast object literal that crosses
|
||||
// into the options slot by reference) are read like a plain options
|
||||
// object: levels, windowBits and strategies apply, and out-of-range values
|
||||
// throw Node's ERR_OUT_OF_RANGE from the sync, callback, promisified and
|
||||
// stream forms.
|
||||
import * as zlib from "node:zlib";
|
||||
import { promisify } from "node:util";
|
||||
|
||||
const data = Buffer.from("hello hello hello hello hello");
|
||||
const stored = { level: 0 } as zlib.ZlibOptions;
|
||||
const fast = { level: 1 } as zlib.ZlibOptions;
|
||||
const huffman = { strategy: zlib.constants.Z_HUFFMAN_ONLY } as zlib.ZlibOptions;
|
||||
const smallWindow = { windowBits: 9, memLevel: 1 } as zlib.ZlibOptions;
|
||||
const badLevel = { level: 99 } as zlib.ZlibOptions;
|
||||
const badWindow = { windowBits: 3 } as zlib.ZlibOptions;
|
||||
|
||||
function attempt(label: string, run: () => void): void {
|
||||
try {
|
||||
run();
|
||||
console.log(label, "ok");
|
||||
} catch (e) {
|
||||
const err = e as NodeJS.ErrnoException;
|
||||
console.log(label, err.name, err.code, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("sync stored", zlib.deflateSync(data, stored).toString("hex"));
|
||||
console.log("sync fast", zlib.deflateSync(data, fast).toString("hex"));
|
||||
console.log("sync huffman", zlib.deflateSync(data, huffman).toString("hex"));
|
||||
console.log("raw small window", zlib.deflateRawSync(data, smallWindow).toString("hex"));
|
||||
console.log("gzip stored", zlib.gzipSync(data, stored).subarray(10).toString("hex"));
|
||||
attempt("sync bad level", () => zlib.deflateSync(data, badLevel));
|
||||
attempt("sync bad window", () => zlib.inflateSync(zlib.deflateSync(data), badWindow));
|
||||
attempt("callback bad level", () => zlib.gzip(data, badLevel, () => console.log("not called")));
|
||||
attempt("stream bad level", () => zlib.createDeflate(badLevel));
|
||||
|
||||
const deflateAsync = promisify(zlib.deflate);
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const viaCallback = await new Promise<Buffer>((resolve, reject) =>
|
||||
zlib.deflate(data, stored, (err, out) => (err ? reject(err) : resolve(out))),
|
||||
);
|
||||
console.log("callback stored", viaCallback.toString("hex"));
|
||||
console.log("promise stored", (await deflateAsync(data, stored)).toString("hex"));
|
||||
try {
|
||||
await deflateAsync(data, badLevel);
|
||||
console.log("promise bad level fulfilled");
|
||||
} catch (e) {
|
||||
console.log("promise bad level", (e as NodeJS.ErrnoException).code);
|
||||
}
|
||||
const stream = zlib.createDeflate(fast);
|
||||
const parts: Buffer[] = [];
|
||||
stream.on("data", (chunk: Buffer) => parts.push(chunk));
|
||||
stream.on("end", () => console.log("stream fast", Buffer.concat(parts).toString("hex")));
|
||||
stream.end(data);
|
||||
}
|
||||
|
||||
main().catch((e) => console.log("unexpected", String(e)));
|
||||
@@ -1976,6 +1976,7 @@
|
||||
"5630-promisify-zlib.ts": 2503,
|
||||
"5631-promisify-crypto.ts": 2200,
|
||||
"5632-promisify-dns.ts": 1700,
|
||||
"5633-zlib-typed-options.ts": 1800,
|
||||
"5644-net-socket-addresses.ts": 2220,
|
||||
"5645-net-socket-callbacks.ts": 2442,
|
||||
"5646-net-server-connections.ts": 2389,
|
||||
@@ -5012,6 +5013,7 @@
|
||||
"5630-promisify-zlib.ts": 3392,
|
||||
"5631-promisify-crypto.ts": 2600,
|
||||
"5632-promisify-dns.ts": 2000,
|
||||
"5633-zlib-typed-options.ts": 2200,
|
||||
"5644-net-socket-addresses.ts": 2393,
|
||||
"5645-net-socket-callbacks.ts": 2060,
|
||||
"5646-net-server-connections.ts": 2755,
|
||||
|
||||
Reference in New Issue
Block a user