mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
Keep scr_lib.c's default object byte-identical for the fs.watchFile poll
Adding scr_stats_of_path and scr_stats_zero to scr_lib.c moved every program's executable: scr_lib.o is linked everywhere, so its new symbols and strings shifted addresses even for programs that never watch a file. The two entry points now live in an SCR_FS_WATCH_FILE build of scr_lib.c, the matrix's variant for programs whose feature set has watchFile, and the poll unit calls the renamed scr_stats_poll_path. Programs that do not poll link the default object unchanged: compiled without the define, scr_lib.o is byte-identical to the base (verified by comparing the two objects). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
60be717d92
commit
ad8f8daccd
@@ -426,6 +426,8 @@ const RUNTIME_DEFINES: readonly {
|
||||
{ define: "SCR_NATIVE_REACTIONS", when: (opts) => opts.webStreams },
|
||||
{ define: "SCR_HANDLE_CLASSES", when: (opts) => opts.webStreams },
|
||||
{ define: "SCR_YIN", when: (opts) => opts.youngNursery },
|
||||
// scr_lib.c's path stat and zero Stats for the fs.watchFile poll.
|
||||
{ define: "SCR_FS_WATCH_FILE", when: (opts) => opts.watchFile },
|
||||
{ define: "SCR_NODE_ISLANDS", when: (opts) => opts.nodeIsland },
|
||||
];
|
||||
|
||||
|
||||
@@ -274,6 +274,17 @@ export function variantsFor(source) {
|
||||
defines: ["SCR_TEXT_DECODER_LEGACY"],
|
||||
});
|
||||
}
|
||||
// fs.watchFile's poll needs a path stat that reports the errno (its failed
|
||||
// poll IS a reportable event). The Stats snapshot is private to scr_lib.c,
|
||||
// so the two entry points live in a build of that unit only programs that
|
||||
// poll link; every other program keeps the default object, byte for byte.
|
||||
if (source === "scr_lib.c") {
|
||||
variants.push({
|
||||
id: "fs-watch-file",
|
||||
when: { watchFile: true },
|
||||
defines: ["SCR_FS_WATCH_FILE"],
|
||||
});
|
||||
}
|
||||
// Programs that assign process.emitWarning link the replacement-aware
|
||||
// warning paths; every other program keeps the default object.
|
||||
if (source === "scr_async_dyn.c") {
|
||||
|
||||
@@ -5584,7 +5584,7 @@ static bool scr_stats_link_target(HANDLE h, DWORD tag, double *size_out, ScrStr
|
||||
return true;
|
||||
}
|
||||
|
||||
static ScrStats *scr_stats_win_handle_stats(const ScrStr *path, const char *op,
|
||||
static ScrStats *scr_stats_of_path(const ScrStr *path, const char *op,
|
||||
bool no_follow) {
|
||||
WCHAR *wide = scr_fs_win_wide(path);
|
||||
if (!wide) return scr_stats_crt_fallback(path, op);
|
||||
@@ -5630,7 +5630,7 @@ static ScrStats *scr_stats_win_handle_stats(const ScrStr *path, const char *op,
|
||||
/* Reparse points are a general interception mechanism. Node/libuv
|
||||
* follows non-link tags even for lstat, so reopen the resolved target. */
|
||||
CloseHandle(h);
|
||||
return scr_stats_win_handle_stats(path, op, false);
|
||||
return scr_stats_of_path(path, op, false);
|
||||
}
|
||||
if (!scr_stats_link_target(h, tagged.ReparseTag, &link_size, NULL)) {
|
||||
/* A mount-point tag may name a mounted volume rather than a junction.
|
||||
@@ -5638,7 +5638,7 @@ static ScrStats *scr_stats_win_handle_stats(const ScrStr *path, const char *op,
|
||||
* ordinary reparse points and retries with the final component
|
||||
* followed. Do not classify from the tag alone. */
|
||||
CloseHandle(h);
|
||||
return scr_stats_win_handle_stats(path, op, false);
|
||||
return scr_stats_of_path(path, op, false);
|
||||
}
|
||||
is_link = true;
|
||||
}
|
||||
@@ -6081,7 +6081,7 @@ ScrBytes *scr_fs_readlink_bytes(ScrStr *path) {
|
||||
ScrStats *scr_fs_stat(ScrStr *path) {
|
||||
if (!scr_fs_path_ok(path, "path")) return NULL;
|
||||
#ifdef _WIN32
|
||||
return scr_stats_win_handle_stats(path, "stat", false);
|
||||
return scr_stats_of_path(path, "stat", false);
|
||||
#else
|
||||
int error = 0;
|
||||
ScrStats *s = scr_stats_posix(path->data, -1, false, &error); /* follows symlinks */
|
||||
@@ -6093,7 +6093,7 @@ ScrStats *scr_fs_stat(ScrStr *path) {
|
||||
ScrStats *scr_fs_lstat(ScrStr *path) {
|
||||
if (!scr_fs_path_ok(path, "path")) return NULL;
|
||||
#ifdef _WIN32
|
||||
return scr_stats_win_handle_stats(path, "lstat", true);
|
||||
return scr_stats_of_path(path, "lstat", true);
|
||||
#else
|
||||
int error = 0;
|
||||
ScrStats *s = scr_stats_posix(path->data, -1, true, &error); /* no follow */
|
||||
@@ -6135,10 +6135,11 @@ ScrStats *scr_fs_fstat(double fd) {
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef SCR_FS_WATCH_FILE
|
||||
/* fs.watchFile's poll (scr_watch_file.c calls this): stat(2) following
|
||||
* symlinks, libuv's uv_fs_stat — NULL with *error = errno on failure,
|
||||
* never throwing, because a failed poll IS a reportable event. +1. */
|
||||
ScrStats *scr_stats_of_path(ScrStr *path, int *error) {
|
||||
ScrStats *scr_stats_poll_path(ScrStr *path, int *error) {
|
||||
if (!scr_fs_path_ok(path, "path")) {
|
||||
*error = EINVAL;
|
||||
return NULL;
|
||||
@@ -6161,6 +6162,7 @@ ScrStats *scr_stats_of_path(ScrStr *path, int *error) {
|
||||
* field 0, so isFile()/isDirectory() and the size/date reads all answer
|
||||
* zero/false. +1. */
|
||||
ScrStats *scr_stats_zero(void) { return scr_stats_new(); }
|
||||
#endif /* SCR_FS_WATCH_FILE */
|
||||
|
||||
/* ── Stats objects ───────────────────────────────────────────────────
|
||||
* Node's Stats and BigIntStats over a snapshot. The integers and the *Ms
|
||||
|
||||
@@ -507,8 +507,10 @@ double scr_stats_big_birthtime(ScrStats *s);
|
||||
/* fstat without throwing: +1, or NULL with *error set to the errno. */
|
||||
ScrStats *scr_stats_of_fd(int fd, int *error);
|
||||
/* stat(2) following symlinks without throwing (the fs.watchFile poll):
|
||||
* +1, or NULL with *error set to the errno. */
|
||||
ScrStats *scr_stats_of_path(ScrStr *path, int *error);
|
||||
* +1, or NULL with *error set to the errno. Both this and scr_stats_zero
|
||||
* exist only in the SCR_FS_WATCH_FILE build of scr_lib.c, which programs
|
||||
* that poll link; every other program links the default object. */
|
||||
ScrStats *scr_stats_poll_path(ScrStr *path, int *error);
|
||||
/* The all-zero snapshot a failed poll reports (Node's kZeroStats). +1. */
|
||||
ScrStats *scr_stats_zero(void);
|
||||
/* Node's Stats (or BigIntStats) object for the snapshot: own fields in the
|
||||
|
||||
@@ -171,7 +171,7 @@ static void scr_watch_file_poll(ScrClosure *cb) {
|
||||
if (p == NULL) return;
|
||||
p->timer = 0; /* the loop consumed this arm */
|
||||
int err = 0;
|
||||
ScrStats *cur = scr_stats_of_path(p->path, &err);
|
||||
ScrStats *cur = scr_stats_poll_path(p->path, &err);
|
||||
if (cur == NULL) {
|
||||
if (p->state != -err) {
|
||||
scr_watch_file_emit(p, NULL, p->last, -err);
|
||||
|
||||
Reference in New Issue
Block a user