mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-22 05:59:31 +08:00
122 lines
6.9 KiB
JavaScript
122 lines
6.9 KiB
JavaScript
// The island's node:buffer and node:string_decoder shims, differentially
|
|
// against Node: every line must match real Node byte-for-byte. Buffer is
|
|
// a Uint8Array subclass with Node's surface — the seven encodings both
|
|
// directions, the numeric accessor family with Node's range errors, the
|
|
// searching/filling/copying methods, the <Buffer ..> inspect form — and
|
|
// the Buffer GLOBAL is the same class. StringDecoder streams utf8 through
|
|
// split multi-byte sequences, holds utf16 byte parity, and carries base64
|
|
// mod-3 remainders.
|
|
import { Buffer as NamedBuffer, constants, INSPECT_MAX_BYTES, isAscii, isUtf8 } from "node:buffer";
|
|
import { StringDecoder } from "node:string_decoder";
|
|
import { inspect } from "node:util";
|
|
|
|
export function report() {
|
|
const lines = [];
|
|
const push = (label, v) => lines.push(label + " " + v);
|
|
const hex = (b) => b.toString("hex");
|
|
|
|
// identity: the named export IS the global
|
|
push("global:", NamedBuffer === Buffer);
|
|
|
|
// from / alloc / concat
|
|
push("from-arr:", hex(Buffer.from([1, 2, 255, 256, -1])));
|
|
push("from-utf8:", hex(Buffer.from("héllo ☃")));
|
|
push("from-latin1:", hex(Buffer.from("héæ", "latin1")));
|
|
push("from-hex:", hex(Buffer.from("00ff10", "hex")) + "|" + hex(Buffer.from("abzz", "hex")));
|
|
push("from-b64:", hex(Buffer.from("aGVsbG8=", "base64")) + "|" + hex(Buffer.from("aGVsbG8", "base64")) + "|" + hex(Buffer.from("-_-_", "base64url")));
|
|
push("from-utf16:", hex(Buffer.from("a☃", "utf16le")));
|
|
push("from-ab:", hex(Buffer.from(new Uint8Array([9, 8, 7, 6]).buffer, 1, 2)));
|
|
push("from-json:", hex(Buffer.from({ type: "Buffer", data: [1, 2] })));
|
|
let threw;
|
|
try {
|
|
Buffer.from("x", "nope");
|
|
threw = "no";
|
|
} catch (e) {
|
|
threw = e.code + ":" + e.message;
|
|
}
|
|
push("from-bad-enc:", threw);
|
|
push("alloc:", hex(Buffer.alloc(3)) + "|" + hex(Buffer.alloc(3, 7)) + "|" + hex(Buffer.alloc(5, "ab")) + "|" + hex(Buffer.alloc(4, "61ff", "hex")));
|
|
push("concat:", hex(Buffer.concat([Buffer.from([1]), Buffer.from([2, 3])])) + "|" + hex(Buffer.concat([Buffer.from([1])], 3)) + "|" + Buffer.concat([]).length);
|
|
push("classify:", [Buffer.isBuffer(Buffer.alloc(1)), Buffer.isBuffer(new Uint8Array(1)), Buffer.isEncoding("UCS-2"), Buffer.isEncoding("nope")].join(","));
|
|
push("bytelen:", [Buffer.byteLength("héllo"), Buffer.byteLength("aGVsbG8=", "base64"), Buffer.byteLength("abcd", "hex"), Buffer.byteLength("ab", "utf16le")].join(","));
|
|
|
|
// toString round trips
|
|
const sample = Buffer.from([0x68, 0xc3, 0xa9, 0xe2, 0x98, 0x83, 0x7f, 0x80, 0xff]);
|
|
push("tostr:", sample.toString() + "|" + sample.toString("utf8", 1, 3));
|
|
push("tostr-hex:", sample.toString("hex"));
|
|
push("tostr-b64:", sample.toString("base64") + "|" + Buffer.from([1]).toString("base64") + "|" + Buffer.from([251, 255, 254]).toString("base64url"));
|
|
push("tostr-ascii:", JSON.stringify(sample.toString("ascii")));
|
|
push("tostr-latin1:", JSON.stringify(sample.toString("latin1")));
|
|
push("tostr-utf16:", Buffer.from([0x61, 0x00, 0x03, 0x26, 0x61]).toString("utf16le"));
|
|
push("tostr-invalid:", JSON.stringify(Buffer.from([0xff, 0x61, 0xc3]).toString()));
|
|
|
|
// methods
|
|
push("json:", JSON.stringify(Buffer.from([1, 2])));
|
|
push("equals:", [Buffer.from([1, 2]).equals(Buffer.from([1, 2])), Buffer.from([1]).equals(Buffer.from([1, 2]))].join(","));
|
|
push("compare:", [Buffer.from([1, 2]).compare(Buffer.from([1, 3])), Buffer.compare(Buffer.from("b"), Buffer.from("a")), Buffer.from([1]).compare(Buffer.from([1, 0]))].join(","));
|
|
const target = Buffer.alloc(5, 9);
|
|
push("copy:", Buffer.from([1, 2, 3]).copy(target, 1) + "|" + hex(target));
|
|
push("fill:", hex(Buffer.alloc(5).fill(1, 1, 3)) + "|" + hex(Buffer.alloc(5).fill("ab")) + "|" + hex(Buffer.alloc(5).fill(Buffer.from([1, 2]))));
|
|
const w = Buffer.alloc(8, 0x2e);
|
|
push("write:", w.write("héllo") + "|" + hex(w) + "|" + Buffer.alloc(4, 0x2e).write("aé☃"));
|
|
const parent = Buffer.from([1, 2, 3, 4]);
|
|
const view = parent.slice(1, 3);
|
|
view[0] = 9;
|
|
push("slice-view:", hex(parent) + "|" + hex(view) + "|" + Buffer.isBuffer(view) + "|" + Buffer.isBuffer(parent.subarray(2)));
|
|
const hay = Buffer.from("hello hello");
|
|
push("search:", [hay.indexOf("llo"), hay.indexOf("llo", 3), hay.indexOf(0x6c), hay.indexOf("nope"), hay.lastIndexOf("llo"), hay.includes("hell")].join(","));
|
|
push("swap:", hex(Buffer.from([1, 2, 3, 4]).swap16()) + "|" + hex(Buffer.from([1, 2, 3, 4]).swap32()));
|
|
|
|
// numeric accessors and their errors
|
|
const rw = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x80, 0xff, 0x7f, 0xfe]);
|
|
push("reads:", [rw.readUInt8(4), rw.readUInt16LE(1), rw.readUInt16BE(1), rw.readUInt32LE(2), rw.readUInt32BE(2), rw.readInt8(4), rw.readInt16LE(4), rw.readInt32BE(4)].join(","));
|
|
push("reads-var:", [rw.readUIntLE(0, 6), rw.readUIntBE(0, 6), rw.readIntLE(2, 6)].join(","));
|
|
push("reads-big:", rw.readBigUInt64LE(0) + "," + rw.readBigInt64BE(0));
|
|
push("reads-fp:", rw.readFloatLE(0) + "," + rw.readDoubleBE(0));
|
|
const errOf = (fn) => {
|
|
try {
|
|
fn();
|
|
return "no";
|
|
} catch (e) {
|
|
return e.code + ":" + e.message;
|
|
}
|
|
};
|
|
push("read-oob:", errOf(() => Buffer.from([1]).readUInt16LE(0)));
|
|
push("read-oor:", errOf(() => Buffer.from([1, 2, 3, 4]).readUInt32LE(1)));
|
|
push("write-range:", errOf(() => Buffer.alloc(1).writeUInt8(256, 0)));
|
|
const wb = Buffer.alloc(6);
|
|
push("writes:", wb.writeUInt16LE(0x0102, 0) + "|" + wb.writeUIntBE(0x030405, 2, 3) + "|" + wb.writeInt8(-2, 5) + "|" + hex(wb));
|
|
const wd = Buffer.alloc(8);
|
|
wd.writeDoubleLE(0.5, 0);
|
|
push("write-fp:", hex(wd));
|
|
|
|
// inspect (the <Buffer ..> custom form, truncation at 50)
|
|
push("inspect:", inspect(Buffer.from([1, 0xab])) + "|" + inspect(Buffer.alloc(0)));
|
|
push("inspect-long:", inspect(Buffer.alloc(60, 7)));
|
|
|
|
// module surface
|
|
push("consts:", INSPECT_MAX_BYTES + "," + (constants.MAX_STRING_LENGTH > 0));
|
|
push("scan:", [isAscii(Buffer.from("abc")), isAscii(Buffer.from([0x80])), isUtf8(Buffer.from("héllo")), isUtf8(Buffer.from([0xff]))].join(","));
|
|
|
|
// interop with typed arrays and iteration
|
|
push("iter:", [...Buffer.from([1, 2, 3])].join(",") + "|" + JSON.stringify([...Buffer.from([9]).entries()]));
|
|
const mapped = Buffer.from([1, 2]).map((x) => x + 1);
|
|
push("map:", hex(mapped) + "|" + Buffer.isBuffer(mapped));
|
|
|
|
// StringDecoder
|
|
const sd = new StringDecoder("utf8");
|
|
const bytes = Buffer.from("héllo ☃");
|
|
let out = "";
|
|
for (let i = 0; i < bytes.length; i++) out += "|" + sd.write(bytes.subarray(i, i + 1));
|
|
push("sd-utf8:", out + "|END:" + sd.end());
|
|
const sd2 = new StringDecoder();
|
|
push("sd-dangling:", JSON.stringify(sd2.write(Buffer.from([0xe2, 0x98])) + "|" + sd2.end()));
|
|
const sd16 = new StringDecoder("ucs2");
|
|
push("sd-utf16:", sd16.write(Buffer.from([0x61, 0x00, 0x62])) + "|" + sd16.end());
|
|
const sdb = new StringDecoder("base64");
|
|
push("sd-b64:", sdb.write(Buffer.from([1])) + "|" + sdb.write(Buffer.from([2, 3, 4])) + "|" + sdb.end(Buffer.from([5])));
|
|
push("sd-enc:", new StringDecoder("UCS-2").encoding + "|" + new StringDecoder().encoding);
|
|
|
|
return lines.join("\n");
|
|
}
|