mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-06 08:23:19 +08:00
The zero-cost gate showed every benchmark executable changing: the new string literals and floating-point constants grew the merged constant pools of scr_json.o and scr_lib.o, which every program linking those units carries, and edits to scr_dyn_fn_get and scr_dyn_has_own changed code the typed benchmarks reach. - The builtin constructor values, the inherited Object.prototype members and the stored timer functions move to scr_dyn_invoke.c, which links only into programs that use them: the frontend now selects that unit for dyn.globalConstructor, dyn.builtinFunction, dyn.objectTag and constant-key reads of constructor/valueOf/toString/hasOwnProperty/ propertyIsEnumerable. Those reads call scr_dyn_inherited_read after the ordinary read (and scr_dyn_object_prototype_member before it, since the ordinary read fences Object.prototype itself); computed-key reads keep their old answer. The unit's new strings live in their own section so programs linking it for other reasons keep their bytes. - scr_date_parse_get_time keeps its exact body; Date.parse and new Date(string) call the new scr_date_parse (bounded grammars, then V8's parser), and JavaScript `new Date(value)` calls scr_dyn_native_date_new_value, so fs.Stats dates are untouched. The parser and UTC(t) avoid new pooled constants. - Object.prototype.toString's "[object Error]" moves to scr_dyn_object_tag_of; scr_json.c is unchanged. - Calling or constructing through stored constructor values and own-property checks on Object.prototype itself are not supported in this change (they would touch shared code). Also pins the IMF-fixdate (cookie Expires) parse and Date#toUTCString round-trip in the corpus. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
51 lines
3.3 KiB
JavaScript
51 lines
3.3 KiB
JavaScript
// JavaScript callers of the Date field constructor and the date-string
|
|
// parser: arguments pass through ToNumber in order (valueOf runs, strings
|
|
// and booleans convert, a throwing conversion stops the rest), arguments
|
|
// past the seventh are evaluated but never converted, and RFC 1123 dates
|
|
// parse the way HTTP caching middleware reads them.
|
|
process.env.TZ = "Europe/Berlin";
|
|
const log = [];
|
|
const arg = (name, value) => ({ valueOf() { log.push(name); return value; } });
|
|
const d = new Date(arg("y", 2024), arg("m", 1), arg("d", 29), arg("h", 13), arg("mi", 5), arg("s", 6), arg("ms", 7), arg("extra", 8));
|
|
console.log(d.getTime(), d.toISOString(), log.join(","));
|
|
console.log(new Date("2024", "0", "15").getTime(), new Date(2024, true, null).getTime(), new Date(2024, undefined).getTime());
|
|
console.log(new Date(2024, 0, "x").getTime(), new Date(99, 0).getFullYear(), new Date(2024, 0, 1, 2, 3).getHours());
|
|
try {
|
|
new Date(2024, arg("m", 0), { valueOf() { throw new Error("conversion stopped"); } }, arg("h", 1));
|
|
} catch (e) {
|
|
console.log(e.message, log.slice(-1).join(","));
|
|
}
|
|
function isFresh(reqHeaders, resHeaders) {
|
|
const modifiedSince = reqHeaders["if-modified-since"];
|
|
const lastModified = resHeaders["last-modified"];
|
|
if (!modifiedSince || !lastModified) return false;
|
|
const lm = Date.parse(lastModified);
|
|
const ms = Date.parse(modifiedSince);
|
|
return !(isNaN(lm) || isNaN(ms) || lm > ms);
|
|
}
|
|
console.log(isFresh({ "if-modified-since": "Mon, 01 Jan 2024 00:00:00 GMT" }, { "last-modified": "Sun, 31 Dec 2023 00:00:00 GMT" }));
|
|
console.log(isFresh({ "if-modified-since": "Sun, 31 Dec 2023 00:00:00 GMT" }, { "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }));
|
|
console.log(isFresh({ "if-modified-since": "not a date" }, { "last-modified": "Mon, 01 Jan 2024 00:00:00 GMT" }));
|
|
const stamps = ["Tue, 15 Nov 1994 08:12:31 GMT", "Tuesday, 15-Nov-94 08:12:31 GMT", "Tue Nov 15 08:12:31 1994", "2024-03-31 02:30"];
|
|
for (const s of stamps) console.log(s, Date.parse(s), new Date(s).getTime());
|
|
// Date#toUTCString's IMF-fixdate (cookie Expires, Last-Modified) round-trips
|
|
// through the parser. Where toUTCString has no native lowering yet the same
|
|
// string comes from fields; `same` checks that string against Node's.
|
|
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
|
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
const pad = (n, w) => String(n).padStart(w, "0");
|
|
function imf(d) {
|
|
const y = d.getUTCFullYear();
|
|
const year = y < 0 ? "-" + pad(-y, 4) : pad(y, 4);
|
|
return days[d.getUTCDay()] + ", " + pad(d.getUTCDate(), 2) + " " + months[d.getUTCMonth()] + " " + year + " " +
|
|
pad(d.getUTCHours(), 2) + ":" + pad(d.getUTCMinutes(), 2) + ":" + pad(d.getUTCSeconds(), 2) + " GMT";
|
|
}
|
|
const stampsMs = [0, 1445412480000, 951782400000, -1, -62135596800000, -61851600000000, -59011459200000, 253402300799000, 1709251199999, -2208988800001, 8640000000000000, -8640000000000000];
|
|
for (const ms of stampsMs) {
|
|
const d = new Date(ms);
|
|
const method = d[["toUTC", "String"].join("")];
|
|
const s = typeof method === "function" ? method.call(d) : imf(d);
|
|
console.log(JSON.stringify(s), Date.parse(s), Date.parse(s) === ms - (ms % 1000 + 1000) % 1000, s === imf(d));
|
|
}
|
|
console.log(Date.parse("Wed, 21 Oct 2015 07:28:00 GMT"), new Date("Wed, 21 Oct 2015 07:28:00 GMT").getTime());
|