@scriptc/cli-darwin-arm64 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/THIRD_PARTY_NOTICES +1 -1
- package/dist/bin/scriptc +0 -0
- package/dist/bin/scriptc.json +1 -1
- package/dist/lib/declarations/scriptc-node-fallback.d.ts +99 -27
- package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
- package/dist/lib/llvm/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_util_style.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_util_style.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_util_style.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_cycle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_url_params.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_util_compare.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_util_style.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-arm64/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/runtime-pack.json +399 -273
- package/dist/lib/runtime-sources/package.json +1 -1
- package/dist/lib/runtime-sources/src/scr_array.c +55 -34
- package/dist/lib/runtime-sources/src/scr_assert.c +26 -0
- package/dist/lib/runtime-sources/src/scr_async.c +44 -0
- package/dist/lib/runtime-sources/src/scr_bigint.c +15 -0
- package/dist/lib/runtime-sources/src/scr_bytes_io.c +305 -48
- package/dist/lib/runtime-sources/src/scr_cycle.c +84 -60
- package/dist/lib/runtime-sources/src/scr_events.c +9 -0
- package/dist/lib/runtime-sources/src/scr_exception.c +1 -0
- package/dist/lib/runtime-sources/src/scr_file_handle.c +11 -0
- package/dist/lib/runtime-sources/src/scr_island.c +1001 -417
- package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -7
- package/dist/lib/runtime-sources/src/scr_json.c +150 -13
- package/dist/lib/runtime-sources/src/scr_lib.c +424 -28
- package/dist/lib/runtime-sources/src/scr_map.c +236 -40
- package/dist/lib/runtime-sources/src/scr_node_builtin.c +78 -0
- package/dist/lib/runtime-sources/src/scr_regex.c +112 -8
- package/dist/lib/runtime-sources/src/scr_runtime.h +108 -14
- package/dist/lib/runtime-sources/src/scr_string.c +29 -0
- package/dist/lib/runtime-sources/src/scr_symbol.c +5 -0
- package/dist/lib/runtime-sources/src/scr_system_errors.h +573 -0
- package/dist/lib/runtime-sources/src/scr_url.c +515 -59
- package/dist/lib/runtime-sources/src/scr_url_internal.h +6 -0
- package/dist/lib/runtime-sources/src/scr_url_params.c +10 -0
- package/dist/lib/runtime-sources/src/scr_util_compare.c +222 -0
- package/dist/lib/runtime-sources/src/scr_util_style.c +337 -0
- package/dist/lib/runtime-sources/src/scr_web.c +720 -238
- package/package.json +1 -1
|
@@ -279,13 +279,204 @@ static ScrStr *scr_fs_cb_path(const ScrDyn *value, const char *name) {
|
|
|
279
279
|
ScrStr *path = value->kind == SCR_DYN_STR ? scr_str_retain(value->v.str)
|
|
280
280
|
: scr_str_new((const char *)value->v.bytes->data, value->v.bytes->len);
|
|
281
281
|
if (memchr(path->data, 0, path->len)) {
|
|
282
|
-
|
|
282
|
+
scr_fs_invalid_named_path(value, path, name);
|
|
283
283
|
scr_str_release(path);
|
|
284
284
|
return NULL;
|
|
285
285
|
}
|
|
286
286
|
return path;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
static ScrStr *scr_fs_checked_path(const ScrDyn *value, const char *name) {
|
|
290
|
+
if (!scr_dyn_native_url_is(value)) return scr_fs_cb_path(value, name);
|
|
291
|
+
ScrStr *path = scr_url_checked_to_path(value);
|
|
292
|
+
if (!path) return NULL;
|
|
293
|
+
ScrDyn input = { .kind = SCR_DYN_STR, .v.str = path };
|
|
294
|
+
ScrStr *checked = scr_fs_cb_path(&input, name);
|
|
295
|
+
scr_str_release(path);
|
|
296
|
+
return checked;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
static ScrStr *scr_fs_timestamp_path(const ScrDyn *value) {
|
|
300
|
+
return scr_fs_checked_path(value, "path");
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/* statfs reads options.bigint without validating/coercing the options object.
|
|
304
|
+
* Undefined selects the default; null throws, and only boolean true opts in. */
|
|
305
|
+
static bool scr_fs_statfs_bigint(const ScrDyn *options) {
|
|
306
|
+
if (options->kind == SCR_DYN_UNDEF) return false;
|
|
307
|
+
if (options->kind == SCR_DYN_NULL) {
|
|
308
|
+
static const char message[] = "Cannot read properties of null (reading 'bigint')";
|
|
309
|
+
scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
ScrDyn *value = scr_fs_cb_option(options, "bigint");
|
|
313
|
+
bool bigint = value && value->kind == SCR_DYN_BOOL && value->v.b;
|
|
314
|
+
scr_dyn_release(value);
|
|
315
|
+
return bigint;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
ScrDyn *scr_fs_statfs_checked(const ScrDyn *input, const ScrDyn *options) {
|
|
319
|
+
ScrStr *path = scr_fs_checked_path(input, "path");
|
|
320
|
+
if (!path) return NULL;
|
|
321
|
+
bool bigint = scr_fs_statfs_bigint(options);
|
|
322
|
+
ScrDyn *result = scr_exc_pending() ? NULL : scr_fs_statfs(path, bigint);
|
|
323
|
+
scr_str_release(path);
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/* validateOneOf runs before either path, even on POSIX where the type has
|
|
328
|
+
* no syscall effect. -1 means infer the target's kind on Windows. */
|
|
329
|
+
static int scr_fs_symlink_type(const ScrDyn *type) {
|
|
330
|
+
if (scr_fs_dyn_absent(type)) return -1;
|
|
331
|
+
if (type->kind == SCR_DYN_STR) {
|
|
332
|
+
const ScrStr *s = type->v.str;
|
|
333
|
+
if (s->len == 4 && !memcmp(s->data, "file", 4)) return 0;
|
|
334
|
+
if (s->len == 3 && !memcmp(s->data, "dir", 3)) return 1;
|
|
335
|
+
if (s->len == 8 && !memcmp(s->data, "junction", 8)) return 2;
|
|
336
|
+
}
|
|
337
|
+
scr_dyn_arg_value_fail("type", "must be one of: 'dir', 'file', 'junction', null, undefined", type);
|
|
338
|
+
return -1;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
void scr_fs_link_checked(const ScrDyn *existing, const ScrDyn *destination) {
|
|
342
|
+
ScrStr *from = scr_fs_checked_path(existing, "existingPath");
|
|
343
|
+
if (!from) return;
|
|
344
|
+
ScrStr *to = scr_fs_checked_path(destination, "newPath");
|
|
345
|
+
if (to) scr_fs_link(from, to);
|
|
346
|
+
scr_str_release(from); scr_str_release(to);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
static void scr_fs_symlink_checked_core(const ScrDyn *target, const ScrDyn *destination, const ScrDyn *type, bool promise) {
|
|
350
|
+
int kind = scr_fs_symlink_type(type);
|
|
351
|
+
if (scr_exc_pending()) return;
|
|
352
|
+
#ifdef _WIN32
|
|
353
|
+
if (kind == -1) {
|
|
354
|
+
// Sync/promise inference stringifies the raw destination and target before
|
|
355
|
+
// getValidatedPath. Sync stat exposes null-byte errors in the resolved path;
|
|
356
|
+
// the promise form catches inference failures and continues as a file link.
|
|
357
|
+
ScrStr *link = scr_dyn_string_coerce_js(destination);
|
|
358
|
+
ScrStr *source = !scr_exc_pending() ? scr_dyn_string_coerce_js(target) : NULL;
|
|
359
|
+
ScrStr *absolute = NULL;
|
|
360
|
+
if (link && source && !scr_exc_pending()) {
|
|
361
|
+
ScrArr *parts = scr_arr_new_ref(scr_str_retain_v, scr_str_release_v, NULL, 3);
|
|
362
|
+
scr_arr_push_ref(parts, scr_str_retain(link));
|
|
363
|
+
scr_arr_push_ref(parts, scr_str_new("..", 2));
|
|
364
|
+
scr_arr_push_ref(parts, scr_str_retain(source));
|
|
365
|
+
absolute = scr_path_win32_resolve(parts);
|
|
366
|
+
scr_arr_release(parts);
|
|
367
|
+
}
|
|
368
|
+
kind = 0;
|
|
369
|
+
if (absolute && !scr_exc_pending()) {
|
|
370
|
+
ScrDyn input = { .kind = SCR_DYN_STR, .v.str = absolute };
|
|
371
|
+
ScrStr *checked = scr_fs_cb_path(&input, "path");
|
|
372
|
+
if (checked) kind = scr_fs_symlink_infer(checked);
|
|
373
|
+
scr_str_release(checked);
|
|
374
|
+
}
|
|
375
|
+
scr_str_release(link); scr_str_release(source); scr_str_release(absolute);
|
|
376
|
+
if (scr_exc_pending()) {
|
|
377
|
+
if (!promise) return;
|
|
378
|
+
scr_caught_release(scr_exc_take());
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
#else
|
|
382
|
+
(void)promise;
|
|
383
|
+
#endif
|
|
384
|
+
ScrStr *from = scr_fs_checked_path(target, "target");
|
|
385
|
+
if (!from) return;
|
|
386
|
+
ScrStr *to = scr_fs_checked_path(destination, "path");
|
|
387
|
+
#ifdef _WIN32
|
|
388
|
+
if (to && kind == 2 && scr_dyn_bytes_is(destination, SCR_BYTES_U8)) {
|
|
389
|
+
scr_dyn_arg_type_fail("paths[0]", "of type string", destination);
|
|
390
|
+
scr_str_release(to); to = NULL;
|
|
391
|
+
}
|
|
392
|
+
#endif
|
|
393
|
+
if (to) scr_fs_symlink(from, to, kind);
|
|
394
|
+
scr_str_release(from); scr_str_release(to);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
void scr_fs_symlink_checked(const ScrDyn *target, const ScrDyn *destination, const ScrDyn *type) {
|
|
398
|
+
scr_fs_symlink_checked_core(target, destination, type, false);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
void scr_fs_symlink_promise_checked(const ScrDyn *target, const ScrDyn *destination, const ScrDyn *type) {
|
|
402
|
+
scr_fs_symlink_checked_core(target, destination, type, true);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/* getOptions accepts functions as defaults and validates signals without
|
|
406
|
+
* cancelling readlink. Unlike readFile, an aborted signal is ignored. */
|
|
407
|
+
static ScrDyn *scr_fs_readlink_encoding(const ScrDyn *options) {
|
|
408
|
+
if (scr_fs_dyn_absent(options) || options->kind == SCR_DYN_FUNC) return scr_dyn_retain(scr_dyn_undefined());
|
|
409
|
+
if (options->kind != SCR_DYN_STR && options->kind != SCR_DYN_OBJ &&
|
|
410
|
+
options->kind != SCR_DYN_ARR && options->kind != SCR_DYN_TYPED_REF &&
|
|
411
|
+
options->kind != SCR_DYN_HANDLE && options->kind != SCR_DYN_BYTES) {
|
|
412
|
+
scr_dyn_arg_type_fail("options", "one of type string or object", options);
|
|
413
|
+
return NULL;
|
|
414
|
+
}
|
|
415
|
+
ScrDyn *encoding = options->kind == SCR_DYN_STR ? scr_dyn_retain((ScrDyn *)options) : scr_fs_cb_option(options, "encoding");
|
|
416
|
+
if (!encoding) return NULL;
|
|
417
|
+
bool buffer = encoding->kind == SCR_DYN_STR && encoding->v.str->len == 6 && !memcmp(encoding->v.str->data, "buffer", 6);
|
|
418
|
+
if (!buffer && scr_dyn_truthy(encoding) &&
|
|
419
|
+
(encoding->kind != SCR_DYN_STR || !scr_bytes_is_encoding(encoding->v.str))) {
|
|
420
|
+
scr_dyn_arg_value_fail("encoding", "is invalid encoding", encoding);
|
|
421
|
+
scr_dyn_release(encoding);
|
|
422
|
+
return NULL;
|
|
423
|
+
}
|
|
424
|
+
if (options->kind != SCR_DYN_STR) {
|
|
425
|
+
ScrDyn *signal = scr_fs_cb_option(options, "signal");
|
|
426
|
+
if (!signal) { scr_dyn_release(encoding); return NULL; }
|
|
427
|
+
bool valid = signal->kind == SCR_DYN_UNDEF || (signal->kind == SCR_DYN_HANDLE && signal->v.handle.tag == SCR_DYNH_ABORT_SIGNAL);
|
|
428
|
+
if (!valid) scr_dyn_prop_type_fail("options.signal", "an instance of AbortSignal", signal);
|
|
429
|
+
scr_dyn_release(signal);
|
|
430
|
+
if (!valid) { scr_dyn_release(encoding); return NULL; }
|
|
431
|
+
}
|
|
432
|
+
return encoding;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
static ScrDyn *scr_fs_readlink_result(ScrStr *path, const ScrDyn *encoding) {
|
|
436
|
+
ScrBytes *bytes = scr_fs_readlink_bytes(path);
|
|
437
|
+
if (!bytes) return NULL;
|
|
438
|
+
ScrDyn *result;
|
|
439
|
+
if (encoding->kind == SCR_DYN_STR && encoding->v.str->len == 6 && !memcmp(encoding->v.str->data, "buffer", 6)) {
|
|
440
|
+
result = scr_dyn_new_buffer(bytes);
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
ScrStr *codec = encoding->kind == SCR_DYN_STR && encoding->v.str->len ? scr_str_retain(encoding->v.str) : scr_str_new("utf8", 4);
|
|
444
|
+
ScrStr *text = scr_bytes_to_str(bytes, codec);
|
|
445
|
+
scr_str_release(codec);
|
|
446
|
+
result = text ? scr_dyn_new_str(text) : NULL;
|
|
447
|
+
scr_str_release(text);
|
|
448
|
+
}
|
|
449
|
+
scr_bytes_release(bytes);
|
|
450
|
+
return result;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
ScrDyn *scr_fs_readlink_checked(const ScrDyn *input, const ScrDyn *options, bool promise) {
|
|
454
|
+
ScrDyn *encoding = scr_fs_readlink_encoding(options);
|
|
455
|
+
if (!encoding) return NULL;
|
|
456
|
+
ScrStr *path = scr_fs_checked_path(input, promise ? "oldPath" : "path");
|
|
457
|
+
ScrDyn *result = path ? scr_fs_readlink_result(path, encoding) : NULL;
|
|
458
|
+
scr_str_release(path); scr_dyn_release(encoding);
|
|
459
|
+
return result;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
ScrDyn *scr_fs_readlink_dyn(const ScrDyn *path, const ScrDyn *options) {
|
|
463
|
+
return scr_fs_readlink_checked(path, options, false);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
ScrStr *scr_fs_readlink_str(const ScrDyn *path, const ScrDyn *options) {
|
|
467
|
+
ScrDyn *result = scr_fs_readlink_dyn(path, options);
|
|
468
|
+
ScrStr *text = result && result->kind == SCR_DYN_STR ? scr_str_retain(result->v.str) : NULL;
|
|
469
|
+
scr_dyn_release(result);
|
|
470
|
+
return text;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
ScrBytes *scr_fs_readlink_buffer(const ScrDyn *path, const ScrDyn *options) {
|
|
474
|
+
ScrDyn *result = scr_fs_readlink_dyn(path, options);
|
|
475
|
+
ScrBytes *bytes = result ? scr_dyn_bytes_unbox(result) : NULL;
|
|
476
|
+
scr_dyn_release(result);
|
|
477
|
+
return bytes;
|
|
478
|
+
}
|
|
479
|
+
|
|
289
480
|
static ScrDyn *scr_fs_cb_string(ScrStr *text) {
|
|
290
481
|
if (!text) return NULL;
|
|
291
482
|
ScrDyn *value = scr_dyn_new_str(text);
|
|
@@ -472,6 +663,13 @@ static bool scr_fs_encoding_chk(const ScrDyn *);
|
|
|
472
663
|
static bool scr_fs_int_range_chk(const ScrDyn *, const char *, double, double, const char *);
|
|
473
664
|
static bool scr_fs_mode_chk(const ScrDyn *, const char *);
|
|
474
665
|
|
|
666
|
+
static bool scr_fs_callback_times(const ScrDyn *atime, const ScrDyn *mtime, bool descriptor, double *access, double *modified) {
|
|
667
|
+
*access = scr_fs_timestamp_value(atime, descriptor ? "atime" : "time");
|
|
668
|
+
if (scr_exc_pending()) return false;
|
|
669
|
+
*modified = scr_fs_timestamp_value(mtime, descriptor ? "mtime" : "time");
|
|
670
|
+
return !scr_exc_pending();
|
|
671
|
+
}
|
|
672
|
+
|
|
475
673
|
static ScrArr *scr_fs_cb_vectors(const ScrDyn *buffers) {
|
|
476
674
|
ScrDyn *snapshot = buffers->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(buffers)
|
|
477
675
|
? scr_dyn_typed_ref_materialize(buffers) : NULL;
|
|
@@ -499,21 +697,86 @@ static ScrArr *scr_fs_cb_vectors(const ScrDyn *buffers) {
|
|
|
499
697
|
|
|
500
698
|
static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc) {
|
|
501
699
|
const char *op = member->data;
|
|
700
|
+
if (!strcmp(op, "statfs")) {
|
|
701
|
+
const ScrDyn *options = scr_fs_cb_arg(args, argc, 1);
|
|
702
|
+
const ScrDyn *callback = options->kind == SCR_DYN_FUNC ? options : scr_fs_cb_arg(args, argc, 2);
|
|
703
|
+
if (!scr_fs_cb_chk(callback, "cb")) return NULL;
|
|
704
|
+
ScrStr *path = scr_fs_checked_path(scr_fs_cb_arg(args, argc, 0), "path");
|
|
705
|
+
if (!path) return NULL;
|
|
706
|
+
if (options->kind == SCR_DYN_FUNC) options = scr_dyn_undefined();
|
|
707
|
+
bool bigint = scr_fs_statfs_bigint(options);
|
|
708
|
+
/* FSReqCallback captures the first read; binding.statfs reads it again. */
|
|
709
|
+
if (!scr_exc_pending()) (void)scr_fs_statfs_bigint(options);
|
|
710
|
+
if (scr_exc_pending()) { scr_str_release(path); return NULL; }
|
|
711
|
+
ScrDyn *result = scr_fs_statfs(path, bigint);
|
|
712
|
+
scr_str_release(path);
|
|
713
|
+
scr_fs_cb_schedule(callback, result, NULL);
|
|
714
|
+
return scr_dyn_retain(scr_dyn_undefined());
|
|
715
|
+
}
|
|
716
|
+
if (!strcmp(op, "link") || !strcmp(op, "symlink") || !strcmp(op, "readlink")) {
|
|
717
|
+
const ScrDyn *first = scr_fs_cb_arg(args, argc, 0);
|
|
718
|
+
const ScrDyn *second = scr_fs_cb_arg(args, argc, 1);
|
|
719
|
+
bool symbolic = !strcmp(op, "symlink"), reading = !strcmp(op, "readlink");
|
|
720
|
+
const ScrDyn *third = scr_fs_cb_arg(args, argc, 2);
|
|
721
|
+
const ScrDyn *fourth = scr_fs_cb_arg(args, argc, 3);
|
|
722
|
+
const ScrDyn *callback = symbolic && fourth->kind != SCR_DYN_UNDEF ? fourth
|
|
723
|
+
: reading && second->kind == SCR_DYN_FUNC ? second : third;
|
|
724
|
+
int kind = -1;
|
|
725
|
+
if (symbolic && fourth->kind != SCR_DYN_UNDEF) {
|
|
726
|
+
kind = scr_fs_symlink_type(third);
|
|
727
|
+
if (scr_exc_pending()) return NULL;
|
|
728
|
+
} else if (!scr_fs_cb_chk(callback, "cb")) return NULL;
|
|
729
|
+
ScrDyn *encoding = reading ? scr_fs_readlink_encoding(second) : NULL;
|
|
730
|
+
if (reading && !encoding) return NULL;
|
|
731
|
+
ScrStr *from = scr_fs_checked_path(first, symbolic ? "target" : reading ? "path" : "existingPath");
|
|
732
|
+
if (!from) { scr_dyn_release(encoding); return NULL; }
|
|
733
|
+
ScrStr *to = reading ? NULL : scr_fs_checked_path(second, symbolic ? "path" : "newPath");
|
|
734
|
+
if ((!reading && !to) || (symbolic && fourth->kind != SCR_DYN_UNDEF && !scr_fs_cb_chk(callback, "cb"))) {
|
|
735
|
+
scr_str_release(from); scr_str_release(to); scr_dyn_release(encoding); return NULL;
|
|
736
|
+
}
|
|
737
|
+
#ifdef _WIN32
|
|
738
|
+
if (symbolic) {
|
|
739
|
+
if (kind == 2 && scr_dyn_bytes_is(second, SCR_BYTES_U8)) {
|
|
740
|
+
scr_dyn_arg_type_fail("paths[0]", "of type string", second);
|
|
741
|
+
scr_str_release(from); scr_str_release(to); return NULL;
|
|
742
|
+
}
|
|
743
|
+
// Callback inference passes validated paths directly to path.resolve;
|
|
744
|
+
// Buffer paths fail that probe and fall back to a file link.
|
|
745
|
+
if (kind == -1 && (scr_dyn_bytes_is(first, SCR_BYTES_U8) || scr_dyn_bytes_is(second, SCR_BYTES_U8))) kind = 0;
|
|
746
|
+
}
|
|
747
|
+
#endif
|
|
748
|
+
ScrDyn *result = NULL;
|
|
749
|
+
if (reading) result = scr_fs_readlink_result(from, encoding);
|
|
750
|
+
else if (symbolic) scr_fs_symlink(from, to, kind);
|
|
751
|
+
else scr_fs_link(from, to);
|
|
752
|
+
scr_str_release(from); scr_str_release(to); scr_dyn_release(encoding);
|
|
753
|
+
scr_fs_cb_schedule(callback, result, NULL);
|
|
754
|
+
return scr_dyn_retain(scr_dyn_undefined());
|
|
755
|
+
}
|
|
502
756
|
bool vector = !strcmp(op, "readv") || !strcmp(op, "writev");
|
|
757
|
+
bool timestamp = !strcmp(op, "utimes") || !strcmp(op, "lutimes") || !strcmp(op, "futimes");
|
|
758
|
+
bool timestamp_fd = !strcmp(op, "futimes");
|
|
759
|
+
double access = 0, modified = 0;
|
|
760
|
+
// futimes converts times before checking the callback; path variants do
|
|
761
|
+
// callback and path validation first. Validation failures throw immediately.
|
|
762
|
+
if (timestamp_fd && !scr_fs_callback_times(scr_fs_cb_arg(args, argc, 1), scr_fs_cb_arg(args, argc, 2), true, &access, &modified)) return NULL;
|
|
503
763
|
bool newControl = !strcmp(op, "fdatasync") || !strcmp(op, "fchmod") || !strcmp(op, "ftruncate");
|
|
504
764
|
if ((vector || newControl) && !scr_fs_int_range_chk(scr_fs_cb_arg(args, argc, 0), "fd", 0, 2147483647.0, ">= 0 && <= 2147483647")) return NULL;
|
|
505
765
|
ScrArr *vectors = vector ? scr_fs_cb_vectors(scr_fs_cb_arg(args, argc, 1)) : NULL;
|
|
506
766
|
if (vector && !vectors) return NULL;
|
|
507
767
|
bool fileCallback = !strcmp(op, "readFile") || !strcmp(op, "mkdtemp");
|
|
508
|
-
const ScrDyn *callback =
|
|
509
|
-
|
|
510
|
-
|
|
768
|
+
const ScrDyn *callback = timestamp ? scr_fs_cb_arg(args, argc, 3)
|
|
769
|
+
: argc >= (fileCallback ? 2u : 1u) ? args[argc - 1] : scr_dyn_undefined();
|
|
770
|
+
if (!scr_fs_cb_chk(callback, fileCallback || vector || timestamp ? "cb" : "callback")) { scr_arr_release(vectors); return NULL; }
|
|
771
|
+
size_t count = timestamp ? argc : argc - 1;
|
|
511
772
|
#define ARG(index) scr_fs_cb_arg(args, count, index)
|
|
512
773
|
if (!strcmp(op, "readFile") && !scr_fs_encoding_chk(ARG(1))) return NULL;
|
|
513
774
|
if (!strcmp(op, "read") && count >= 4 && !scr_fs_read_validate(ARG(0), ARG(1), ARG(2), ARG(3), ARG(4))) return NULL;
|
|
514
|
-
bool descriptor = vector || newControl || !strcmp(op, "close") || !strcmp(op, "fstat") || !strcmp(op, "fsync") || !strcmp(op, "read") || !strcmp(op, "write");
|
|
515
|
-
ScrStr *path = descriptor ? NULL : scr_fs_cb_path(ARG(0), !strcmp(op, "mkdtemp") ? "prefix" : "path");
|
|
775
|
+
bool descriptor = timestamp_fd || vector || newControl || !strcmp(op, "close") || !strcmp(op, "fstat") || !strcmp(op, "fsync") || !strcmp(op, "read") || !strcmp(op, "write");
|
|
776
|
+
ScrStr *path = descriptor ? NULL : timestamp ? scr_fs_timestamp_path(ARG(0)) : scr_fs_cb_path(ARG(0), !strcmp(op, "mkdtemp") ? "prefix" : "path");
|
|
516
777
|
if (!descriptor && !path) return NULL;
|
|
778
|
+
if (timestamp && !timestamp_fd && !scr_fs_callback_times(ARG(1), ARG(2), false, &access, &modified)) { scr_str_release(path); return NULL; }
|
|
779
|
+
if (timestamp_fd && !scr_fs_int_range_chk(ARG(0), "fd", 0, 2147483647.0, ">= 0 && <= 2147483647")) return NULL;
|
|
517
780
|
double fd = descriptor ? scr_fs_cb_number(ARG(0), "fd", -1) : -1;
|
|
518
781
|
if (scr_exc_pending()) { scr_str_release(path); scr_arr_release(vectors); return NULL; }
|
|
519
782
|
if (newControl && strcmp(op, "fdatasync")) {
|
|
@@ -646,11 +909,10 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
|
|
646
909
|
scr_dyn_release(ownedBuffer); scr_str_release(path);
|
|
647
910
|
return scr_dyn_retain(scr_dyn_undefined());
|
|
648
911
|
}
|
|
649
|
-
} else if (!strcmp(op, "copyFile") || !strcmp(op, "rename")
|
|
912
|
+
} else if (!strcmp(op, "copyFile") || !strcmp(op, "rename")) {
|
|
650
913
|
ScrStr *destination = scr_fs_cb_path(ARG(1), "dest");
|
|
651
914
|
if (destination) {
|
|
652
915
|
if (!strcmp(op, "rename")) scr_fs_rename(path, destination);
|
|
653
|
-
else if (!strcmp(op, "link")) scr_fs_link(path, destination);
|
|
654
916
|
else if (!strcmp(op, "copyFile")) {
|
|
655
917
|
double flags = scr_fs_cb_number(ARG(2), "mode", 0);
|
|
656
918
|
if (flags == 1 && scr_fs_exists(destination)) scr_fs_throw(EEXIST, "copyfile", destination);
|
|
@@ -659,13 +921,6 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
|
|
659
921
|
scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
|
|
660
922
|
} else if (!scr_exc_pending()) scr_fs_copyfile(path, destination);
|
|
661
923
|
}
|
|
662
|
-
else {
|
|
663
|
-
#if !defined(_WIN32)
|
|
664
|
-
if (symlink(path->data, destination->data) < 0) scr_fs_throw(errno, "symlink", path);
|
|
665
|
-
#else
|
|
666
|
-
scr_fs_throw(ENOSYS, "symlink", path);
|
|
667
|
-
#endif
|
|
668
|
-
}
|
|
669
924
|
scr_str_release(destination);
|
|
670
925
|
}
|
|
671
926
|
} else if (!strcmp(op, "truncate") || !strcmp(op, "ftruncate")) {
|
|
@@ -674,35 +929,9 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
|
|
674
929
|
if (descriptor) scr_fs_ftruncate(fd, length);
|
|
675
930
|
else if (truncate(path->data, (off_t)length) < 0) scr_fs_throw(errno, "truncate", path);
|
|
676
931
|
}
|
|
677
|
-
} else if (
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
char *text = NULL;
|
|
681
|
-
for (;;) {
|
|
682
|
-
char *grown = realloc(text, capacity);
|
|
683
|
-
if (!grown) scr_bytes_io_oom();
|
|
684
|
-
text = grown;
|
|
685
|
-
ssize_t size = readlink(path->data, text, capacity);
|
|
686
|
-
if (size < 0) { scr_fs_throw(errno, "readlink", path); break; }
|
|
687
|
-
if ((size_t)size < capacity) { result = scr_fs_cb_string(scr_str_new(text, (size_t)size)); break; }
|
|
688
|
-
capacity *= 2;
|
|
689
|
-
}
|
|
690
|
-
free(text);
|
|
691
|
-
#else
|
|
692
|
-
scr_fs_throw(ENOSYS, "readlink", path);
|
|
693
|
-
#endif
|
|
694
|
-
} else if (!strcmp(op, "utimes")) {
|
|
695
|
-
double access = scr_fs_to_unix_timestamp(ARG(1)), modified = scr_fs_to_unix_timestamp(ARG(2));
|
|
696
|
-
#if !defined(_WIN32)
|
|
697
|
-
struct timespec times[2] = {
|
|
698
|
-
{ (time_t)floor(access), (long)((access - floor(access)) * 1000000000) },
|
|
699
|
-
{ (time_t)floor(modified), (long)((modified - floor(modified)) * 1000000000) },
|
|
700
|
-
};
|
|
701
|
-
if (!scr_exc_pending() && utimensat(AT_FDCWD, path->data, times, 0) < 0) scr_fs_throw(errno, "utime", path);
|
|
702
|
-
#else
|
|
703
|
-
struct utimbuf times = { (time_t)access, (time_t)modified };
|
|
704
|
-
if (!scr_exc_pending() && utime(path->data, ×) < 0) scr_fs_throw(errno, "utime", path);
|
|
705
|
-
#endif
|
|
932
|
+
} else if (timestamp) {
|
|
933
|
+
if (timestamp_fd) scr_fs_futimes(fd, access, modified);
|
|
934
|
+
else scr_fs_utimes(path, access, modified, !strcmp(op, "lutimes"));
|
|
706
935
|
} else if (!strcmp(op, "readdir")) {
|
|
707
936
|
if (scr_fs_cb_refuse_option(ARG(1), "encoding") || scr_fs_cb_option_bool(ARG(1), "withFileTypes") || scr_fs_cb_option_bool(ARG(1), "recursive")) {
|
|
708
937
|
if (!scr_exc_pending()) { const char *message = "Recursive readdir and Dirent results have no native lowering"; scr_throw_error_msg_code(SCR_ERR_ERROR, message, strlen(message), "SC2020"); }
|
|
@@ -929,10 +1158,11 @@ ScrBytes *scr_buffer_new_string_fail(const ScrDyn *got) {
|
|
|
929
1158
|
* its time arguments (fs.js's toUnixTimestamp, underscore-exported):
|
|
930
1159
|
* numeric STRINGS pass ToNumber's loose-equality gate (+time == time —
|
|
931
1160
|
* whitespace-only strings answer 0), finite numbers pass (negatives
|
|
932
|
-
* answer now/1000, Node's "past times" shape),
|
|
1161
|
+
* answer now/1000, Node's "past times" shape), Dates supply milliseconds,
|
|
1162
|
+
* and everything else throws
|
|
933
1163
|
* Node's exact ERR_INVALID_ARG_TYPE. Borrowed; the throw is pending on
|
|
934
1164
|
* the dummy 0 return. */
|
|
935
|
-
double
|
|
1165
|
+
double scr_fs_timestamp_value(const ScrDyn *t, const char *name) {
|
|
936
1166
|
if (t->kind == SCR_DYN_STR) {
|
|
937
1167
|
double n = scr_string_to_number(t->v.str);
|
|
938
1168
|
/* +time == time: NaN fails; every parsed number loosely equals its
|
|
@@ -943,14 +1173,41 @@ double scr_fs_to_unix_timestamp(const ScrDyn *t) {
|
|
|
943
1173
|
if (t->v.num < 0) {
|
|
944
1174
|
struct timespec ts;
|
|
945
1175
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
946
|
-
return ((double)ts.tv_sec * 1000.0 + (double)ts.tv_nsec /
|
|
1176
|
+
return ((double)ts.tv_sec * 1000.0 + (double)(ts.tv_nsec / 1000000)) / 1000.0;
|
|
947
1177
|
}
|
|
948
1178
|
return t->v.num;
|
|
949
1179
|
}
|
|
950
|
-
|
|
1180
|
+
if (scr_dyn_native_date_is(t)) return scr_dyn_native_date_value(t) / 1000.0;
|
|
1181
|
+
scr_dyn_arg_type_fail(name, "an instance of Date or an Time in seconds", t);
|
|
951
1182
|
return 0;
|
|
952
1183
|
}
|
|
953
1184
|
|
|
1185
|
+
double scr_fs_to_unix_timestamp(const ScrDyn *t) {
|
|
1186
|
+
return scr_fs_timestamp_value(t, "time");
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
static void scr_fs_path_times_checked(const ScrDyn *input, const ScrDyn *atime, const ScrDyn *mtime, bool nofollow) {
|
|
1190
|
+
ScrStr *path = scr_fs_timestamp_path(input);
|
|
1191
|
+
if (!path) return;
|
|
1192
|
+
double access, modified;
|
|
1193
|
+
if (scr_fs_callback_times(atime, mtime, false, &access, &modified)) scr_fs_utimes(path, access, modified, nofollow);
|
|
1194
|
+
scr_str_release(path);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
void scr_fs_utimes_checked(const ScrDyn *path, const ScrDyn *atime, const ScrDyn *mtime) {
|
|
1198
|
+
scr_fs_path_times_checked(path, atime, mtime, false);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
void scr_fs_lutimes_checked(const ScrDyn *path, const ScrDyn *atime, const ScrDyn *mtime) {
|
|
1202
|
+
scr_fs_path_times_checked(path, atime, mtime, true);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
void scr_fs_futimes_checked(const ScrDyn *fd, const ScrDyn *atime, const ScrDyn *mtime) {
|
|
1206
|
+
double access, modified;
|
|
1207
|
+
if (!scr_fs_callback_times(atime, mtime, true, &access, &modified)) return;
|
|
1208
|
+
if (scr_fs_int_range_chk(fd, "fd", 0, 2147483647.0, ">= 0 && <= 2147483647")) scr_fs_futimes(fd->v.num, access, modified);
|
|
1209
|
+
}
|
|
1210
|
+
|
|
954
1211
|
/* ── the fs argument-validation ladders (checked-dynamic lane) ─────────
|
|
955
1212
|
* Each fs.*Chk libCall replicates its API's Node-order validation over
|
|
956
1213
|
* dyn values and throws Node's exact typed errors; when every validation
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* markGray trial-delete: decrement rc once per internal edge;
|
|
10
10
|
* scan nodes still rc > 0 are externally referenced — re-blacken
|
|
11
11
|
* their subgraph and restore the trial decrements;
|
|
12
|
-
*
|
|
12
|
+
* gather filter the scanned white set, then free it, releasing
|
|
13
13
|
* only edges that LEAVE the white set (each member's
|
|
14
14
|
* teardown releases its untraced children; traced edges were
|
|
15
15
|
* already accounted by markGray).
|
|
@@ -26,9 +26,10 @@
|
|
|
26
26
|
* count was already given up (which would over-decrement and free live
|
|
27
27
|
* data).
|
|
28
28
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* The main graph phases keep a bounded depth-first walk and defer deeper
|
|
30
|
+
* traces to reusable worklists. Ordinary RC destruction and cross-generation
|
|
31
|
+
* releases are separate paths. White candidates are recorded during scan
|
|
32
|
+
* and filtered after outside roots settle, avoiding a separate gather walk.
|
|
32
33
|
*
|
|
33
34
|
* ── generations ──────────────────────────────────────────────────────
|
|
34
35
|
* A pass costs O(objects reachable from its candidates), and a candidate
|
|
@@ -154,6 +155,12 @@ static SCR_TL ScrVec scr_cands;
|
|
|
154
155
|
/* Nursery survivors awaiting promotion (see scr_scan_black). */
|
|
155
156
|
static SCR_TL ScrVec scr_promote;
|
|
156
157
|
|
|
158
|
+
/* Deferred traces cap recursive traversal without changing the common
|
|
159
|
+
* depth-first walk. Restore can run inside scan, so it has its own stack. */
|
|
160
|
+
static SCR_TL ScrVec scr_pending;
|
|
161
|
+
static SCR_TL ScrVec scr_restore_pending;
|
|
162
|
+
#define SCR_CYC_WALK_DEPTH 64
|
|
163
|
+
|
|
157
164
|
/* The gathered white set (freed after the walk completes). */
|
|
158
165
|
static SCR_TL ScrVec scr_white;
|
|
159
166
|
|
|
@@ -281,14 +288,15 @@ void scr_cyc_on_dead(void *obj) {
|
|
|
281
288
|
void scr_cyc_on_release(void *obj) {
|
|
282
289
|
ScrCycHdr *h = scr_cyc_hdr(obj);
|
|
283
290
|
h->color = SCR_CYC_PURPLE;
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
291
|
+
/* Releasing an existing candidate cannot advance the trigger. A pass
|
|
292
|
+
* always re-arms after its teardowns, including any candidates they add. */
|
|
293
|
+
if (h->buffered) return;
|
|
294
|
+
ScrVec *b = &scr_roots[h->gen];
|
|
295
|
+
if (b->n == b->cap) scr_cyc_grow(b);
|
|
296
|
+
h->buffered = 1;
|
|
297
|
+
h->buf_index = b->n;
|
|
298
|
+
b->v[b->n++] = obj;
|
|
299
|
+
scr_cyc_nbuffered++;
|
|
292
300
|
/* Never re-entered: a teardown's releases of untraced children can buffer
|
|
293
301
|
* new candidates mid-collection, but they only wait for the next pass. */
|
|
294
302
|
if (!scr_collecting && scr_cyc_nbuffered >= scr_cyc_trigger)
|
|
@@ -306,69 +314,68 @@ void scr_cyc_on_release(void *obj) {
|
|
|
306
314
|
((child) == NULL || SCR_RC(child) == SIZE_MAX \
|
|
307
315
|
|| scr_cyc_hdr(child)->gen > scr_gen_limit)
|
|
308
316
|
|
|
309
|
-
|
|
317
|
+
/* Trace callbacks forward an integer depth through their opaque context;
|
|
318
|
+
* it is never dereferenced. The ABI already carries it through every edge. */
|
|
319
|
+
static void scr_mark_gray(void *obj, uintptr_t depth);
|
|
310
320
|
static void scr_mg_visit(void *child, void *ctx) {
|
|
311
|
-
(void)ctx;
|
|
312
321
|
if (SCR_CYC_SKIP(child)) return;
|
|
313
|
-
SCR_RC(child) -= 1;
|
|
314
|
-
scr_mark_gray(child);
|
|
322
|
+
SCR_RC(child) -= 1;
|
|
323
|
+
scr_mark_gray(child, (uintptr_t)ctx);
|
|
315
324
|
}
|
|
316
|
-
static void scr_mark_gray(void *obj) {
|
|
325
|
+
static void scr_mark_gray(void *obj, uintptr_t depth) {
|
|
317
326
|
ScrCycHdr *h = scr_cyc_hdr(obj);
|
|
318
327
|
if (h->color == SCR_CYC_GRAY) return;
|
|
319
328
|
h->color = SCR_CYC_GRAY;
|
|
320
|
-
|
|
329
|
+
if (depth == SCR_CYC_WALK_DEPTH) {
|
|
330
|
+
scr_cyc_push(&scr_pending, obj);
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
h->trace(obj, scr_mg_visit, (void *)(depth + 1));
|
|
321
334
|
}
|
|
322
335
|
|
|
323
|
-
static void scr_scan_black(void *obj);
|
|
336
|
+
static void scr_scan_black(void *obj, uintptr_t depth);
|
|
324
337
|
static void scr_sb_visit(void *child, void *ctx) {
|
|
325
|
-
(void)ctx;
|
|
326
338
|
if (SCR_CYC_SKIP(child)) return;
|
|
327
|
-
SCR_RC(child) += 1;
|
|
328
|
-
if (scr_cyc_hdr(child)->color != SCR_CYC_BLACK)
|
|
339
|
+
SCR_RC(child) += 1;
|
|
340
|
+
if (scr_cyc_hdr(child)->color != SCR_CYC_BLACK)
|
|
341
|
+
scr_scan_black(child, (uintptr_t)ctx);
|
|
329
342
|
}
|
|
330
|
-
static void scr_scan_black(void *obj) {
|
|
343
|
+
static void scr_scan_black(void *obj, uintptr_t depth) {
|
|
331
344
|
ScrCycHdr *h = scr_cyc_hdr(obj);
|
|
332
345
|
h->color = SCR_CYC_BLACK;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
h->trace(obj, scr_sb_visit, NULL);
|
|
346
|
+
if (h->gen < SCR_CYC_MATURE) scr_cyc_push(&scr_promote, obj);
|
|
347
|
+
if (depth == SCR_CYC_WALK_DEPTH) {
|
|
348
|
+
scr_cyc_push(&scr_restore_pending, obj);
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
h->trace(obj, scr_sb_visit, (void *)(depth + 1));
|
|
340
352
|
}
|
|
341
353
|
|
|
342
|
-
static void scr_scan(void *obj);
|
|
354
|
+
static void scr_scan(void *obj, uintptr_t depth);
|
|
343
355
|
static void scr_scan_visit(void *child, void *ctx) {
|
|
344
|
-
(void)ctx;
|
|
345
356
|
if (SCR_CYC_SKIP(child)) return;
|
|
346
|
-
scr_scan(child);
|
|
357
|
+
scr_scan(child, (uintptr_t)ctx);
|
|
347
358
|
}
|
|
348
|
-
static void scr_scan(void *obj) {
|
|
359
|
+
static void scr_scan(void *obj, uintptr_t depth) {
|
|
349
360
|
ScrCycHdr *h = scr_cyc_hdr(obj);
|
|
350
361
|
if (h->color != SCR_CYC_GRAY) return;
|
|
351
362
|
if (SCR_RC(obj) > 0) {
|
|
352
|
-
|
|
353
|
-
|
|
363
|
+
scr_scan_black(obj, 0);
|
|
364
|
+
while (scr_restore_pending.n) {
|
|
365
|
+
void *next = scr_restore_pending.v[--scr_restore_pending.n];
|
|
366
|
+
scr_cyc_hdr(next)->trace(next, scr_sb_visit, NULL);
|
|
367
|
+
}
|
|
354
368
|
return;
|
|
355
369
|
}
|
|
356
370
|
h->color = SCR_CYC_WHITE;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
static void scr_collect_white(void *obj);
|
|
361
|
-
static void scr_cw_visit(void *child, void *ctx) {
|
|
362
|
-
(void)ctx;
|
|
363
|
-
if (SCR_CYC_SKIP(child)) return;
|
|
364
|
-
scr_collect_white(child);
|
|
365
|
-
}
|
|
366
|
-
static void scr_collect_white(void *obj) {
|
|
367
|
-
ScrCycHdr *h = scr_cyc_hdr(obj);
|
|
368
|
-
if (h->color != SCR_CYC_WHITE || h->buffered) return;
|
|
369
|
-
h->color = SCR_CYC_DOOMED; /* gathered — don't gather twice */
|
|
370
|
-
h->trace(obj, scr_cw_visit, NULL);
|
|
371
|
+
/* Record each whitened object once. A later outside root can restore it;
|
|
372
|
+
* filter the list only after every scan finishes. No gather trace needed. */
|
|
371
373
|
scr_cyc_push(&scr_white, obj);
|
|
374
|
+
if (depth == SCR_CYC_WALK_DEPTH) {
|
|
375
|
+
scr_cyc_push(&scr_pending, obj);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
h->trace(obj, scr_scan_visit, (void *)(depth + 1));
|
|
372
379
|
}
|
|
373
380
|
|
|
374
381
|
/* ── cross-generation edges ───────────────────────────────────────────── */
|
|
@@ -443,12 +450,10 @@ static size_t scr_cyc_pass(unsigned gen_limit) {
|
|
|
443
450
|
scr_gen_limit = gen_limit;
|
|
444
451
|
|
|
445
452
|
/* markRoots: keep live candidates (still purple), drop the rest — an
|
|
446
|
-
* object re-retained since buffering is black
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
*
|
|
450
|
-
* to gather members of an earlier root's cycle. Candidates ABOVE the
|
|
451
|
-
* limit keep their buffer slots and wait for a full pass. */
|
|
453
|
+
* object re-retained since buffering is black. Drain the buffers before
|
|
454
|
+
* walking: tracing only adjusts counts and worklists, so nothing can
|
|
455
|
+
* re-buffer underneath us. Candidates ABOVE the limit keep their slots
|
|
456
|
+
* and wait for a full pass. */
|
|
452
457
|
scr_cands.n = 0;
|
|
453
458
|
for (unsigned g = 0; g <= gen_limit; g++) {
|
|
454
459
|
for (size_t i = 0; i < scr_roots[g].n; i++) {
|
|
@@ -460,12 +465,31 @@ static size_t scr_cyc_pass(unsigned gen_limit) {
|
|
|
460
465
|
}
|
|
461
466
|
scr_roots[g].n = 0;
|
|
462
467
|
}
|
|
463
|
-
for (size_t i = 0; i < scr_cands.n; i++) scr_mark_gray(scr_cands.v[i]);
|
|
464
|
-
|
|
465
|
-
|
|
468
|
+
for (size_t i = 0; i < scr_cands.n; i++) scr_mark_gray(scr_cands.v[i], 0);
|
|
469
|
+
while (scr_pending.n) {
|
|
470
|
+
void *obj = scr_pending.v[--scr_pending.n];
|
|
471
|
+
scr_cyc_hdr(obj)->trace(obj, scr_mg_visit, NULL);
|
|
472
|
+
}
|
|
466
473
|
|
|
467
474
|
scr_white.n = 0;
|
|
468
|
-
for (size_t i = 0; i < scr_cands.n; i++)
|
|
475
|
+
for (size_t i = 0; i < scr_cands.n; i++) scr_scan(scr_cands.v[i], 0);
|
|
476
|
+
while (scr_pending.n) {
|
|
477
|
+
void *obj = scr_pending.v[--scr_pending.n];
|
|
478
|
+
/* A later outside root may have restored this deferred white node and
|
|
479
|
+
* its descendants already. Never scan a black node's edges again. */
|
|
480
|
+
if (scr_cyc_hdr(obj)->color == SCR_CYC_WHITE)
|
|
481
|
+
scr_cyc_hdr(obj)->trace(obj, scr_scan_visit, NULL);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
size_t dead = 0;
|
|
485
|
+
for (size_t i = 0; i < scr_white.n; i++) {
|
|
486
|
+
void *obj = scr_white.v[i];
|
|
487
|
+
ScrCycHdr *h = scr_cyc_hdr(obj);
|
|
488
|
+
if (h->color != SCR_CYC_WHITE) continue;
|
|
489
|
+
h->color = SCR_CYC_DOOMED;
|
|
490
|
+
scr_white.v[dead++] = obj;
|
|
491
|
+
}
|
|
492
|
+
scr_white.n = dead;
|
|
469
493
|
|
|
470
494
|
/* Pin the cross-generation targets of everything about to be freed, while
|
|
471
495
|
* `gen` still holds the values the walk filtered on (promotion below is
|