@scriptc/cli-darwin-x64 0.2.1 → 0.2.2

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.
Files changed (118) hide show
  1. package/dist/THIRD_PARTY_NOTICES +1 -1
  2. package/dist/bin/scriptc +0 -0
  3. package/dist/bin/scriptc.json +1 -1
  4. package/dist/lib/declarations/scriptc-node-fallback.d.ts +59 -4
  5. package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
  6. package/dist/lib/llvm/package.json +1 -1
  7. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async.o +0 -0
  8. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
  9. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
  10. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
  11. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_crypto_async.o +0 -0
  12. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
  13. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
  14. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
  15. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  16. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_qs.o +0 -0
  17. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  18. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url.o +0 -0
  19. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
  20. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
  21. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  22. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  23. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
  24. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
  25. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
  26. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
  27. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  28. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  29. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
  30. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  31. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
  32. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
  33. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  34. package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  35. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  36. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  37. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
  38. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  39. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  40. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  41. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
  42. package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  43. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  44. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  45. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
  46. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  47. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  48. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  49. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url.o +0 -0
  50. package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  51. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  52. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  53. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
  54. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  55. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  56. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  57. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
  58. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  59. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  60. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  61. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
  62. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  63. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  64. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  65. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
  66. package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  67. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async.o +0 -0
  68. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
  69. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  70. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  71. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
  72. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
  73. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
  74. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
  75. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
  76. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_qs.o +0 -0
  77. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
  78. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url.o +0 -0
  79. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
  80. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
  81. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  82. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  83. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
  84. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
  85. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
  86. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
  87. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  88. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  89. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
  90. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  91. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
  92. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
  93. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  94. package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  95. package/dist/lib/runtime-darwin-x64/package.json +1 -1
  96. package/dist/lib/runtime-darwin-x64/runtime-pack.json +177 -177
  97. package/dist/lib/runtime-sources/package.json +1 -1
  98. package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
  99. package/dist/lib/runtime-sources/src/scr_async.c +12 -4
  100. package/dist/lib/runtime-sources/src/scr_async_dyn.c +118 -24
  101. package/dist/lib/runtime-sources/src/scr_bytes.c +226 -0
  102. package/dist/lib/runtime-sources/src/scr_bytes_io.c +52 -5
  103. package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
  104. package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +181 -43
  105. package/dist/lib/runtime-sources/src/scr_fetch.c +45 -1
  106. package/dist/lib/runtime-sources/src/scr_file_handle.c +31 -0
  107. package/dist/lib/runtime-sources/src/scr_island.c +1188 -392
  108. package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -9
  109. package/dist/lib/runtime-sources/src/scr_json.c +449 -52
  110. package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
  111. package/dist/lib/runtime-sources/src/scr_lib.c +816 -34
  112. package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
  113. package/dist/lib/runtime-sources/src/scr_regex.c +42 -5
  114. package/dist/lib/runtime-sources/src/scr_runtime.h +67 -8
  115. package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +12 -12
  116. package/dist/lib/runtime-sources/src/scr_url.c +34 -7
  117. package/dist/lib/runtime-sources/src/scr_web.c +129 -26
  118. package/package.json +1 -1
@@ -2663,7 +2663,7 @@ static JSValue isl_host_env(JSContext *ctx, JSValueConst this_val, int argc,
2663
2663
  for (size_t i = 0; i + 1 < n; i += 2) {
2664
2664
  ScrStr *k = scr_arr_get_ref(pairs, (double)i);
2665
2665
  ScrStr *v = scr_arr_get_ref(pairs, (double)(i + 1));
2666
- JS_SetPropertyStr(ctx, obj, k->data, JS_NewStringLen(ctx, v->data, v->len));
2666
+ JS_DefinePropertyValueStr(ctx, obj, k->data, JS_NewStringLen(ctx, v->data, v->len), JS_PROP_C_W_E);
2667
2667
  scr_str_release(k);
2668
2668
  scr_str_release(v);
2669
2669
  }
@@ -2856,6 +2856,120 @@ static ScrStr *isl_arg_str(JSContext *ctx, JSValueConst v) {
2856
2856
  return out;
2857
2857
  }
2858
2858
 
2859
+ /* Dotenv and environment mutations share the native process environment.
2860
+ * The JS layer validates types before these host calls. */
2861
+ static JSValue isl_host_env_get(JSContext *ctx, JSValueConst this_val, int argc,
2862
+ JSValueConst *argv) {
2863
+ (void)this_val; (void)argc;
2864
+ ScrStr *key = isl_arg_str(ctx, argv[0]);
2865
+ if (!key) return JS_EXCEPTION;
2866
+ ScrStr *value = scr_env_get(key);
2867
+ scr_str_release(key);
2868
+ JSValue result = value ? JS_NewStringLen(ctx, value->data, value->len) : JS_UNDEFINED;
2869
+ scr_str_release(value);
2870
+ return result;
2871
+ }
2872
+
2873
+ static JSValue isl_host_chdir(JSContext *ctx, JSValueConst this_val, int argc,
2874
+ JSValueConst *argv) {
2875
+ (void)this_val; (void)argc;
2876
+ ScrStr *directory = isl_arg_str(ctx, argv[0]);
2877
+ if (!directory) return JS_EXCEPTION;
2878
+ scr_process_chdir(directory);
2879
+ scr_str_release(directory);
2880
+ return scr_exc_pending() ? isl_throw_pending(ctx) : JS_UNDEFINED;
2881
+ }
2882
+
2883
+ static JSValue isl_host_env_set(JSContext *ctx, JSValueConst this_val, int argc,
2884
+ JSValueConst *argv) {
2885
+ (void)this_val; (void)argc;
2886
+ ScrStr *key = isl_arg_str(ctx, argv[0]);
2887
+ if (!key) return JS_EXCEPTION;
2888
+ ScrStr *value = isl_arg_str(ctx, argv[1]);
2889
+ if (!value) { scr_str_release(key); return JS_EXCEPTION; }
2890
+ scr_env_set(key, value);
2891
+ scr_str_release(key);
2892
+ scr_str_release(value);
2893
+ return JS_TRUE;
2894
+ }
2895
+
2896
+ static JSValue isl_host_env_delete(JSContext *ctx, JSValueConst this_val, int argc,
2897
+ JSValueConst *argv) {
2898
+ (void)this_val; (void)argc;
2899
+ ScrStr *key = isl_arg_str(ctx, argv[0]);
2900
+ if (!key) return JS_EXCEPTION;
2901
+ scr_env_unset(key);
2902
+ scr_str_release(key);
2903
+ return JS_TRUE;
2904
+ }
2905
+
2906
+ static JSValue isl_host_parse_env(JSContext *ctx, JSValueConst this_val, int argc,
2907
+ JSValueConst *argv) {
2908
+ (void)this_val; (void)argc;
2909
+ ScrDyn *content = isl_dyn_from_value(argv[0]);
2910
+ ScrDyn *parsed = scr_util_parse_env(content);
2911
+ scr_dyn_release(content);
2912
+ if (!parsed) return isl_throw_pending(ctx);
2913
+ /* Preserve embedded NUL keys: JS_SetPropertyStr would truncate them. */
2914
+ JSValue result = JS_NewObject(ctx);
2915
+ for (size_t i = 0; i < parsed->v.obj.len; i++) {
2916
+ const ScrDynEntry *entry = &parsed->v.obj.entries[i];
2917
+ JSAtom key = JS_NewAtomLen(ctx, entry->key, entry->key_len);
2918
+ int status = JS_SetProperty(ctx, result, key, isl_from_dyn(entry->value));
2919
+ JS_FreeAtom(ctx, key);
2920
+ if (status < 0) { JS_FreeValue(ctx, result); result = JS_EXCEPTION; break; }
2921
+ }
2922
+ scr_dyn_release(parsed);
2923
+ return result;
2924
+ }
2925
+
2926
+ static JSValue isl_host_transcode(JSContext *ctx, JSValueConst this_val, int argc,
2927
+ JSValueConst *argv) {
2928
+ (void)this_val;
2929
+ if (argc != 3) return JS_ThrowTypeError(ctx, "invalid transcode bridge arity");
2930
+ size_t length = 0;
2931
+ uint8_t *data = JS_GetUint8Array(ctx, &length, argv[0]);
2932
+ if (!data && length) return JS_EXCEPTION;
2933
+ ScrBytes bytes = {0};
2934
+ bytes.elem = SCR_BYTES_U8; bytes.len = length; bytes.data = data;
2935
+ ScrDyn source = {0};
2936
+ source.kind = SCR_DYN_BYTES; source.v.bytes = &bytes;
2937
+ ScrDyn *from = isl_dyn_from_value(argv[1]), *to = isl_dyn_from_value(argv[2]);
2938
+ ScrBytes *result = scr_buffer_transcode(&source, from, to);
2939
+ scr_dyn_release(from); scr_dyn_release(to);
2940
+ if (!result) {
2941
+ JSValue error = isl_pending_to_value(ctx);
2942
+ JSValue code = JS_GetPropertyStr(ctx, error, "code");
2943
+ const char *name = JS_ToCString(ctx, code);
2944
+ if (name && strcmp(name, "U_INVALID_CHAR_FOUND") == 0) JS_SetPropertyStr(ctx, error, "errno", JS_NewInt32(ctx, 10));
2945
+ else if (name && strcmp(name, "U_ILLEGAL_ARGUMENT_ERROR") == 0) JS_SetPropertyStr(ctx, error, "errno", JS_NewInt32(ctx, 1));
2946
+ JS_FreeCString(ctx, name); JS_FreeValue(ctx, code);
2947
+ return JS_Throw(ctx, error);
2948
+ }
2949
+ JSValue value = JS_NewUint8ArrayCopy(ctx, result->data, result->len);
2950
+ scr_bytes_release(result);
2951
+ return value;
2952
+ }
2953
+
2954
+ static JSValue isl_host_load_env_file(JSContext *ctx, JSValueConst this_val, int argc,
2955
+ JSValueConst *argv) {
2956
+ (void)this_val;
2957
+ ScrDyn *path;
2958
+ if (argc > 1 && JS_ToBool(ctx, argv[1])) {
2959
+ size_t len;
2960
+ uint8_t *data = JS_GetUint8Array(ctx, &len, argv[0]);
2961
+ if (!data) return JS_EXCEPTION;
2962
+ ScrBytes *bytes = scr_bytes_new(SCR_BYTES_U8, (double)len);
2963
+ if (len) memcpy(bytes->data, data, len);
2964
+ path = scr_dyn_new_bytes(bytes);
2965
+ path->buffer = argc > 2 && JS_ToBool(ctx, argv[2]);
2966
+ scr_bytes_release(bytes);
2967
+ } else path = isl_dyn_from_value(argc ? argv[0] : JS_UNDEFINED);
2968
+ scr_process_load_env_file(path);
2969
+ scr_dyn_release(path);
2970
+ return scr_exc_pending() ? isl_throw_pending(ctx) : JS_UNDEFINED;
2971
+ }
2972
+
2859
2973
  static JSValue isl_host_fs(JSContext *ctx, JSValueConst this_val, int argc,
2860
2974
  JSValueConst *argv) {
2861
2975
  (void)this_val;
@@ -2871,8 +2985,47 @@ static JSValue isl_host_fs(JSContext *ctx, JSValueConst this_val, int argc,
2871
2985
  return JS_EXCEPTION;
2872
2986
  }
2873
2987
  }
2874
- if (strcmp(op, "readFile") == 0) {
2875
- ScrBytes *data = scr_fs_read_file_bytes(a);
2988
+ if (strcmp(op, "open") == 0) {
2989
+ double flags = 0, mode = 0666;
2990
+ JS_ToFloat64(ctx, &flags, argv[2]);
2991
+ JS_ToFloat64(ctx, &mode, argv[3]);
2992
+ ret = JS_NewFloat64(ctx, scr_fs_open_native(a, flags, mode));
2993
+ } else if (strcmp(op, "close") == 0 || strcmp(op, "fsync") == 0 ||
2994
+ strcmp(op, "fdatasync") == 0 || strcmp(op, "ftruncate") == 0 ||
2995
+ strcmp(op, "fchmod") == 0) {
2996
+ double fd = 0, value = 0;
2997
+ JS_ToFloat64(ctx, &fd, argv[1]);
2998
+ if (argc > 2) JS_ToFloat64(ctx, &value, argv[2]);
2999
+ if (strcmp(op, "close") == 0) scr_fs_close(fd);
3000
+ else if (strcmp(op, "fsync") == 0) scr_fs_fsync(fd);
3001
+ else if (strcmp(op, "fdatasync") == 0) scr_fs_fdatasync(fd);
3002
+ else if (strcmp(op, "ftruncate") == 0) scr_fs_ftruncate(fd, value);
3003
+ else scr_fs_fchmod(fd, value);
3004
+ } else if (strcmp(op, "read") == 0 || strcmp(op, "write") == 0 ||
3005
+ strcmp(op, "readv") == 0 || strcmp(op, "writev") == 0) {
3006
+ double fd = 0, offset = 0, length = 0, position = -1;
3007
+ JS_ToFloat64(ctx, &fd, argv[1]);
3008
+ JS_ToFloat64(ctx, &offset, argv[3]);
3009
+ JS_ToFloat64(ctx, &length, argv[4]);
3010
+ JS_ToFloat64(ctx, &position, argv[5]);
3011
+ size_t size = 0;
3012
+ uint8_t *data = JS_GetUint8Array(ctx, &size, argv[2]);
3013
+ if (data || size == 0) {
3014
+ ScrBytes buffer = {SIZE_MAX, size, SCR_BYTES_U8, data, NULL};
3015
+ if (strcmp(op, "readv") == 0 && argc > 6 && JS_ToBool(ctx, argv[6])) {
3016
+ scr_fs_throw(EINVAL, "read", NULL);
3017
+ } else {
3018
+ double n = op[0] == 'r'
3019
+ ? strcmp(op, "readv") == 0 && length == 0 ? scr_fs_read_zero(fd, position)
3020
+ : scr_fs_read_sync(fd, &buffer, offset, length, position)
3021
+ : scr_fs_write_sync(fd, &buffer, offset, length, position);
3022
+ ret = JS_NewFloat64(ctx, n);
3023
+ }
3024
+ } else ret = JS_EXCEPTION;
3025
+ } else if (strcmp(op, "readFile") == 0) {
3026
+ double fd = 0;
3027
+ if (!a) JS_ToFloat64(ctx, &fd, argv[1]);
3028
+ ScrBytes *data = a ? scr_fs_read_file_bytes(a) : scr_fs_read_fd_bytes(fd);
2876
3029
  if (data) {
2877
3030
  ret = JS_NewUint8ArrayCopy(ctx, data->data, (size_t)scr_bytes_len(data));
2878
3031
  scr_bytes_release(data);
@@ -2881,10 +3034,22 @@ static JSValue isl_host_fs(JSContext *ctx, JSValueConst this_val, int argc,
2881
3034
  size_t len = 0;
2882
3035
  uint8_t *buf = JS_GetUint8Array(ctx, &len, argv[2]);
2883
3036
  if (buf || len == 0) {
2884
- ScrStr *data = scr_str_new((const char *)buf, len);
2885
- if (strcmp(op, "writeFile") == 0) scr_fs_write_file(a, data);
2886
- else scr_fs_append_file(a, data);
2887
- scr_str_release(data);
3037
+ if (a) {
3038
+ ScrStr *data = scr_str_new((const char *)buf, len);
3039
+ if (strcmp(op, "writeFile") == 0) scr_fs_write_file(a, data);
3040
+ else scr_fs_append_file(a, data);
3041
+ scr_str_release(data);
3042
+ } else {
3043
+ double fd = 0;
3044
+ JS_ToFloat64(ctx, &fd, argv[1]);
3045
+ ScrBytes buffer = {SIZE_MAX, len, SCR_BYTES_U8, buf, NULL};
3046
+ size_t at = 0;
3047
+ while (at < len && !scr_exc_pending()) {
3048
+ double n = scr_fs_write_sync(fd, &buffer, (double)at, (double)(len - at), -1);
3049
+ if (n <= 0) { if (!scr_exc_pending()) scr_fs_throw(EIO, "write", NULL); break; }
3050
+ at += (size_t)n;
3051
+ }
3052
+ }
2888
3053
  } else {
2889
3054
  ret = JS_EXCEPTION;
2890
3055
  }
@@ -2945,8 +3110,11 @@ static JSValue isl_host_fs(JSContext *ctx, JSValueConst this_val, int argc,
2945
3110
  scr_fs_scandir_free(s);
2946
3111
  ret = arr;
2947
3112
  }
2948
- } else if (strcmp(op, "stat") == 0 || strcmp(op, "lstat") == 0) {
2949
- ScrStats *st = strcmp(op, "stat") == 0 ? scr_fs_stat(a) : scr_fs_lstat(a);
3113
+ } else if (strcmp(op, "stat") == 0 || strcmp(op, "lstat") == 0 || strcmp(op, "fstat") == 0) {
3114
+ double fd = 0;
3115
+ if (strcmp(op, "fstat") == 0) JS_ToFloat64(ctx, &fd, argv[1]);
3116
+ ScrStats *st = strcmp(op, "fstat") == 0 ? scr_fs_fstat(fd)
3117
+ : strcmp(op, "stat") == 0 ? scr_fs_stat(a) : scr_fs_lstat(a);
2950
3118
  if (st) {
2951
3119
  JSValue arr = JS_NewArray(ctx);
2952
3120
  JS_SetPropertyUint32(ctx, arr, 0, JS_NewBool(ctx, scr_stats_is_file(st)));
@@ -3205,6 +3373,14 @@ static JSValue isl_host_fs_constants(JSContext *ctx, JSValueConst this_val, int
3205
3373
  ISL_CONST(O_EXCL);
3206
3374
  ISL_CONST(O_TRUNC);
3207
3375
  ISL_CONST(O_APPEND);
3376
+ #ifdef O_SYNC
3377
+ ISL_CONST(O_SYNC);
3378
+ #else
3379
+ JS_SetPropertyStr(ctx, o, "O_SYNC", JS_NewInt32(ctx, 0));
3380
+ #endif
3381
+ #ifdef O_NOFOLLOW
3382
+ ISL_CONST(O_NOFOLLOW);
3383
+ #endif
3208
3384
  #ifdef O_NONBLOCK
3209
3385
  ISL_CONST(O_NONBLOCK);
3210
3386
  #endif
@@ -3253,7 +3429,7 @@ static JSValue isl_host_digest(JSContext *ctx, JSValueConst this_val, int argc,
3253
3429
  JS_FreeCString(ctx, alg);
3254
3430
  return JS_EXCEPTION;
3255
3431
  }
3256
- unsigned char out[32];
3432
+ unsigned char out[64];
3257
3433
  size_t n = scr_crypto_digest_raw(alg, data, len, out);
3258
3434
  JS_FreeCString(ctx, alg);
3259
3435
  return n == 0 ? JS_UNDEFINED : JS_NewUint8ArrayCopy(ctx, out, n);
@@ -3273,12 +3449,38 @@ static JSValue isl_host_hmac(JSContext *ctx, JSValueConst this_val, int argc,
3273
3449
  JS_FreeCString(ctx, alg);
3274
3450
  return JS_EXCEPTION;
3275
3451
  }
3276
- unsigned char out[32];
3452
+ unsigned char out[64];
3277
3453
  size_t n = scr_crypto_hmac_raw(alg, key, keylen, data, len, out);
3278
3454
  JS_FreeCString(ctx, alg);
3279
3455
  return n == 0 ? JS_UNDEFINED : JS_NewUint8ArrayCopy(ctx, out, n);
3280
3456
  }
3281
3457
 
3458
+ /* The island validates JavaScript overloads; the native RFC 7914 core
3459
+ * owns memory accounting, ROMix, and sensitive scratch cleanup. */
3460
+ static JSValue isl_host_scrypt(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
3461
+ (void)this_val;
3462
+ if (argc != 7) return JS_ThrowTypeError(ctx, "invalid scrypt bridge arity");
3463
+ size_t password_len = 0, salt_len = 0;
3464
+ uint8_t *password_data = JS_GetUint8Array(ctx, &password_len, argv[0]);
3465
+ uint8_t *salt_data = JS_GetUint8Array(ctx, &salt_len, argv[1]);
3466
+ if ((!password_data && password_len) || (!salt_data && salt_len)) return JS_EXCEPTION;
3467
+ double values[5];
3468
+ for (int i = 0; i < 5; i++) if (JS_ToFloat64(ctx, &values[i], argv[i + 2]) < 0) return JS_EXCEPTION;
3469
+ /* These wrappers borrow engine storage for the synchronous core. No
3470
+ * extra heap copies of the password or salt outlive the bridge call. */
3471
+ ScrBytes password = {0}, salt = {0};
3472
+ password.elem = salt.elem = SCR_BYTES_U8;
3473
+ password.len = password_len;
3474
+ password.data = password_data;
3475
+ salt.len = salt_len;
3476
+ salt.data = salt_data;
3477
+ ScrBytes *result = scr_crypto_scrypt_derive(&password, &salt, values[0], values[1], values[2], values[3], values[4]);
3478
+ if (scr_exc_pending()) return isl_throw_pending(ctx);
3479
+ JSValue value = JS_NewUint8ArrayCopy(ctx, result->data, result->len);
3480
+ scr_bytes_release(result);
3481
+ return value;
3482
+ }
3483
+
3282
3484
  static JSValue isl_host_pid(JSContext *ctx, JSValueConst this_val, int argc,
3283
3485
  JSValueConst *argv) {
3284
3486
  (void)this_val;
@@ -3658,20 +3860,19 @@ static const char isl_modules_bootstrap[] =
3658
3860
  /* Node's events module: the emitter surface streams and CLIs drive —
3659
3861
  * prepend/once/remove with listener-unwrap, maxListeners bookkeeping
3660
3862
  * (warnings are not emitted), eventNames/rawListeners, Node's
3661
- * unhandled-'error' throw, and the once/getEventListeners statics.
3863
+ * unhandled-'error' throw, cancellable once, and async event iteration.
3662
3864
  * EventEmitter is callable so legacy constructors can use .call(this). */
3663
3865
  " builtins.events = memo(() => {\n"
3664
3866
  " function EventEmitter() {\n"
3665
3867
  " if (this._events === undefined || !Object.prototype.hasOwnProperty.call(this, '_events')) this._events = Object.create(null);\n"
3666
3868
  " if (!Object.prototype.hasOwnProperty.call(this, '_maxListeners')) this._maxListeners = undefined;\n"
3667
3869
  " }\n"
3870
+ " const checkListener = (listener) => {\n"
3871
+ " if (typeof listener !== 'function') envArgumentError('listener', 'of type function', listener);\n"
3872
+ " };\n"
3668
3873
  " class EventEmitterMethods {\n"
3669
3874
  " _add(n, f, prepend) {\n"
3670
- " if (typeof f !== 'function') {\n"
3671
- " const e = new TypeError('The \"listener\" argument must be of type function. Received ' + (f === null ? 'null' : typeof f));\n"
3672
- " e.code = 'ERR_INVALID_ARG_TYPE';\n"
3673
- " throw e;\n"
3674
- " }\n"
3875
+ " checkListener(f);\n"
3675
3876
  " this.emit('newListener', n, f.listener !== undefined ? f.listener : f);\n"
3676
3877
  " const a = this._events[n] = this._events[n] || [];\n"
3677
3878
  " if (prepend) a.unshift(f); else a.push(f);\n"
@@ -3681,42 +3882,64 @@ static const char isl_modules_bootstrap[] =
3681
3882
  " addListener(n, f) { return this.on(n, f); }\n"
3682
3883
  " prependListener(n, f) { return this._add(n, f, true); }\n"
3683
3884
  " _wrapOnce(n, f) {\n"
3684
- " const g = (...a) => { this.removeListener(n, g); f.apply(this, a); };\n"
3885
+ " let fired = false;\n"
3886
+ " const g = (...a) => {\n"
3887
+ " if (fired) return;\n"
3888
+ " this.removeListener(n, g);\n"
3889
+ " fired = true;\n"
3890
+ " return f.apply(this, a);\n"
3891
+ " };\n"
3892
+ " Object.defineProperty(g, \"name\", { value: \"bound onceWrapper\", configurable: true });\n"
3685
3893
  " g.listener = f;\n"
3686
3894
  " return g;\n"
3687
3895
  " }\n"
3688
- " once(n, f) { return this._add(n, this._wrapOnce(n, f), false); }\n"
3689
- " prependOnceListener(n, f) { return this._add(n, this._wrapOnce(n, f), true); }\n"
3896
+ " once(n, f) { checkListener(f); return this._add(n, this._wrapOnce(n, f), false); }\n"
3897
+ " prependOnceListener(n, f) { checkListener(f); return this._add(n, this._wrapOnce(n, f), true); }\n"
3690
3898
  " removeListener(n, f) {\n"
3899
+ " checkListener(f);\n"
3691
3900
  " const a = this._events[n];\n"
3692
3901
  " if (a) {\n"
3693
- " const i = a.findIndex((x) => x === f || x.listener === f);\n"
3902
+ " let i = a.length - 1;\n"
3903
+ " while (i >= 0 && a[i] !== f && a[i].listener !== f) i--;\n"
3694
3904
  " if (i >= 0) {\n"
3695
- " const x = a[i];\n"
3905
+ " const x = a.length === 1 ? (a[i].listener !== undefined ? a[i].listener : a[i]) : f;\n"
3696
3906
  " a.splice(i, 1);\n"
3697
3907
  " if (a.length === 0) delete this._events[n];\n"
3698
- " this.emit('removeListener', n, x.listener !== undefined ? x.listener : x);\n"
3908
+ " this.emit('removeListener', n, x);\n"
3699
3909
  " }\n"
3700
3910
  " }\n"
3701
3911
  " return this;\n"
3702
3912
  " }\n"
3703
3913
  " off(n, f) { return this.removeListener(n, f); }\n"
3704
3914
  " removeAllListeners(n) {\n"
3705
- " if (n === undefined) this._events = Object.create(null);\n"
3706
- " else delete this._events[n];\n"
3915
+ " if (!this._events.removeListener) {\n"
3916
+ " if (arguments.length === 0) this._events = Object.create(null);\n"
3917
+ " else delete this._events[n];\n"
3918
+ " return this;\n"
3919
+ " }\n"
3920
+ " if (arguments.length === 0) {\n"
3921
+ " for (const key of Reflect.ownKeys(this._events)) {\n"
3922
+ " if (key !== 'removeListener') this.removeAllListeners(key);\n"
3923
+ " }\n"
3924
+ " this.removeAllListeners('removeListener');\n"
3925
+ " this._events = Object.create(null);\n"
3926
+ " } else {\n"
3927
+ " const listeners = this._events[n];\n"
3928
+ " if (listeners) for (let i = listeners.length - 1; i >= 0; i--) this.removeListener(n, listeners[i]);\n"
3929
+ " }\n"
3707
3930
  " return this;\n"
3708
3931
  " }\n"
3709
3932
  " setMaxListeners(m) { this._maxListeners = m; return this; }\n"
3710
3933
  " getMaxListeners() { return this._maxListeners === undefined ? EventEmitter.defaultMaxListeners : this._maxListeners; }\n"
3711
3934
  " emit(n, ...args) {\n"
3935
+ " if (n === 'error' && this._events[EventEmitter.errorMonitor]) this.emit(EventEmitter.errorMonitor, ...args);\n"
3712
3936
  " const a = this._events[n];\n"
3713
3937
  " if (!a || a.length === 0) {\n"
3714
3938
  " if (n === 'error') {\n"
3715
- /* Node throws the unhandled error payload (or a synthetic one) —
3716
- * inside the island this crosses the bridge like any engine throw. */
3939
+ /* Unhandled error payloads cross the bridge as engine exceptions. */
3717
3940
  " const err = args[0];\n"
3718
3941
  " if (err instanceof Error) throw err;\n"
3719
- " const e = new Error(\"Unhandled error.\" + (err === undefined ? '' : ' (' + String(err) + ')'));\n"
3942
+ " const e = new Error(\"Unhandled error.\" + ' (' + builtins.util().inspect(err) + ')');\n"
3720
3943
  " e.code = 'ERR_UNHANDLED_ERROR';\n"
3721
3944
  " e.context = err;\n"
3722
3945
  " throw e;\n"
@@ -3726,13 +3949,16 @@ static const char isl_modules_bootstrap[] =
3726
3949
  " for (const f of a.slice()) f.apply(this, args);\n"
3727
3950
  " return true;\n"
3728
3951
  " }\n"
3729
- " listenerCount(n) { const a = this._events[n]; return a ? a.length : 0; }\n"
3952
+ " listenerCount(n, listener) {\n"
3953
+ " const a = this._events[n];\n"
3954
+ " return a ? listener == null ? a.length : a.filter(f => f === listener || f.listener === listener).length : 0;\n"
3955
+ " }\n"
3730
3956
  " listeners(n) {\n"
3731
3957
  " const a = this._events[n];\n"
3732
3958
  " return a ? a.map((x) => (x.listener !== undefined ? x.listener : x)) : [];\n"
3733
3959
  " }\n"
3734
3960
  " rawListeners(n) { const a = this._events[n]; return a ? a.slice() : []; }\n"
3735
- " eventNames() { return Object.keys(this._events); }\n"
3961
+ " eventNames() { return Reflect.ownKeys(this._events); }\n"
3736
3962
  " }\n"
3737
3963
  " EventEmitter.prototype = EventEmitterMethods.prototype;\n"
3738
3964
  " EventEmitter.prototype.constructor = EventEmitter;\n"
@@ -3742,18 +3968,155 @@ static const char isl_modules_bootstrap[] =
3742
3968
  " EventEmitter.listenerCount = (emitter, n) => emitter.listenerCount(n);\n"
3743
3969
  " EventEmitter.getEventListeners = (emitter, n) => emitter.listeners(n);\n"
3744
3970
  " EventEmitter.setMaxListeners = (m, ...emitters) => { for (const e of emitters) e.setMaxListeners(m); };\n"
3745
- " EventEmitter.once = (emitter, name) => new Promise((resolve, reject) => {\n"
3746
- " const onEvent = (...args) => {\n"
3747
- " emitter.removeListener('error', onError);\n"
3748
- " resolve(args);\n"
3971
+ " const resistStopPropagation = Symbol.for('scriptc.events.resistStopPropagation');\n"
3972
+ " const checkSignal = (signal, name) => {\n"
3973
+ " if (signal !== undefined && (signal === null || typeof signal !== 'object' || !('aborted' in signal)))\n"
3974
+ " envArgumentError(name, 'an instance of AbortSignal', signal);\n"
3975
+ " };\n"
3976
+ " const checkOptions = (options) => {\n"
3977
+ " if (options === null || typeof options !== 'object' || Array.isArray(options))\n"
3978
+ " envArgumentError('options', 'of type object', options);\n"
3979
+ " };\n"
3980
+ " const abortError = (signal) => {\n"
3981
+ " const error = new Error('The operation was aborted', { cause: signal.reason });\n"
3982
+ " error.name = 'AbortError';\n"
3983
+ " error.code = 'ABORT_ERR';\n"
3984
+ " return error;\n"
3985
+ " };\n"
3986
+ " const add = (emitter, name, listener, flags) => {\n"
3987
+ " if (typeof emitter.on === 'function') {\n"
3988
+ " if (flags && flags.once) emitter.once(name, listener);\n"
3989
+ " else emitter.on(name, listener);\n"
3990
+ " } else if (typeof emitter.addEventListener === 'function') emitter.addEventListener(name, listener, flags);\n"
3991
+ " else envArgumentError('emitter', 'an instance of EventEmitter', emitter);\n"
3992
+ " };\n"
3993
+ " const remove = (emitter, name, listener) => {\n"
3994
+ " if (typeof emitter.removeListener === 'function') emitter.removeListener(name, listener);\n"
3995
+ " else if (typeof emitter.removeEventListener === 'function') emitter.removeEventListener(name, listener);\n"
3996
+ " else envArgumentError('emitter', 'an instance of EventEmitter', emitter);\n"
3997
+ " };\n"
3998
+ " EventEmitter.addAbortListener = (signal, listener) => {\n"
3999
+ " if (signal === undefined) envArgumentError('signal', 'an instance of AbortSignal', signal);\n"
4000
+ " checkSignal(signal, 'signal');\n"
4001
+ " checkListener(listener);\n"
4002
+ " let dispose;\n"
4003
+ " if (signal.aborted) queueMicrotask(() => listener());\n"
4004
+ " else {\n"
4005
+ " signal.addEventListener('abort', listener, { once: true, [resistStopPropagation]: true });\n"
4006
+ " dispose = () => signal.removeEventListener('abort', listener);\n"
4007
+ " }\n"
4008
+ " return { __proto__: null, [Symbol.dispose]() { if (dispose) dispose(); } };\n"
4009
+ " };\n"
4010
+ " EventEmitter.once = async (emitter, name, options = {}) => {\n"
4011
+ " checkOptions(options);\n"
4012
+ " const signal = options.signal;\n"
4013
+ " checkSignal(signal, 'options.signal');\n"
4014
+ " if (signal && signal.aborted) throw abortError(signal);\n"
4015
+ " return new Promise((resolve, reject) => {\n"
4016
+ " const onError = (err) => {\n"
4017
+ " remove(emitter, name, onEvent);\n"
4018
+ " if (signal) remove(signal, 'abort', onAbort);\n"
4019
+ " reject(err);\n"
4020
+ " };\n"
4021
+ " const onEvent = (...args) => {\n"
4022
+ " if (typeof emitter.removeListener === 'function') emitter.removeListener('error', onError);\n"
4023
+ " if (signal) remove(signal, 'abort', onAbort);\n"
4024
+ " resolve(args);\n"
4025
+ " };\n"
4026
+ " const onAbort = () => {\n"
4027
+ " remove(emitter, name, onEvent);\n"
4028
+ " remove(emitter, 'error', onError);\n"
4029
+ " reject(abortError(signal));\n"
4030
+ " };\n"
4031
+ " const flags = { __proto__: null, once: true, [resistStopPropagation]: true };\n"
4032
+ " add(emitter, name, onEvent, flags);\n"
4033
+ " if (name !== 'error' && typeof emitter.once === 'function') emitter.once('error', onError);\n"
4034
+ " if (signal) add(signal, 'abort', onAbort, flags);\n"
4035
+ " });\n"
4036
+ " };\n"
4037
+ " const queue = () => {\n"
4038
+ " let values = [], head = 0;\n"
4039
+ " return {\n"
4040
+ " get size() { return values.length - head; },\n"
4041
+ " push(value) { values.push(value); },\n"
4042
+ " shift() {\n"
4043
+ " const value = values[head];\n"
4044
+ " values[head++] = undefined;\n"
4045
+ " if (head === values.length) { values = []; head = 0; }\n"
4046
+ " else if (head >= 1024 && head * 2 > values.length) { values = values.slice(head); head = 0; }\n"
4047
+ " return value;\n"
4048
+ " },\n"
4049
+ " };\n"
4050
+ " };\n"
4051
+ " const checkWatermark = (value, name) => {\n"
4052
+ " if (typeof value !== 'number') envArgumentError(name, 'of type number', value);\n"
4053
+ " if (!Number.isInteger(value) || value < 1 || value > Number.MAX_SAFE_INTEGER) {\n"
4054
+ " const range = Number.isInteger(value) ? '>= 1 && <= 9007199254740991' : 'an integer';\n"
4055
+ " const received = Number.isInteger(value) && Math.abs(value) > 2 ** 32 ? String(value).replace(/\\B(?=(\\d{3})+(?!\\d))/g, '_') : String(value);\n"
4056
+ " const error = new RangeError('The value of \"' + name + '\" is out of range. It must be ' + range + '. Received ' + received);\n"
4057
+ " error.code = 'ERR_OUT_OF_RANGE';\n"
4058
+ " throw error;\n"
4059
+ " }\n"
4060
+ " };\n"
4061
+ " const iteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf((async function* () {})())));\n"
4062
+ " EventEmitter.on = (emitter, name, options = {}) => {\n"
4063
+ " checkOptions(options);\n"
4064
+ " const signal = options.signal;\n"
4065
+ " checkSignal(signal, 'options.signal');\n"
4066
+ " if (signal && signal.aborted) throw abortError(signal);\n"
4067
+ " const high = options.highWaterMark ?? options.highWatermark ?? Number.MAX_SAFE_INTEGER;\n"
4068
+ " checkWatermark(high, 'options.highWaterMark');\n"
4069
+ " const low = options.lowWaterMark ?? options.lowWatermark ?? 1;\n"
4070
+ " checkWatermark(low, 'options.lowWaterMark');\n"
4071
+ " const events = queue(), pending = queue(), listeners = [];\n"
4072
+ " let paused = false, error = null, finished = false, abortListener;\n"
4073
+ " const close = () => {\n"
4074
+ " if (abortListener) abortListener[Symbol.dispose]();\n"
4075
+ " while (listeners.length) { const [event, handler] = listeners.pop(); remove(emitter, event, handler); }\n"
4076
+ " finished = true;\n"
4077
+ " paused = false;\n"
4078
+ " const result = { value: undefined, done: true };\n"
4079
+ " while (pending.size) pending.shift().resolve(result);\n"
4080
+ " return Promise.resolve(result);\n"
3749
4081
  " };\n"
3750
4082
  " const onError = (err) => {\n"
3751
- " emitter.removeListener(name, onEvent);\n"
3752
- " reject(err);\n"
4083
+ " if (pending.size) pending.shift().reject(err);\n"
4084
+ " else error = err;\n"
4085
+ " close();\n"
3753
4086
  " };\n"
3754
- " emitter.once(name, onEvent);\n"
3755
- " if (name !== 'error') emitter.once('error', onError);\n"
3756
- " });\n"
4087
+ " const onEvent = (...args) => {\n"
4088
+ " if (pending.size) pending.shift().resolve({ value: args, done: false });\n"
4089
+ " else {\n"
4090
+ " if (!paused && events.size + 1 > high) { paused = true; emitter.pause(); }\n"
4091
+ " events.push(args);\n"
4092
+ " }\n"
4093
+ " };\n"
4094
+ " const iterator = Object.setPrototypeOf({\n"
4095
+ " next() {\n"
4096
+ " if (events.size) {\n"
4097
+ " const value = events.shift();\n"
4098
+ " if (paused && events.size < low) { emitter.resume(); paused = false; }\n"
4099
+ " return Promise.resolve({ value, done: false });\n"
4100
+ " }\n"
4101
+ " if (error) { const err = error; error = null; return Promise.reject(err); }\n"
4102
+ " if (finished) return close();\n"
4103
+ " return new Promise((resolve, reject) => pending.push({ resolve, reject }));\n"
4104
+ " },\n"
4105
+ " return() { return close(); },\n"
4106
+ " throw(err) {\n"
4107
+ " if (!(err instanceof Error)) envArgumentError('EventEmitter.AsyncIterator', 'an instance of Error', err);\n"
4108
+ " onError(err);\n"
4109
+ " },\n"
4110
+ " [Symbol.asyncIterator]() { return this; },\n"
4111
+ " }, iteratorPrototype);\n"
4112
+ " const listen = (event, handler) => { add(emitter, event, handler); listeners.push([event, handler]); };\n"
4113
+ " listen(name, onEvent);\n"
4114
+ " if (name !== 'error' && typeof emitter.on === 'function') listen('error', onError);\n"
4115
+ " const closeEvents = options.close;\n"
4116
+ " if (closeEvents && closeEvents.length) { for (let i = 0; i < closeEvents.length; i++) listen(closeEvents[i], close); }\n"
4117
+ " if (signal) abortListener = EventEmitter.addAbortListener(signal, () => onError(abortError(signal)));\n"
4118
+ " return iterator;\n"
4119
+ " };\n"
3757
4120
  " EventEmitter.EventEmitter = EventEmitter;\n"
3758
4121
  " EventEmitter.default = EventEmitter;\n"
3759
4122
  " return EventEmitter;\n"
@@ -3987,13 +4350,19 @@ static const char isl_modules_bootstrap[] =
3987
4350
  "function makeFs(env) {\n"
3988
4351
  " const Buffer = env.Buffer;\n"
3989
4352
  " const constants = env.fsConstants();\n"
3990
- " const call = env.fs;\n"
4353
+ " const call = (op, ...args) => {\n"
4354
+ " try { return env.fs(op, ...args); } catch (e) {\n"
4355
+ " if (e.code && !e.code.startsWith('ERR_') && e.code !== 'SC2020') {\n"
4356
+ " e.syscall = op === 'readv' ? 'read' : op === 'writev' ? 'write' : op;\n"
4357
+ " if (typeof args[0] === 'string') e.path = args[0];\n"
4358
+ " }\n"
4359
+ " throw e;\n"
4360
+ " }\n"
4361
+ " };\n"
3991
4362
  " const pathOf = (p) => {\n"
3992
4363
  " if (typeof p === \"string\") return p;\n"
3993
4364
  " if (p instanceof Uint8Array) return Buffer.from(p).toString(\"utf8\");\n"
3994
- " if (p !== null && typeof p === \"object\" && typeof p.href === \"string\" && p.href.startsWith(\"file://\")) {\n"
3995
- " return decodeURIComponent(p.href.slice(7));\n"
3996
- " }\n"
4365
+ " if (p instanceof env.URL) return env.fileURLToPath(p);\n"
3997
4366
  " const e = new TypeError('The \"path\" argument must be of type string or an instance of Buffer or URL. Received ' + (p === null ? \"null\" : typeof p === \"object\" ? \"an instance of \" + ((p.constructor && p.constructor.name) || \"Object\") : \"type \" + typeof p + \" (\" + JSON.stringify(p) + \")\"));\n"
3998
4367
  " e.code = \"ERR_INVALID_ARG_TYPE\";\n"
3999
4368
  " throw e;\n"
@@ -4049,16 +4418,16 @@ static const char isl_modules_bootstrap[] =
4049
4418
  " isBlockDevice() { return this._kind === 7; }\n"
4050
4419
  " }\n"
4051
4420
  " const readFileSync = (p, options) => {\n"
4052
- " const u8 = call(\"readFile\", pathOf(p));\n"
4421
+ " const u8 = call(\"readFile\", typeof p === \"number\" ? fdOf(p) : pathOf(p));\n"
4053
4422
  " const enc = encodingOf(options, null);\n"
4054
4423
  " const buf = Buffer.from(u8.buffer, u8.byteOffset, u8.length);\n"
4055
4424
  " return enc === null ? buf : buf.toString(enc);\n"
4056
4425
  " };\n"
4057
4426
  " const writeFileSync = (p, data, options) => {\n"
4058
- " call(\"writeFile\", pathOf(p), dataToU8(data, options));\n"
4427
+ " call(\"writeFile\", typeof p === \"number\" ? fdOf(p) : pathOf(p), dataToU8(data, options));\n"
4059
4428
  " };\n"
4060
4429
  " const appendFileSync = (p, data, options) => {\n"
4061
- " call(\"appendFile\", pathOf(p), dataToU8(data, options));\n"
4430
+ " call(\"appendFile\", typeof p === \"number\" ? fdOf(p) : pathOf(p), dataToU8(data, options));\n"
4062
4431
  " };\n"
4063
4432
  " const existsSync = (p) => {\n"
4064
4433
  " try {\n"
@@ -4112,11 +4481,209 @@ static const char isl_modules_bootstrap[] =
4112
4481
  " const readlinkSync = (p) => call(\"readlink\", pathOf(p));\n"
4113
4482
  " const copyFileSync = (src, dest) => call(\"copyFile\", pathOf(src), pathOf(dest));\n"
4114
4483
  " const renameSync = (src, dest) => call(\"rename\", pathOf(src), pathOf(dest));\n"
4484
+ " // Descriptor callbacks validate before scheduling; only system I/O failures\n"
4485
+ " // travel through the callback. Payloads always retain the caller's identity.\n"
4486
+ " const received = (v) => v === undefined ? 'undefined' : v === null ? 'null' : typeof v === 'string' ? 'type string (' + JSON.stringify(v) + ')' : typeof v === 'object' ? 'an instance of ' + ((v.constructor && v.constructor.name) || 'Object') : 'type ' + typeof v + ' (' + String(v) + ')';\n"
4487
+ " const failType = (name, expected, v) => { const e = new TypeError('The \"' + name + '\" argument must be ' + expected + '. Received ' + received(v)); e.code = 'ERR_INVALID_ARG_TYPE'; throw e; };\n"
4488
+ " const failRange = (name, range, v) => { const e = new RangeError('The value of \"' + name + '\" is out of range. It must be ' + range + '. Received ' + String(v)); e.code = 'ERR_OUT_OF_RANGE'; throw e; };\n"
4489
+ " const integer = (v, name, min = -9007199254740991, max = 9007199254740991) => {\n"
4490
+ " if (typeof v !== 'number') failType(name, 'of type number', v);\n"
4491
+ " if (!Number.isInteger(v)) failRange(name, 'an integer', v);\n"
4492
+ " if (v < min || v > max) failRange(name, '>= ' + min + ' && <= ' + max, v);\n"
4493
+ " return v;\n"
4494
+ " };\n"
4495
+ " const fdOf = (fd) => integer(fd, 'fd', 0, 2147483647);\n"
4496
+ " const cbOf = (cb) => { if (typeof cb !== 'function') failType('cb', 'of type function', cb); return cb; };\n"
4497
+ " const optionsOf = (o) => { if (o != null && (typeof o !== 'object' || Array.isArray(o))) failType('options', 'of type object', o); return o || {}; };\n"
4498
+ " const viewOf = (v) => { if (!ArrayBuffer.isView(v)) failType('buffer', 'an instance of Buffer, TypedArray, or DataView', v); return new Uint8Array(v.buffer, v.byteOffset, v.byteLength); };\n"
4499
+ " const modeOf = (m, dflt = 0o666) => { if (m === undefined) return dflt; if (typeof m === 'string') { if (!/^[0-7]+$/.test(m)) { const e = new TypeError(\"The argument 'mode' must be a 32-bit unsigned integer or an octal string. Received '\" + m + \"'\"); e.code = 'ERR_INVALID_ARG_VALUE'; throw e; } m = parseInt(m, 8); } return integer(m, 'mode', 0, 4294967295); };\n"
4500
+ " const flagsOf = (f) => {\n"
4501
+ " if (f === undefined) f = 'r';\n"
4502
+ " if (typeof f === 'number') return integer(f, 'flags', -2147483648, 2147483647);\n"
4503
+ " if (typeof f !== 'string') failType('flags', 'of type string or number', f);\n"
4504
+ " const c = constants, sync = c.O_SYNC || 0;\n"
4505
+ " const flags = { r: c.O_RDONLY, rs: c.O_RDONLY | sync, sr: c.O_RDONLY | sync, 'r+': c.O_RDWR, 'rs+': c.O_RDWR | sync, 'sr+': c.O_RDWR | sync,\n"
4506
+ " w: c.O_WRONLY | c.O_CREAT | c.O_TRUNC, wx: c.O_WRONLY | c.O_CREAT | c.O_TRUNC | c.O_EXCL, xw: c.O_WRONLY | c.O_CREAT | c.O_TRUNC | c.O_EXCL,\n"
4507
+ " 'w+': c.O_RDWR | c.O_CREAT | c.O_TRUNC, 'wx+': c.O_RDWR | c.O_CREAT | c.O_TRUNC | c.O_EXCL, 'xw+': c.O_RDWR | c.O_CREAT | c.O_TRUNC | c.O_EXCL,\n"
4508
+ " a: c.O_WRONLY | c.O_CREAT | c.O_APPEND, ax: c.O_WRONLY | c.O_CREAT | c.O_APPEND | c.O_EXCL, xa: c.O_WRONLY | c.O_CREAT | c.O_APPEND | c.O_EXCL,\n"
4509
+ " as: c.O_WRONLY | c.O_CREAT | c.O_APPEND | sync, sa: c.O_WRONLY | c.O_CREAT | c.O_APPEND | sync,\n"
4510
+ " 'a+': c.O_RDWR | c.O_CREAT | c.O_APPEND, 'ax+': c.O_RDWR | c.O_CREAT | c.O_APPEND | c.O_EXCL, 'xa+': c.O_RDWR | c.O_CREAT | c.O_APPEND | c.O_EXCL,\n"
4511
+ " 'as+': c.O_RDWR | c.O_CREAT | c.O_APPEND | sync, 'sa+': c.O_RDWR | c.O_CREAT | c.O_APPEND | sync };\n"
4512
+ " if (Object.prototype.hasOwnProperty.call(flags, f)) return flags[f];\n"
4513
+ " const e = new TypeError(\"The argument 'flags' is invalid. Received '\" + f + \"'\"); e.code = 'ERR_INVALID_ARG_VALUE'; throw e;\n"
4514
+ " };\n"
4515
+ " const openArgs = (p, flags, mode) => {\n"
4516
+ " const path = pathOf(p);\n"
4517
+ " if (path.includes('\\0')) { const e = new TypeError(\"The argument 'path' must be a string, Uint8Array, or URL without null bytes. Received \" + JSON.stringify(path)); e.code = 'ERR_INVALID_ARG_VALUE'; throw e; }\n"
4518
+ " return [path, flagsOf(flags), modeOf(mode)];\n"
4519
+ " };\n"
4520
+ " const openSync = (p, flags, mode) => call('open', ...openArgs(p, flags, mode));\n"
4521
+ " const closeSync = (fd) => call('close', fdOf(fd));\n"
4522
+ " const fsyncSync = (fd) => call('fsync', fdOf(fd));\n"
4523
+ " const fdatasyncSync = (fd) => call('fdatasync', fdOf(fd));\n"
4524
+ " const ftruncateSync = (fd, len = 0) => { fdOf(fd); integer(len, 'len'); return call('ftruncate', fd, Math.max(0, len)); };\n"
4525
+ " const fchmodSync = (fd, mode) => { fdOf(fd); if (mode === undefined) failType('mode', 'of type number', mode); return call('fchmod', fd, modeOf(mode)); };\n"
4526
+ " const fstatSync = (fd, options) => {\n"
4527
+ " fdOf(fd);\n"
4528
+ " if (options && options.bigint) { const e = new Error('fs.fstat with bigint Stats is not supported in the scriptc island'); e.code = 'SC2020'; throw e; }\n"
4529
+ " return new Stats(call('fstat', fd));\n"
4530
+ " };\n"
4531
+ " const readWindow = (buffer, offset, length, position, nullOffset, coerceLength = true) => {\n"
4532
+ " const bytes = viewOf(buffer);\n"
4533
+ " offset = offset === undefined || (nullOffset && offset === null) ? 0 : integer(offset, 'offset', 0);\n"
4534
+ " if (coerceLength) length |= 0;\n"
4535
+ " if (length === 0) return [bytes, offset, 0, -1];\n"
4536
+ " if (bytes.length === 0) { const e = new TypeError(\"The argument 'buffer' is empty and cannot be written. Received \" + (Buffer.isBuffer(buffer) ? '<Buffer >' : String(buffer))); e.code = 'ERR_INVALID_ARG_VALUE'; throw e; }\n"
4537
+ " if (offset > bytes.length) failRange('offset', '>= 0 && <= 9007199254740991', offset);\n"
4538
+ " if (length < 0 || offset + length > bytes.length) failRange('length', '<= ' + (bytes.length - offset), length);\n"
4539
+ " if (position == null) position = -1;\n"
4540
+ " else if (typeof position === 'bigint') {\n"
4541
+ " if (position < -1n || position > 9007199254740991n) { const e = new Error('fs.read positions outside the safe integer range are not supported in the scriptc island'); e.code = 'SC2020'; throw e; }\n"
4542
+ " position = Number(position);\n"
4543
+ " } else integer(position, 'position', -1);\n"
4544
+ " return [bytes, offset, length, position];\n"
4545
+ " };\n"
4546
+ " const readSync = function(fd, buffer, offset, length, position) {\n"
4547
+ " viewOf(buffer);\n"
4548
+ " if (arguments.length <= 3 || typeof offset === 'object') {\n"
4549
+ " ({ offset = 0, length = buffer.byteLength - offset, position = null } = optionsOf(offset));\n"
4550
+ " }\n"
4551
+ " const a = readWindow(buffer, offset, length, position, false);\n"
4552
+ " if (a[2] === 0) return 0;\n"
4553
+ " return call('read', fdOf(fd), ...a);\n"
4554
+ " };\n"
4555
+ " const writeWindow = (buffer, offset, length, position) => {\n"
4556
+ " const bytes = viewOf(buffer);\n"
4557
+ " offset = offset == null || typeof offset === 'function' ? 0 : integer(offset, 'offset', 0);\n"
4558
+ " if (typeof length !== 'number') length = bytes.length - offset;\n"
4559
+ " if (offset > bytes.length) failRange('offset', '<= ' + bytes.length, offset);\n"
4560
+ " if (length < 0) failRange('length', '>= 0', length);\n"
4561
+ " if (length > bytes.length - offset) failRange('length', '<= ' + (bytes.length - offset), length);\n"
4562
+ " integer(length, 'length', 0);\n"
4563
+ " position = typeof position === 'number' ? position : -1;\n"
4564
+ " return [bytes, offset, length, position];\n"
4565
+ " };\n"
4566
+ " const stringBytes = (buffer, encoding) => {\n"
4567
+ " if (typeof buffer !== 'string') failType('buffer', 'of type string or an instance of Buffer, TypedArray, or DataView', buffer);\n"
4568
+ " if (encoding && !Buffer.isEncoding(encoding)) { const e = new TypeError('Unknown encoding: ' + encoding); e.code = 'ERR_UNKNOWN_ENCODING'; throw e; }\n"
4569
+ " return Buffer.from(buffer, encoding || 'utf8');\n"
4570
+ " };\n"
4571
+ " const writeSync = (fd, buffer, offset, length, position) => {\n"
4572
+ " let a;\n"
4573
+ " if (ArrayBuffer.isView(buffer)) {\n"
4574
+ " if (typeof offset === 'object') { const o = optionsOf(offset); offset = o.offset; length = o.length; position = o.position; }\n"
4575
+ " a = writeWindow(buffer, offset, length, position);\n"
4576
+ " } else { const bytes = stringBytes(buffer, length); a = [bytes, 0, bytes.length, typeof offset === 'number' ? offset : -1]; }\n"
4577
+ " return call('write', fdOf(fd), ...a);\n"
4578
+ " };\n"
4579
+ " const vectorArgs = (buffers, position) => {\n"
4580
+ " if (!Array.isArray(buffers)) failType('buffers', 'an instance of Array', buffers);\n"
4581
+ " const views = buffers.map((b) => viewOf(b));\n"
4582
+ " position = typeof position === 'number' && Number.isFinite(position) && position >= 0 ? Math.trunc(position) : -1;\n"
4583
+ " return [views, position];\n"
4584
+ " };\n"
4585
+ " const vectorIO = (writing, fd, buffers, views, position) => {\n"
4586
+ " if (writing && buffers.length === 0) return 0;\n"
4587
+ " fdOf(fd);\n"
4588
+ " const length = views.reduce((n, b) => n + b.length, 0);\n"
4589
+ " const bytes = writing ? Buffer.concat(views) : Buffer.alloc(length);\n"
4590
+ " const n = call(writing ? 'writev' : 'readv', fd, bytes, 0, length, position, buffers.length === 0);\n"
4591
+ " if (!writing) { let at = 0; for (const b of views) { const size = Math.min(b.length, n - at); if (size > 0) b.set(bytes.subarray(at, at + size)); at += b.length; } }\n"
4592
+ " return n;\n"
4593
+ " };\n"
4594
+ " const readvSync = (fd, buffers, position) => { const [views, pos] = vectorArgs(buffers, position); return vectorIO(false, fd, buffers, views, pos); };\n"
4595
+ " const writevSync = (fd, buffers, position) => { const [views, pos] = vectorArgs(buffers, position); return vectorIO(true, fd, buffers, views, pos); };\n"
4596
+ " const callbackIO = (cb, action, payload) => {\n"
4597
+ " let result, error = null;\n"
4598
+ " try { result = action(); } catch (e) { error = e; }\n"
4599
+ " env.nextTick(() => payload === undefined ? cb(error, result) : cb(error, result || 0, payload));\n"
4600
+ " };\n"
4601
+ " const open = function(p, flags, mode, cb) {\n"
4602
+ " if (arguments.length < 3) { cb = flags; flags = 'r'; mode = 0o666; }\n"
4603
+ " else if (typeof mode === 'function') { cb = mode; mode = 0o666; }\n"
4604
+ " const a = openArgs(p, flags, mode); cbOf(cb); callbackIO(cb, () => call('open', ...a));\n"
4605
+ " };\n"
4606
+ " const read = function(fd, buffer, offset, length, position, cb) {\n"
4607
+ " fdOf(fd);\n"
4608
+ " if (arguments.length <= 4) {\n"
4609
+ " let o;\n"
4610
+ " if (arguments.length === 4) { o = optionsOf(offset); cb = length; }\n"
4611
+ " else if (arguments.length === 3) { cb = offset; if (!ArrayBuffer.isView(buffer)) { o = optionsOf(buffer); ({ buffer = Buffer.alloc(16384) } = o); } }\n"
4612
+ " else { cb = buffer; buffer = Buffer.alloc(16384); }\n"
4613
+ " ({ offset = 0, length = buffer.byteLength - offset, position = null } = o || {});\n"
4614
+ " }\n"
4615
+ " viewOf(buffer); cbOf(cb);\n"
4616
+ " const a = readWindow(buffer, offset, length, position, true);\n"
4617
+ " callbackIO(cb, () => a[2] === 0 ? 0 : call('read', fd, ...a), buffer);\n"
4618
+ " };\n"
4619
+ " const write = function(fd, buffer, offset, length, position, cb) {\n"
4620
+ " fdOf(fd); let a;\n"
4621
+ " if (ArrayBuffer.isView(buffer)) {\n"
4622
+ " cb = cb || position || length || offset; cbOf(cb);\n"
4623
+ " if (typeof offset === 'object') { const o = optionsOf(offset); offset = o.offset; length = o.length; position = o.position; }\n"
4624
+ " a = writeWindow(buffer, offset, length, position);\n"
4625
+ " } else {\n"
4626
+ " if (typeof position !== 'function') { if (typeof offset === 'function') { position = offset; offset = null; } else position = length; length = 'utf8'; }\n"
4627
+ " const bytes = stringBytes(buffer, length); cb = position; cbOf(cb); a = [bytes, 0, bytes.length, typeof offset === 'number' ? offset : -1];\n"
4628
+ " }\n"
4629
+ " callbackIO(cb, () => call('write', fd, ...a), buffer);\n"
4630
+ " };\n"
4631
+ " const vectorCallback = (writing) => (fd, buffers, position, cb) => {\n"
4632
+ " fdOf(fd); const [views, pos] = vectorArgs(buffers, position); cb = cb || position; cbOf(cb);\n"
4633
+ " callbackIO(cb, () => vectorIO(writing, fd, buffers, views, pos), buffers);\n"
4634
+ " };\n"
4635
+ " const controlCallback = (op, normalize) => (...args) => {\n"
4636
+ " const cb = args.pop(); fdOf(args[0]); normalize(args); cbOf(cb);\n"
4637
+ " callbackIO(cb, () => call(op, ...args));\n"
4638
+ " };\n"
4639
+ " const handleState = new WeakMap();\n"
4640
+ " class FileHandle extends env.EventEmitter {\n"
4641
+ " constructor(fd) { super(); handleState.set(this, { fd }); }\n"
4642
+ " get fd() { return handleState.get(this).fd; }\n"
4643
+ " close = () => {\n"
4644
+ " const state = handleState.get(this);\n"
4645
+ " if (state.fd === -1) return Promise.resolve();\n"
4646
+ " const fd = state.fd; state.fd = -1;\n"
4647
+ " const result = Promise.resolve().then(() => closeSync(fd));\n"
4648
+ " this.emit('close'); return result;\n"
4649
+ " };\n"
4650
+ " async [Symbol.asyncDispose || Symbol.for('nodejs.asyncDispose')]() { await this.close(); }\n"
4651
+ " async _call(op, action) {\n"
4652
+ " if (this.fd === -1) { const e = new Error('file closed'); e.code = 'EBADF'; e.syscall = op; throw e; }\n"
4653
+ " return action(this.fd);\n"
4654
+ " }\n"
4655
+ " read(buffer, offset, length, position) {\n"
4656
+ " return this._call('read', (fd) => {\n"
4657
+ " if (!ArrayBuffer.isView(buffer)) { ({ buffer = Buffer.alloc(16384), offset = 0, length = buffer.byteLength - offset, position = null } = optionsOf(buffer)); }\n"
4658
+ " if (offset !== null && typeof offset === 'object') { ({ offset = 0, length = buffer.byteLength - offset, position = null } = optionsOf(offset)); }\n"
4659
+ " if (offset == null) offset = 0;\n"
4660
+ " if (length == null) length = buffer.byteLength - offset;\n"
4661
+ " const a = readWindow(buffer, offset, length, position, true, false);\n"
4662
+ " return { __proto__: null, bytesRead: a[2] === 0 ? 0 : call('read', fd, ...a), buffer };\n"
4663
+ " });\n"
4664
+ " }\n"
4665
+ " write(buffer, offset, length, position) {\n"
4666
+ " return this._call('write', (fd) => {\n"
4667
+ " const bytesWritten = buffer && buffer.byteLength === 0 ? 0 : writeSync(fd, buffer, offset, length, position);\n"
4668
+ " return { __proto__: null, bytesWritten, buffer };\n"
4669
+ " });\n"
4670
+ " }\n"
4671
+ " readv(buffers, position) { return this._call('readv', (fd) => ({ __proto__: null, bytesRead: readvSync(fd, buffers, position), buffers })); }\n"
4672
+ " writev(buffers, position) { return this._call('writev', (fd) => ({ __proto__: null, bytesWritten: writevSync(fd, buffers, position), buffers })); }\n"
4673
+ " readFile(options) { return this._call('readFile', (fd) => readFileSync(fd, options)); }\n"
4674
+ " writeFile(data, options) { return this._call('writeFile', (fd) => writeFileSync(fd, data, options)); }\n"
4675
+ " appendFile(data, options) { return this._call('writeFile', (fd) => writeFileSync(fd, data, options)); }\n"
4676
+ " stat(options) { return this._call('fstat', (fd) => fstatSync(fd, options)); }\n"
4677
+ " sync() { return this._call('fsync', fsyncSync); }\n"
4678
+ " datasync() { return this._call('fdatasync', fdatasyncSync); }\n"
4679
+ " truncate(len = 0) { return this._call('ftruncate', (fd) => ftruncateSync(fd, len)); }\n"
4680
+ " chmod(mode) { return this._call('fchmod', (fd) => fchmodSync(fd, mode)); }\n"
4681
+ " }\n"
4115
4682
  " const sync = {\n"
4116
4683
  " readFileSync, writeFileSync, appendFileSync, existsSync, realpathSync,\n"
4117
4684
  " mkdirSync, rmSync, rmdirSync, unlinkSync, readdirSync, statSync,\n"
4118
4685
  " lstatSync, accessSync, mkdtempSync, chmodSync, copyFileSync, renameSync,\n"
4119
- " readlinkSync,\n"
4686
+ " readlinkSync, openSync, closeSync, readSync, writeSync, readvSync, writevSync, fstatSync, fchmodSync, ftruncateSync, fsyncSync, fdatasyncSync,\n"
4120
4687
  " };\n"
4121
4688
  " const callbackify = (syncFn) => (...args) => {\n"
4122
4689
  " const cb = args.pop();\n"
@@ -4213,22 +4780,13 @@ static const char isl_modules_bootstrap[] =
4213
4780
  " watchFile: () => {\n"
4214
4781
  " throw new Error(\"fs.watchFile is not available in the scriptc island\");\n"
4215
4782
  " },\n"
4216
- " openSync: () => {\n"
4217
- " throw new Error(\"fs.openSync is not available in the scriptc island (whole-file reads/writes only)\");\n"
4218
- " },\n"
4219
- " closeSync: () => undefined,\n"
4220
- " readSync: () => {\n"
4221
- " throw new Error(\"fs.readSync is not available in the scriptc island (whole-file reads/writes only)\");\n"
4222
- " },\n"
4223
- " writeSync: () => {\n"
4224
- " throw new Error(\"fs.writeSync is not available in the scriptc island (whole-file reads/writes only)\");\n"
4225
- " },\n"
4226
- " read: () => {\n"
4227
- " throw new Error(\"fs.read is not available in the scriptc island (whole-file reads/writes only)\");\n"
4228
- " },\n"
4229
- " open: () => {\n"
4230
- " throw new Error(\"fs.open is not available in the scriptc island (whole-file reads/writes only)\");\n"
4231
- " },\n"
4783
+ " open, read, write, readv: vectorCallback(false), writev: vectorCallback(true),\n"
4784
+ " close: controlCallback('close', () => {}),\n"
4785
+ " fsync: controlCallback('fsync', () => {}),\n"
4786
+ " fdatasync: controlCallback('fdatasync', () => {}),\n"
4787
+ " ftruncate: controlCallback('ftruncate', (a) => { a[1] = a[1] === undefined ? 0 : integer(a[1], 'len'); }),\n"
4788
+ " fchmod: controlCallback('fchmod', (a) => { if (a[1] === undefined) failType('mode', 'of type number', a[1]); a[1] = modeOf(a[1]); }),\n"
4789
+ " fstat: (fd, options, cb) => { fdOf(fd); if (typeof options === 'function') { cb = options; options = undefined; } cbOf(cb); callbackIO(cb, () => fstatSync(fd, options)); },\n"
4232
4790
  " unwatchFile: () => undefined,\n"
4233
4791
  " };\n"
4234
4792
  " fs.promises = {\n"
@@ -4250,13 +4808,11 @@ static const char isl_modules_bootstrap[] =
4250
4808
  " rename: promisify(renameSync),\n"
4251
4809
  " readlink: promisify(readlinkSync),\n"
4252
4810
  " constants,\n"
4253
- " open: () => {\n"
4254
- " return Promise.reject(new Error(\"fs.promises.open is not available in the scriptc island (whole-file reads/writes only)\"));\n"
4255
- " },\n"
4811
+ " open: async (p, flags, mode) => new FileHandle(openSync(p, flags, mode)),\n"
4256
4812
  " };\n"
4257
4813
  " return fs;\n"
4258
4814
  "}\n"
4259
- " const fs = makeFs({ fs: (...a) => host.fs(...a), fsConstants: () => host.fsConstants(), Buffer: builtins.buffer().Buffer, Readable: builtins.stream().Readable, Writable: builtins.stream().Writable, nextTick: (fn) => queueMicrotask(fn) });\n"
4815
+ " const fs = makeFs({ fs: (...a) => host.fs(...a), fsConstants: () => host.fsConstants(), Buffer: builtins.buffer().Buffer, Readable: builtins.stream().Readable, Writable: builtins.stream().Writable, EventEmitter: builtins.events().EventEmitter, URL: builtins.url().URL, fileURLToPath: builtins.url().fileURLToPath, nextTick: (fn) => queueMicrotask(fn) });\n"
4260
4816
  " fs.default = fs;\n"
4261
4817
  " return fs;\n"
4262
4818
  " });\n"
@@ -4510,7 +5066,7 @@ static const char isl_modules_bootstrap[] =
4510
5066
  " const K_STRING_MAX_LENGTH = 536870888;\n"
4511
5067
  " const INSPECT_MAX_BYTES = 50;\n"
4512
5068
  " const utf8Enc = new TextEncoder();\n"
4513
- " const utf8Dec = new TextDecoder();\n"
5069
+ " const utf8Dec = new TextDecoder(\"utf-8\", { ignoreBOM: true });\n"
4514
5070
  " const B64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n"
4515
5071
  " const B64U = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n"
4516
5072
  " const b64Val = (() => {\n"
@@ -4548,7 +5104,7 @@ static const char isl_modules_bootstrap[] =
4548
5104
  " return e;\n"
4549
5105
  " };\n"
4550
5106
  " const invalidArg = (name, expected, actual) => {\n"
4551
- " const t = actual === null ? \"null\" : typeof actual === \"object\" ? \"an instance of \" + (actual.constructor && actual.constructor.name || \"Object\") : typeof actual === \"string\" ? \"type string ('\" + actual + \"')\" : \"type \" + typeof actual + \" (\" + String(actual) + \")\";\n"
5107
+ " const t = actual == null ? String(actual) : typeof actual === \"object\" ? \"an instance of \" + (actual.constructor && actual.constructor.name || \"Object\") : typeof actual === \"string\" ? \"type string ('\" + actual + \"')\" : \"type \" + typeof actual + \" (\" + String(actual) + (typeof actual === 'bigint' ? 'n' : '') + \")\";\n"
4552
5108
  " const label = name === \"first argument\" ? \"The first argument\" : 'The \"' + name + '\" argument';\n"
4553
5109
  " const e = new TypeError(label + \" must be \" + expected + \". Received \" + t);\n"
4554
5110
  " e.code = \"ERR_INVALID_ARG_TYPE\";\n"
@@ -5210,15 +5766,20 @@ static const char isl_modules_bootstrap[] =
5210
5766
  " return -1;\n"
5211
5767
  " };\n"
5212
5768
  " function SlowBuffer(size) { return Buffer.alloc(size); }\n"
5769
+ " const validationBytes = (input) => {\n"
5770
+ " if (ArrayBuffer.isView(input) && !(input instanceof DataView)) return new Uint8Array(input.buffer, input.byteOffset, input.byteLength);\n"
5771
+ " if (input instanceof ArrayBuffer || (typeof SharedArrayBuffer === 'function' && input instanceof SharedArrayBuffer)) return new Uint8Array(input);\n"
5772
+ " throw invalidArg('input', 'an instance of ArrayBuffer, Buffer, or TypedArray', input);\n"
5773
+ " };\n"
5213
5774
  " const isAscii = (input) => {\n"
5214
- " const u8 = input instanceof Uint8Array ? input : new Uint8Array(input);\n"
5775
+ " const u8 = validationBytes(input);\n"
5215
5776
  " for (let i = 0; i < u8.length; i++) {\n"
5216
5777
  " if (u8[i] > 0x7f) return false;\n"
5217
5778
  " }\n"
5218
5779
  " return true;\n"
5219
5780
  " };\n"
5220
5781
  " const isUtf8 = (input) => {\n"
5221
- " const u8 = input instanceof Uint8Array ? input : new Uint8Array(input);\n"
5782
+ " const u8 = validationBytes(input);\n"
5222
5783
  " let i = 0;\n"
5223
5784
  " while (i < u8.length) {\n"
5224
5785
  " const b = u8[i];\n"
@@ -5256,8 +5817,9 @@ static const char isl_modules_bootstrap[] =
5256
5817
  * (scr_web.c) owns the implementations. */
5257
5818
  " Blob: globalThis.Blob,\n"
5258
5819
  " File: globalThis.File,\n"
5259
- " transcode: () => {\n"
5260
- " throw new Error(\"buffer.transcode is not available in the scriptc island\");\n"
5820
+ " transcode: (source, from, to) => {\n"
5821
+ " if (!(source instanceof Uint8Array)) throw invalidArg('source', 'an instance of Buffer or Uint8Array', source);\n"
5822
+ " return Buffer.from(host.transcode(source, from, to));\n"
5261
5823
  " },\n"
5262
5824
  " resolveObjectURL: () => undefined,\n"
5263
5825
  " };\n"
@@ -5266,97 +5828,89 @@ static const char isl_modules_bootstrap[] =
5266
5828
  " mod.default = mod;\n"
5267
5829
  " return mod;\n"
5268
5830
  " });\n"
5269
- /* node:string_decoder — StringDecoder over the Buffer shim: utf8
5270
- * rides the prelude TextDecoder's streaming state machine,
5271
- * utf16le holds byte parity, base64 carries mod-3 remainders. */
5831
+ /* node:string_decoder — preserve Node's byte buffering independently
5832
+ * of WHATWG TextDecoder: BOMs, invalid prefixes, UTF-16 pairs, and
5833
+ * base64 groups retain their chunk-boundary behavior. */
5272
5834
  " builtins.string_decoder = memo(() => {\n"
5273
5835
  "function makeStringDecoder(Buffer) {\n"
5274
5836
  " const normEnc = (enc) => {\n"
5275
- " if (enc === undefined || enc === null) return \"utf8\";\n"
5276
- " const e = String(enc).toLowerCase();\n"
5277
- " if (e === \"utf8\" || e === \"utf-8\") return \"utf8\";\n"
5278
- " if (e === \"hex\") return \"hex\";\n"
5279
- " if (e === \"base64\") return \"base64\";\n"
5280
- " if (e === \"base64url\") return \"base64url\";\n"
5281
- " if (e === \"latin1\" || e === \"binary\") return \"latin1\";\n"
5282
- " if (e === \"ascii\") return \"ascii\";\n"
5283
- " if (e === \"utf16le\" || e === \"utf-16le\" || e === \"ucs2\" || e === \"ucs-2\") return \"utf16le\";\n"
5284
- " const err = new TypeError(\"Unknown encoding: \" + enc);\n"
5285
- " err.code = \"ERR_UNKNOWN_ENCODING\";\n"
5837
+ " if (enc === undefined || enc === null || enc === '') return 'utf8';\n"
5838
+ " const e = typeof enc === 'string' ? enc.toLowerCase() : enc;\n"
5839
+ " if (e === 'utf8' || e === 'utf-8') return 'utf8';\n"
5840
+ " if (e === 'hex' || e === 'base64' || e === 'base64url' || e === 'ascii') return e;\n"
5841
+ " if (e === 'latin1' || e === 'binary') return 'latin1';\n"
5842
+ " if (e === 'utf16le' || e === 'utf-16le' || e === 'ucs2' || e === 'ucs-2') return 'utf16le';\n"
5843
+ " const err = new TypeError('Unknown encoding: ' + String(enc));\n"
5844
+ " err.code = 'ERR_UNKNOWN_ENCODING';\n"
5286
5845
  " throw err;\n"
5287
5846
  " };\n"
5288
5847
  " class StringDecoder {\n"
5289
5848
  " constructor(encoding) {\n"
5290
5849
  " this.encoding = normEnc(encoding);\n"
5291
- " if (this.encoding === \"utf8\") {\n"
5292
- " this._dec = new TextDecoder();\n"
5293
- " } else if (this.encoding === \"utf16le\") {\n"
5294
- " this._oddByte = -1;\n"
5295
- " } else if (this.encoding === \"base64\" || this.encoding === \"base64url\") {\n"
5296
- " this._rem = null;\n"
5297
- " }\n"
5850
+ " this._encoding = this.encoding;\n"
5851
+ " this._pending = new Uint8Array(0);\n"
5852
+ " this._missing = 0;\n"
5298
5853
  " }\n"
5299
5854
  " write(buf) {\n"
5300
- " if (typeof buf === \"string\") return buf;\n"
5301
- " const u8 = buf instanceof Uint8Array ? buf : new Uint8Array(buf);\n"
5302
- " switch (this.encoding) {\n"
5303
- " case \"utf8\":\n"
5304
- " return this._dec.decode(u8, { stream: true });\n"
5305
- " case \"utf16le\": {\n"
5306
- " let bytes = u8;\n"
5307
- " if (this._oddByte >= 0) {\n"
5308
- " const joined = new Uint8Array(u8.length + 1);\n"
5309
- " joined[0] = this._oddByte;\n"
5310
- " joined.set(u8, 1);\n"
5311
- " bytes = joined;\n"
5312
- " this._oddByte = -1;\n"
5313
- " }\n"
5314
- " if (bytes.length % 2 !== 0) {\n"
5315
- " this._oddByte = bytes[bytes.length - 1];\n"
5316
- " bytes = bytes.subarray(0, bytes.length - 1);\n"
5855
+ " if (typeof buf === 'string') return buf;\n"
5856
+ " if (!ArrayBuffer.isView(buf)) {\n"
5857
+ " const received = buf === null ? 'null' : buf === undefined ? 'undefined' : typeof buf === 'object' ? 'an instance of ' + (buf.constructor && buf.constructor.name || 'Object') : 'type ' + typeof buf + ' (' + String(buf) + ')';\n"
5858
+ " const err = new TypeError('The \"buf\" argument must be an instance of Buffer, TypedArray, or DataView. Received ' + received);\n"
5859
+ " err.code = 'ERR_INVALID_ARG_TYPE';\n"
5860
+ " throw err;\n"
5861
+ " }\n"
5862
+ " const bytes = new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);\n"
5863
+ " const enc = this._encoding;\n"
5864
+ " let offset = 0;\n"
5865
+ " let out = '';\n"
5866
+ " if (this._missing > 0) {\n"
5867
+ " let take = Math.min(bytes.length, this._missing);\n"
5868
+ " if (enc === 'utf8') {\n"
5869
+ " for (let i = 0; i < take; i++) {\n"
5870
+ " if ((bytes[i] & 0xc0) !== 0x80) { take = i; this._missing = i; break; }\n"
5317
5871
  " }\n"
5318
- " return Buffer.from(bytes).toString(\"utf16le\");\n"
5319
5872
  " }\n"
5320
- " case \"base64\":\n"
5321
- " case \"base64url\": {\n"
5322
- " let bytes = u8;\n"
5323
- " if (this._rem !== null) {\n"
5324
- " const joined = new Uint8Array(this._rem.length + u8.length);\n"
5325
- " joined.set(this._rem, 0);\n"
5326
- " joined.set(u8, this._rem.length);\n"
5327
- " bytes = joined;\n"
5328
- " this._rem = null;\n"
5329
- " }\n"
5330
- " const usable = bytes.length - (bytes.length % 3);\n"
5331
- " if (usable < bytes.length) {\n"
5332
- " this._rem = bytes.slice(usable);\n"
5333
- " bytes = bytes.subarray(0, usable);\n"
5334
- " }\n"
5335
- " return Buffer.from(bytes).toString(this.encoding);\n"
5873
+ " const pending = new Uint8Array(this._pending.length + take);\n"
5874
+ " pending.set(this._pending);\n"
5875
+ " pending.set(bytes.subarray(0, take), this._pending.length);\n"
5876
+ " this._pending = pending;\n"
5877
+ " this._missing -= take;\n"
5878
+ " offset = take;\n"
5879
+ " if (this._missing === 0) {\n"
5880
+ " out = Buffer.from(pending).toString(enc);\n"
5881
+ " this._pending = new Uint8Array(0);\n"
5336
5882
  " }\n"
5337
- " default:\n"
5338
- " return Buffer.from(u8).toString(this.encoding);\n"
5339
- " }\n"
5883
+ " if (offset === bytes.length) return out;\n"
5884
+ " }\n"
5885
+ " const n = bytes.length - offset;\n"
5886
+ " let held = 0;\n"
5887
+ " let total = 0;\n"
5888
+ " if (enc === 'utf8') {\n"
5889
+ " for (let back = 1; back <= Math.min(n, 3); back++) {\n"
5890
+ " const b = bytes[bytes.length - back];\n"
5891
+ " if ((b & 0xc0) === 0x80) continue;\n"
5892
+ " total = (b & 0xe0) === 0xc0 ? 2 : (b & 0xf0) === 0xe0 ? 3 : (b & 0xf8) === 0xf0 ? 4 : 0;\n"
5893
+ " if (back < total) held = back;\n"
5894
+ " break;\n"
5895
+ " }\n"
5896
+ " } else if (enc === 'utf16le') {\n"
5897
+ " if (n % 2) { held = 1; total = 2; }\n"
5898
+ " else if (n >= 2 && (bytes[bytes.length - 1] & 0xfc) === 0xd8) { held = 2; total = 4; }\n"
5899
+ " } else if (enc === 'base64' || enc === 'base64url') {\n"
5900
+ " held = n % 3;\n"
5901
+ " total = 3;\n"
5902
+ " }\n"
5903
+ " const end = bytes.length - held;\n"
5904
+ " this._pending = bytes.slice(end);\n"
5905
+ " this._missing = held ? total - held : 0;\n"
5906
+ " return out + Buffer.from(bytes.subarray(offset, end)).toString(enc);\n"
5340
5907
  " }\n"
5341
5908
  " end(buf) {\n"
5342
- " let out = buf !== undefined ? this.write(buf) : \"\";\n"
5343
- " switch (this.encoding) {\n"
5344
- " case \"utf8\":\n"
5345
- " out += this._dec.decode();\n"
5346
- " this._dec = new TextDecoder();\n"
5347
- " break;\n"
5348
- " case \"utf16le\":\n"
5349
- " this._oddByte = -1;\n"
5350
- " break;\n"
5351
- " case \"base64\":\n"
5352
- " case \"base64url\":\n"
5353
- " if (this._rem !== null) {\n"
5354
- " out += Buffer.from(this._rem).toString(this.encoding);\n"
5355
- " this._rem = null;\n"
5356
- " }\n"
5357
- " break;\n"
5358
- " }\n"
5359
- " return out;\n"
5909
+ " const out = buf === undefined ? '' : this.write(buf);\n"
5910
+ " const tail = Buffer.from(this._pending).toString(this._encoding);\n"
5911
+ " this._pending = new Uint8Array(0);\n"
5912
+ " this._missing = 0;\n"
5913
+ " return out + tail;\n"
5360
5914
  " }\n"
5361
5915
  " }\n"
5362
5916
  " return { StringDecoder };\n"
@@ -5366,7 +5920,7 @@ static const char isl_modules_bootstrap[] =
5366
5920
  " return mod;\n"
5367
5921
  " });\n"
5368
5922
  /* node:crypto — the hashing/random slice over host bridges
5369
- * (md5/sha1/sha256 digest + HMAC through the same C
5923
+ * (MD5/SHA-1/SHA-2 digest + HMAC through the same C
5370
5924
  * implementations the static lowerings use; randomness through
5371
5925
  * the web prelude's CSPRNG), pbkdf2 over the HMAC bridge, and
5372
5926
  * honest throwing stubs for the key/cipher machinery the island
@@ -5584,12 +6138,119 @@ static const char isl_modules_bootstrap[] =
5584
6138
  " }\n"
5585
6139
  " queueMicrotask(() => callback(null, derived));\n"
5586
6140
  " };\n"
6141
+ " const kdfError = (kind, code, message) => {\n"
6142
+ " const error = new kind(message);\n"
6143
+ " error.code = code;\n"
6144
+ " return error;\n"
6145
+ " };\n"
6146
+ " const kdfNumber = (value) => Number.isInteger(value) && Math.abs(value) > 4294967296 ? String(value).replace(/\\B(?=(\\d{3})+(?!\\d))/g, \"_\") : String(value);\n"
6147
+ " const kdfInteger = (value, name, max) => {\n"
6148
+ " if (typeof value !== \"number\") {\n"
6149
+ " const received = value === null ? \"null\" : value === undefined ? \"undefined\" : typeof value === \"object\" ? \"an instance of \" + ((value.constructor && value.constructor.name) || \"Object\") : \"type \" + typeof value + \" (\" + (typeof value === \"string\" ? \"'\" + value + \"'\" : String(value)) + \")\";\n"
6150
+ " throw kdfError(TypeError, \"ERR_INVALID_ARG_TYPE\", 'The \"' + name + '\" argument must be of type number. Received ' + received);\n"
6151
+ " }\n"
6152
+ " if (!Number.isInteger(value) || value < 0 || value > max) {\n"
6153
+ " const range = Number.isInteger(value) ? \">= 0 && <= \" + max : \"an integer\";\n"
6154
+ " throw kdfError(RangeError, \"ERR_OUT_OF_RANGE\", 'The value of \"' + name + '\" is out of range. It must be ' + range + '. Received ' + kdfNumber(value));\n"
6155
+ " }\n"
6156
+ " return value;\n"
6157
+ " };\n"
6158
+ " const kdfInput = (value, name, hkdfKey = false, hkdfSource = false) => {\n"
6159
+ " if (typeof value === \"string\") return Buffer.from(value);\n"
6160
+ " if (value instanceof ArrayBuffer) return new Uint8Array(value);\n"
6161
+ " if (ArrayBuffer.isView(value)) return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);\n"
6162
+ " const received = value === null ? \"null\" : value === undefined ? \"undefined\" : typeof value === \"object\" ? \"an instance of \" + ((value.constructor && value.constructor.name) || \"Object\") : \"type \" + typeof value + \" (\" + (typeof value === \"string\" ? \"'\" + value + \"'\" : String(value)) + \")\";\n"
6163
+ " const expected = hkdfKey ? \"string or an instance of SecretKeyObject, ArrayBuffer, TypedArray, DataView, or Buffer\" : hkdfSource ? \"string or an instance of ArrayBuffer, TypedArray, DataView, or Buffer\" : \"string or an instance of ArrayBuffer, Buffer, TypedArray, or DataView\";\n"
6164
+ " throw kdfError(TypeError, \"ERR_INVALID_ARG_TYPE\", 'The \"' + name + '\" argument must be of type ' + expected + '. Received ' + received);\n"
6165
+ " };\n"
6166
+ " const kdfCallback = (callback) => {\n"
6167
+ " if (typeof callback !== \"function\") {\n"
6168
+ " const received = callback === undefined ? \"undefined\" : callback === null ? \"null\" : typeof callback === \"object\" ? \"an instance of \" + ((callback.constructor && callback.constructor.name) || \"Object\") : \"type \" + typeof callback + \" (\" + String(callback) + \")\";\n"
6169
+ " throw kdfError(TypeError, \"ERR_INVALID_ARG_TYPE\", 'The \"callback\" argument must be of type function. Received ' + received);\n"
6170
+ " }\n"
6171
+ " };\n"
6172
+ " const hkdfParameters = (digest, ikm, salt, info, keylen) => {\n"
6173
+ " if (typeof digest !== \"string\") {\n"
6174
+ " const received = digest === undefined ? \"undefined\" : digest === null ? \"null\" : \"type \" + typeof digest + \" (\" + String(digest) + \")\";\n"
6175
+ " throw kdfError(TypeError, \"ERR_INVALID_ARG_TYPE\", 'The \"digest\" argument must be of type string. Received ' + received);\n"
6176
+ " }\n"
6177
+ " ikm = kdfInput(ikm, \"ikm\", true);\n"
6178
+ " salt = kdfInput(salt, \"salt\", false, true);\n"
6179
+ " info = kdfInput(info, \"info\", false, true);\n"
6180
+ " kdfInteger(keylen, \"length\", Number.MAX_SAFE_INTEGER);\n"
6181
+ " if (info.length > 1024) throw kdfError(RangeError, \"ERR_OUT_OF_RANGE\", 'The value of \"info\" is out of range. It must be must not contain more than 1024 bytes. Received ' + info.length);\n"
6182
+ " return [digest, ikm, salt, info, keylen];\n"
6183
+ " };\n"
6184
+ " const hkdfDerive = (digest, ikm, salt, info, keylen) => {\n"
6185
+ " const prk = env.hmac(digest.toLowerCase(), salt, ikm);\n"
6186
+ " if (prk === undefined) throw kdfError(TypeError, \"ERR_CRYPTO_INVALID_DIGEST\", \"Invalid digest: \" + digest);\n"
6187
+ " if (keylen > 255 * prk.length) {\n"
6188
+ " prk.fill(0);\n"
6189
+ " throw kdfError(RangeError, \"ERR_CRYPTO_INVALID_KEYLEN\", \"Invalid key length\");\n"
6190
+ " }\n"
6191
+ " const result = new Uint8Array(keylen);\n"
6192
+ " let previous = new Uint8Array(0), offset = 0;\n"
6193
+ " for (let counter = 1; offset < keylen; counter++) {\n"
6194
+ " const block = new Uint8Array(previous.length + info.length + 1);\n"
6195
+ " block.set(previous);\n"
6196
+ " block.set(info, previous.length);\n"
6197
+ " block[block.length - 1] = counter;\n"
6198
+ " const next = env.hmac(digest.toLowerCase(), prk, block);\n"
6199
+ " previous.fill(0);\n"
6200
+ " block.fill(0);\n"
6201
+ " previous = next;\n"
6202
+ " const take = Math.min(next.length, keylen - offset);\n"
6203
+ " result.set(next.subarray(0, take), offset);\n"
6204
+ " offset += take;\n"
6205
+ " }\n"
6206
+ " prk.fill(0);\n"
6207
+ " previous.fill(0);\n"
6208
+ " return result.buffer;\n"
6209
+ " };\n"
6210
+ " const hkdfSync = (digest, ikm, salt, info, keylen) => {\n"
6211
+ " const result = hkdfDerive(...hkdfParameters(digest, ikm, salt, info, keylen));\n"
6212
+ " if (result.byteLength === 0) throw new Error(\"Deriving bits failed\");\n"
6213
+ " return result;\n"
6214
+ " };\n"
6215
+ " const hkdf = (digest, ikm, salt, info, keylen, callback) => {\n"
6216
+ " const params = hkdfParameters(digest, ikm, salt, info, keylen);\n"
6217
+ " kdfCallback(callback);\n"
6218
+ " const result = hkdfDerive(...params);\n"
6219
+ " setImmediate(() => result.byteLength === 0 ? callback(new Error(\"Deriving bits failed\")) : callback(null, result));\n"
6220
+ " };\n"
6221
+ " const scryptParameters = (password, salt, keylen, options) => {\n"
6222
+ " password = kdfInput(password, \"password\");\n"
6223
+ " salt = kdfInput(salt, \"salt\");\n"
6224
+ " kdfInteger(keylen, \"keylen\", 2147483647);\n"
6225
+ " const values = [16384, 8, 1, 33554432];\n"
6226
+ " if (options) {\n"
6227
+ " const names = [\"N\", \"r\", \"p\"], aliases = [\"cost\", \"blockSize\", \"parallelization\"];\n"
6228
+ " for (let i = 0; i < 3; i++) {\n"
6229
+ " const name = names[i], alias = aliases[i], present = options[name] !== undefined;\n"
6230
+ " if (present) values[i] = kdfInteger(options[name], name, 4294967295);\n"
6231
+ " if (options[alias] !== undefined) {\n"
6232
+ " if (present) throw kdfError(TypeError, \"ERR_INCOMPATIBLE_OPTION_PAIR\", 'Option \"' + name + '\" cannot be used in combination with option \"' + alias + '\"');\n"
6233
+ " values[i] = kdfInteger(options[alias], alias, 4294967295);\n"
6234
+ " }\n"
6235
+ " }\n"
6236
+ " if (options.maxmem !== undefined) values[3] = kdfInteger(options.maxmem, \"maxmem\", Number.MAX_SAFE_INTEGER);\n"
6237
+ " }\n"
6238
+ " return [password, salt, keylen, ...values];\n"
6239
+ " };\n"
6240
+ " const scryptSync = (password, salt, keylen, options) => Buffer.from(env.scrypt(...scryptParameters(password, salt, keylen, options)));\n"
6241
+ " const scrypt = (password, salt, keylen, options, callback) => {\n"
6242
+ " if (callback === undefined) { callback = options; options = undefined; }\n"
6243
+ " const params = scryptParameters(password, salt, keylen, options);\n"
6244
+ " kdfCallback(callback);\n"
6245
+ " const result = Buffer.from(env.scrypt(...params));\n"
6246
+ " setImmediate(() => callback(null, result));\n"
6247
+ " };\n"
5587
6248
  " const die = (name) => function unsupported() {\n"
5588
- " throw new Error(\"crypto.\" + name + \" is not available in the scriptc island (the embedded runtime carries the hashing/random slice only)\");\n"
6249
+ " throw new Error(\"crypto.\" + name + \" is not available in the scriptc island (the embedded runtime carries the hashing/random/KDF slice only)\");\n"
5589
6250
  " };\n"
5590
6251
  " class KeyObject {\n"
5591
6252
  " constructor() {\n"
5592
- " throw new Error(\"crypto.KeyObject is not available in the scriptc island (the embedded runtime carries the hashing/random slice only)\");\n"
6253
+ " throw new Error(\"crypto.KeyObject is not available in the scriptc island (the embedded runtime carries the hashing/random/KDF slice only)\");\n"
5593
6254
  " }\n"
5594
6255
  " }\n"
5595
6256
  " const constants = {\n"
@@ -5607,8 +6268,8 @@ static const char isl_modules_bootstrap[] =
5607
6268
  " createHash, createHmac, hash, Hash, Hmac,\n"
5608
6269
  " randomBytes, randomFillSync, randomFill, randomInt, randomUUID,\n"
5609
6270
  " getRandomValues: (ta) => webcrypto.getRandomValues(ta),\n"
5610
- " timingSafeEqual, pbkdf2, pbkdf2Sync,\n"
5611
- " getHashes: () => [\"md5\", \"sha1\", \"sha256\"],\n"
6271
+ " timingSafeEqual, pbkdf2, pbkdf2Sync, hkdf, hkdfSync, scrypt, scryptSync,\n"
6272
+ " getHashes: () => [\"md5\", \"sha1\", \"sha224\", \"sha256\", \"sha384\", \"sha512\"],\n"
5612
6273
  " getCiphers: () => [],\n"
5613
6274
  " getCurves: () => [],\n"
5614
6275
  " webcrypto,\n"
@@ -5634,10 +6295,6 @@ static const char isl_modules_bootstrap[] =
5634
6295
  " publicDecrypt: die(\"publicDecrypt\"),\n"
5635
6296
  " privateEncrypt: die(\"privateEncrypt\"),\n"
5636
6297
  " privateDecrypt: die(\"privateDecrypt\"),\n"
5637
- " scrypt: die(\"scrypt\"),\n"
5638
- " scryptSync: die(\"scryptSync\"),\n"
5639
- " hkdf: die(\"hkdf\"),\n"
5640
- " hkdfSync: die(\"hkdfSync\"),\n"
5641
6298
  " X509Certificate: die(\"X509Certificate\"),\n"
5642
6299
  " Certificate: die(\"Certificate\"),\n"
5643
6300
  " checkPrime: die(\"checkPrime\"),\n"
@@ -5652,7 +6309,7 @@ static const char isl_modules_bootstrap[] =
5652
6309
  " crypto.subtle = webcrypto ? webcrypto.subtle : undefined;\n"
5653
6310
  " return crypto;\n"
5654
6311
  "}\n"
5655
- " const mod = makeCrypto({ digest: (a, d) => host.digest(a, d), hmac: (a, k, d) => host.hmac(a, k, d), Buffer: builtins.buffer().Buffer });\n"
6312
+ " const mod = makeCrypto({ digest: (a, d) => host.digest(a, d), hmac: (a, k, d) => host.hmac(a, k, d), scrypt: (...args) => host.scrypt(...args), Buffer: builtins.buffer().Buffer });\n"
5656
6313
  " mod.default = mod;\n"
5657
6314
  " return mod;\n"
5658
6315
  " });\n"
@@ -6942,6 +7599,17 @@ static const char isl_modules_bootstrap[] =
6942
7599
  * isDeepStrictEqual, stripVTControlCharacters, styleText,
6943
7600
  * parseArgs, toUSVString). The host supplies what JS cannot see:
6944
7601
  * promise state (JS_PromiseState), the pid, and fd writes. */
7602
+ " const envArgumentError = (name, expected, value) => {\n"
7603
+ " const type = typeof value;\n"
7604
+ " let received;\n"
7605
+ " if (value === null || value === undefined) received = String(value);\n"
7606
+ " else if (type === 'function') received = 'function ' + value.name;\n"
7607
+ " else if (type === 'object' && value.constructor && value.constructor.name) received = 'an instance of ' + value.constructor.name;\n"
7608
+ " else received = type === 'object' ? builtins.util().inspect(value, { depth: -1 }) : 'type ' + type + ' (' + builtins.util().inspect(value) + ')';\n"
7609
+ " const error = new TypeError('The \"' + name + '\" ' + (name.includes('.') ? 'property' : 'argument') + ' must be ' + expected + '. Received ' + received);\n"
7610
+ " error.code = 'ERR_INVALID_ARG_TYPE';\n"
7611
+ " throw error;\n"
7612
+ " };\n"
6945
7613
  " builtins.util = memo(() => {\n"
6946
7614
  "function makeUtil(env) {\n"
6947
7615
  " const inspectCustom = Symbol.for(\"nodejs.util.inspect.custom\");\n"
@@ -7337,7 +8005,7 @@ static const char isl_modules_bootstrap[] =
7337
8005
  " braces = [\"{\", \"}\"];\n"
7338
8006
  " formatter = () => [];\n"
7339
8007
  " } else {\n"
7340
- " if (depth > ctx.depth && ctx.depth !== null) {\n"
8008
+ " if (keys.length > 0 && depth > ctx.depth && ctx.depth !== null) {\n"
7341
8009
  " return \"[\" + (ctorName === null ? \"Object: null prototype\" : ctorName) + \"]\";\n"
7342
8010
  " }\n"
7343
8011
  " if (protoOf === null) {\n"
@@ -7527,21 +8195,33 @@ static const char isl_modules_bootstrap[] =
7527
8195
  " Object.defineProperty(ctor, \"super_\", { value: superCtor, writable: true, configurable: true });\n"
7528
8196
  " Object.setPrototypeOf(ctor.prototype, superCtor.prototype);\n"
7529
8197
  " };\n"
8198
+ " const received = (v) => {\n"
8199
+ " if (v === null || v === undefined) return String(v);\n"
8200
+ " if (typeof v === 'object') return v.constructor && 'name' in v.constructor ? 'an instance of ' + v.constructor.name : inspect(v, { depth: -1 });\n"
8201
+ " if (typeof v === 'function') return 'function ' + v.name;\n"
8202
+ " if (typeof v === 'string') {\n"
8203
+ " if (v.length > 28) v = v.slice(0, 25) + '...';\n"
8204
+ " return 'type string (' + (v.includes(\"'\") ? JSON.stringify(v) : \"'\" + v + \"'\") + ')';\n"
8205
+ " }\n"
8206
+ " if (typeof v === 'number') return 'type number (' + (Object.is(v, -0) ? '-0' : String(v)) + ')';\n"
8207
+ " if (typeof v === 'bigint') return 'type bigint (' + v + 'n)';\n"
8208
+ " if (typeof v === 'symbol') return 'type symbol (' + String(v) + ')';\n"
8209
+ " return 'type ' + typeof v + ' (' + String(v) + ')';\n"
8210
+ " };\n"
8211
+ " const validateAdapterFunction = (value, name) => {\n"
8212
+ " if (typeof value !== 'function') {\n"
8213
+ " const e = new TypeError('The ' + (name === 'last argument' ? name : '\"' + name + '\" ' + (name.includes('.') ? 'property' : 'argument')) + ' must be of type function. Received ' + received(value));\n"
8214
+ " e.code = 'ERR_INVALID_ARG_TYPE';\n"
8215
+ " throw e;\n"
8216
+ " }\n"
8217
+ " };\n"
7530
8218
  " const kCustomPromisified = Symbol.for(\"nodejs.util.promisify.custom\");\n"
7531
8219
  " const kCustomPromisifyArgs = Symbol(\"customPromisifyArgs\");\n"
7532
8220
  " const promisify = (original) => {\n"
7533
- " if (typeof original !== \"function\") {\n"
7534
- " const e = new TypeError('The \"original\" argument must be of type function. Received ' + (original === null ? \"null\" : typeof original === \"object\" ? \"an instance of Object\" : typeof original === \"undefined\" ? \"undefined\" : \"type \" + typeof original + \" (\" + JSON.stringify(original) + \")\"));\n"
7535
- " e.code = \"ERR_INVALID_ARG_TYPE\";\n"
7536
- " throw e;\n"
7537
- " }\n"
8221
+ " validateAdapterFunction(original, 'original');\n"
7538
8222
  " if (original[kCustomPromisified]) {\n"
7539
8223
  " const fn = original[kCustomPromisified];\n"
7540
- " if (typeof fn !== \"function\") {\n"
7541
- " const e = new TypeError('The \"util.promisify.custom\" property must be of type function');\n"
7542
- " e.code = \"ERR_INVALID_ARG_TYPE\";\n"
7543
- " throw e;\n"
7544
- " }\n"
8224
+ " validateAdapterFunction(fn, 'util.promisify.custom');\n"
7545
8225
  " return Object.defineProperty(fn, kCustomPromisified, { value: fn, enumerable: false, writable: false, configurable: true });\n"
7546
8226
  " }\n"
7547
8227
  " const argumentNames = original[kCustomPromisifyArgs];\n"
@@ -7563,30 +8243,21 @@ static const char isl_modules_bootstrap[] =
7563
8243
  " Object.setPrototypeOf(fn, Object.getPrototypeOf(original));\n"
7564
8244
  " Object.defineProperty(fn, kCustomPromisified, { value: fn, enumerable: false, writable: false, configurable: true });\n"
7565
8245
  " const descriptors = Object.getOwnPropertyDescriptors(original);\n"
7566
- " delete descriptors.name;\n"
7567
- " delete descriptors.length;\n"
8246
+ " for (const descriptor of Object.values(descriptors)) Object.setPrototypeOf(descriptor, null);\n"
7568
8247
  " return Object.defineProperties(fn, descriptors);\n"
7569
8248
  " };\n"
7570
8249
  " promisify.custom = kCustomPromisified;\n"
7571
8250
  " const callbackify = (original) => {\n"
7572
- " if (typeof original !== \"function\") {\n"
7573
- " const e = new TypeError('The \"original\" argument must be of type function');\n"
7574
- " e.code = \"ERR_INVALID_ARG_TYPE\";\n"
7575
- " throw e;\n"
7576
- " }\n"
8251
+ " validateAdapterFunction(original, 'original');\n"
7577
8252
  " function callbackified(...args) {\n"
7578
8253
  " const maybeCb = args.pop();\n"
7579
- " if (typeof maybeCb !== \"function\") {\n"
7580
- " const e = new TypeError(\"The last argument must be of type function\");\n"
7581
- " e.code = \"ERR_INVALID_ARG_TYPE\";\n"
7582
- " throw e;\n"
7583
- " }\n"
8254
+ " validateAdapterFunction(maybeCb, 'last argument');\n"
7584
8255
  " const cb = (...cbArgs) => Reflect.apply(maybeCb, this, cbArgs);\n"
7585
8256
  " Reflect.apply(original, this, args).then(\n"
7586
8257
  " (ret) => queueMicrotask(() => cb(null, ret)),\n"
7587
8258
  " (rej) => queueMicrotask(() => {\n"
7588
- " if (rej === null || (typeof rej !== \"object\" && typeof rej !== \"function\")) {\n"
7589
- " const wrapped = new Error(\"Promise was rejected with a falsy value\");\n"
8259
+ " if (!rej) {\n"
8260
+ " const wrapped = new Error(\"Promise was rejected with falsy value\");\n"
7590
8261
  " wrapped.code = \"ERR_FALSY_VALUE_REJECTION\";\n"
7591
8262
  " wrapped.reason = rej;\n"
7592
8263
  " return cb(wrapped);\n"
@@ -7595,8 +8266,10 @@ static const char isl_modules_bootstrap[] =
7595
8266
  " }),\n"
7596
8267
  " );\n"
7597
8268
  " }\n"
7598
- " Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));\n"
7599
8269
  " const descriptors = Object.getOwnPropertyDescriptors(original);\n"
8270
+ " if (typeof descriptors.length.value === 'number') descriptors.length.value++;\n"
8271
+ " if (typeof descriptors.name.value === 'string') descriptors.name.value += 'Callbackified';\n"
8272
+ " for (const descriptor of Object.values(descriptors)) Object.setPrototypeOf(descriptor, null);\n"
7600
8273
  " Object.defineProperties(callbackified, descriptors);\n"
7601
8274
  " return callbackified;\n"
7602
8275
  " };\n"
@@ -7867,147 +8540,138 @@ static const char isl_modules_bootstrap[] =
7867
8540
  " }\n"
7868
8541
  " return colorize ? left + text + right : text;\n"
7869
8542
  " };\n"
7870
- " const parseArgs = (config) => {\n"
7871
- " config = config === undefined ? {} : config;\n"
7872
- " const args = config.args !== undefined ? config.args : env.argv.slice(2);\n"
7873
- " const strict = config.strict !== undefined ? !!config.strict : true;\n"
7874
- " const allowPositionals = config.allowPositionals !== undefined ? !!config.allowPositionals : !strict;\n"
7875
- " const allowNegative = !!config.allowNegative;\n"
7876
- " const returnTokens = !!config.tokens;\n"
7877
- " const options = config.options !== undefined ? config.options : {};\n"
7878
- " const result = { values: { __proto__: null }, positionals: [] };\n"
7879
- " const tokens = [];\n"
7880
- " const shortOf = (ch) => {\n"
7881
- " for (const name of Object.keys(options)) {\n"
7882
- " if (options[name].short === ch) return name;\n"
7883
- " }\n"
7884
- " return undefined;\n"
7885
- " };\n"
7886
- " const unknownError = (raw) => {\n"
7887
- " const e = new TypeError(\"Unknown option '\" + raw + \"'. To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- \\\"\" + raw + \"\\\"\");\n"
7888
- " e.code = \"ERR_PARSE_ARGS_UNKNOWN_OPTION\";\n"
7889
- " throw e;\n"
8543
+ " const parseArgs = (config = {}) => {\n"
8544
+ " if (config === null) throw new TypeError(\"Cannot convert undefined or null to object\");\n"
8545
+ " const own = (o, k) => Object.prototype.hasOwnProperty.call(o, k);\n"
8546
+ " const get = (o, k) => own(o, k) ? o[k] : undefined;\n"
8547
+ " const args = get(config, 'args') ?? env.argv.slice(2);\n"
8548
+ " const strict = get(config, 'strict') ?? true;\n"
8549
+ " const allowPositionals = get(config, 'allowPositionals') ?? !strict;\n"
8550
+ " const returnTokens = get(config, 'tokens') ?? false;\n"
8551
+ " const allowNegative = get(config, 'allowNegative') ?? false;\n"
8552
+ " const options = get(config, 'options') ?? Object.create(null);\n"
8553
+ " const fail = (code, message) => { const e = new TypeError(message); e.code = code; throw e; };\n"
8554
+ " const validate = (v, name, expected, ok) => {\n"
8555
+ " if (!ok) fail('ERR_INVALID_ARG_TYPE', 'The \"' + name + '\" ' + (name.startsWith('options.') ? 'property' : 'argument') + ' must be ' + expected + '. Received ' + received(v));\n"
7890
8556
  " };\n"
7891
- " const store = (name, value, raw) => {\n"
7892
- " const cfg = options[name] || {};\n"
7893
- " const type = cfg.type;\n"
7894
- " if (strict) {\n"
7895
- " if (options[name] === undefined) unknownError(raw);\n"
7896
- " if (type === \"string\" && value === undefined) {\n"
7897
- " const e = new TypeError(\"Option '\" + raw + (cfg.short && raw.startsWith(\"--\") === false ? \"\" : \"\") + \" <value>' argument missing\");\n"
7898
- " e.code = \"ERR_PARSE_ARGS_INVALID_OPTION_VALUE\";\n"
7899
- " throw e;\n"
7900
- " }\n"
7901
- " if (type === \"boolean\" && value !== undefined) {\n"
7902
- " const e = new TypeError(\"Option '\" + raw + \"' does not take an argument\");\n"
7903
- " e.code = \"ERR_PARSE_ARGS_INVALID_OPTION_VALUE\";\n"
7904
- " throw e;\n"
7905
- " }\n"
7906
- " }\n"
7907
- " const finalValue = value === undefined ? true : value;\n"
7908
- " tokens.push({ kind: \"option\", name, rawName: raw, index: tokenIndex, value: value === undefined ? undefined : value, inlineValue: inline });\n"
7909
- " if (cfg.multiple) {\n"
7910
- " if (result.values[name] === undefined) result.values[name] = [];\n"
7911
- " result.values[name].push(finalValue);\n"
7912
- " } else {\n"
7913
- " result.values[name] = finalValue;\n"
8557
+ " const object = (v, name) => validate(v, name, 'of type object', v !== null && typeof v === 'object' && !Array.isArray(v));\n"
8558
+ " const boolean = (v, name) => validate(v, name, 'of type boolean', typeof v === 'boolean');\n"
8559
+ " const string = (v, name) => validate(v, name, 'of type string', typeof v === 'string');\n"
8560
+ " validate(args, 'args', 'an instance of Array', Array.isArray(args));\n"
8561
+ " boolean(strict, 'strict');\n"
8562
+ " boolean(allowPositionals, 'allowPositionals');\n"
8563
+ " boolean(returnTokens, 'tokens');\n"
8564
+ " boolean(allowNegative, 'allowNegative');\n"
8565
+ " object(options, 'options');\n"
8566
+ " for (const [name, option] of Object.entries(options)) {\n"
8567
+ " const path = 'options.' + name;\n"
8568
+ " object(option, path);\n"
8569
+ " const type = get(option, 'type');\n"
8570
+ " validate(type, path + '.type', \"('string|boolean')\", type === 'string' || type === 'boolean');\n"
8571
+ " if (own(option, 'short')) {\n"
8572
+ " const short = option.short;\n"
8573
+ " string(short, path + '.short');\n"
8574
+ " if (short.length !== 1) fail('ERR_INVALID_ARG_VALUE', \"The property '\" + path + \".short' must be a single character. Received \" + inspect(short));\n"
8575
+ " }\n"
8576
+ " const multiple = get(option, 'multiple');\n"
8577
+ " if (own(option, 'multiple')) boolean(multiple, path + '.multiple');\n"
8578
+ " const value = get(option, 'default');\n"
8579
+ " if (value !== undefined) {\n"
8580
+ " const check = type === 'string' ? string : boolean;\n"
8581
+ " if (multiple) {\n"
8582
+ " validate(value, path + '.default', 'an instance of Array', Array.isArray(value));\n"
8583
+ " for (let i = 0; i < value.length; i++) check(value[i], path + '.default[' + i + ']');\n"
8584
+ " } else check(value, path + '.default');\n"
7914
8585
  " }\n"
8586
+ " }\n"
8587
+ " const optionGet = (name, key) => own(options, name) ? get(options[name], key) : undefined;\n"
8588
+ " const shortName = (ch) => {\n"
8589
+ " const entry = Object.entries(options).find(([, option]) => get(option, 'short') === ch);\n"
8590
+ " return entry ? entry[0] : ch;\n"
7915
8591
  " };\n"
7916
- " let tokenIndex = -1;\n"
7917
- " let inline;\n"
7918
- " let afterDashDash = false;\n"
7919
- " for (let i = 0; i < args.length; i++) {\n"
7920
- " const arg = args[i];\n"
7921
- " tokenIndex = i;\n"
7922
- " inline = undefined;\n"
7923
- " if (afterDashDash) {\n"
7924
- " tokens.push({ kind: \"positional\", index: i, value: arg });\n"
7925
- " result.positionals.push(arg);\n"
7926
- " continue;\n"
7927
- " }\n"
7928
- " if (arg === \"--\") {\n"
7929
- " afterDashDash = true;\n"
7930
- " tokens.push({ kind: \"option-terminator\", index: i });\n"
7931
- " continue;\n"
8592
+ " const tokens = [];\n"
8593
+ " // Tokenize the full argument snapshot before checking usage, as Node does.\n"
8594
+ " const remaining = Array.prototype.slice.call(args);\n"
8595
+ " let index = -1;\n"
8596
+ " let groupCount = 0;\n"
8597
+ " while (remaining.length) {\n"
8598
+ " const arg = remaining.shift();\n"
8599
+ " if (groupCount > 0) groupCount--; else index++;\n"
8600
+ " if (arg === '--') {\n"
8601
+ " tokens.push({ kind: 'option-terminator', index });\n"
8602
+ " for (const value of remaining) tokens.push({ kind: 'positional', index: ++index, value });\n"
8603
+ " break;\n"
7932
8604
  " }\n"
7933
- " if (arg.startsWith(\"--\")) {\n"
7934
- " const eq = arg.indexOf(\"=\");\n"
7935
- " if (eq !== -1) {\n"
7936
- " const name = arg.slice(2, eq);\n"
7937
- " inline = true;\n"
7938
- " store(name, arg.slice(eq + 1), \"--\" + name);\n"
8605
+ " // Reading length first deliberately preserves Node's nullish-argument error.\n"
8606
+ " if (arg == null) throw new TypeError(\"Cannot read properties of \" + arg + \" (reading 'length')\");\n"
8607
+ " const length = arg.length;\n"
8608
+ " if (length === 2 && String.prototype.charAt.call(arg, 0) === '-' && String.prototype.charAt.call(arg, 1) !== '-') {\n"
8609
+ " const name = shortName(String.prototype.charAt.call(arg, 1));\n"
8610
+ " let value, inlineValue;\n"
8611
+ " if (optionGet(name, 'type') === 'string' && remaining[0] != null) { value = remaining.shift(); inlineValue = false; }\n"
8612
+ " tokens.push({ kind: 'option', name, rawName: arg, index, value, inlineValue });\n"
8613
+ " if (value != null) index++;\n"
8614
+ " } else if (length > 2 && String.prototype.charAt.call(arg, 0) === '-' && String.prototype.charAt.call(arg, 1) !== '-') {\n"
8615
+ " const firstName = shortName(String.prototype.charAt.call(arg, 1));\n"
8616
+ " if (optionGet(firstName, 'type') === 'string') {\n"
8617
+ " tokens.push({ kind: 'option', name: firstName, rawName: '-' + String.prototype.charAt.call(arg, 1), index, value: String.prototype.slice.call(arg, 2), inlineValue: true });\n"
7939
8618
  " } else {\n"
7940
- " const name = arg.slice(2);\n"
7941
- " const cfg = options[name];\n"
7942
- " if (cfg !== undefined && cfg.type === \"string\" && i + 1 < args.length) {\n"
7943
- " inline = false;\n"
7944
- " store(name, args[++i], arg);\n"
7945
- " } else if (allowNegative && name.startsWith(\"no-\") && (options[name.slice(3)] || {}).type === \"boolean\") {\n"
7946
- " const positive = name.slice(3);\n"
7947
- " tokens.push({ kind: \"option\", name: positive, rawName: arg, index: i, value: undefined, inlineValue: undefined });\n"
7948
- " result.values[positive] = false;\n"
7949
- " } else {\n"
7950
- " if (strict && cfg === undefined) unknownError(arg);\n"
7951
- " if (strict && cfg.type === \"string\") {\n"
7952
- " const e = new TypeError(\"Option '--\" + name + \" <value>' argument missing\");\n"
7953
- " e.code = \"ERR_PARSE_ARGS_INVALID_OPTION_VALUE\";\n"
7954
- " throw e;\n"
7955
- " }\n"
7956
- " store(name, undefined, arg);\n"
8619
+ " const expanded = [];\n"
8620
+ " for (let i = 1; i < length; i++) {\n"
8621
+ " const ch = String.prototype.charAt.call(arg, i);\n"
8622
+ " const name = shortName(ch);\n"
8623
+ " if (optionGet(name, 'type') === 'string' && i !== length - 1) { expanded.push('-' + String.prototype.slice.call(arg, i)); break; }\n"
8624
+ " expanded.push('-' + ch);\n"
7957
8625
  " }\n"
8626
+ " remaining.unshift(...expanded);\n"
8627
+ " groupCount = expanded.length;\n"
7958
8628
  " }\n"
7959
- " continue;\n"
7960
- " }\n"
7961
- " if (arg.length > 1 && arg[0] === \"-\") {\n"
7962
- " const chars = arg.slice(1);\n"
7963
- " let consumed = false;\n"
7964
- " for (let c = 0; c < chars.length; c++) {\n"
7965
- " const ch = chars[c];\n"
7966
- " const name = shortOf(ch);\n"
7967
- " const raw = \"-\" + ch;\n"
7968
- " const cfg = name !== undefined ? options[name] : undefined;\n"
7969
- " if (cfg !== undefined && cfg.type === \"string\") {\n"
7970
- " if (c < chars.length - 1) {\n"
7971
- " inline = true;\n"
7972
- " store(name, chars.slice(c + 1), raw);\n"
7973
- " } else if (i + 1 < args.length) {\n"
7974
- " inline = false;\n"
7975
- " store(name, args[++i], raw);\n"
7976
- " } else if (strict) {\n"
7977
- " const e = new TypeError(\"Option '\" + raw + \", --\" + name + \" <value>' argument missing\");\n"
7978
- " e.code = \"ERR_PARSE_ARGS_INVALID_OPTION_VALUE\";\n"
7979
- " throw e;\n"
7980
- " } else {\n"
7981
- " store(name, undefined, raw);\n"
7982
- " }\n"
7983
- " consumed = true;\n"
7984
- " break;\n"
8629
+ " } else if (length > 2 && String.prototype.startsWith.call(arg, '--')) {\n"
8630
+ " const eq = String.prototype.indexOf.call(arg, '=', 3);\n"
8631
+ " const name = String.prototype.slice.call(arg, 2, eq < 0 ? undefined : eq);\n"
8632
+ " let value, inlineValue;\n"
8633
+ " if (eq >= 0) { value = String.prototype.slice.call(arg, eq + 1); inlineValue = true; }\n"
8634
+ " else if (optionGet(name, 'type') === 'string' && remaining[0] != null) { value = remaining.shift(); inlineValue = false; }\n"
8635
+ " tokens.push({ kind: 'option', name, rawName: '--' + name, index, value, inlineValue });\n"
8636
+ " if (eq < 0 && value != null) index++;\n"
8637
+ " } else tokens.push({ kind: 'positional', index, value: arg });\n"
8638
+ " }\n"
8639
+ " const result = { values: Object.create(null), positionals: [] };\n"
8640
+ " if (returnTokens) result.tokens = tokens;\n"
8641
+ " for (const token of tokens) {\n"
8642
+ " if (token.kind === 'positional') {\n"
8643
+ " if (!allowPositionals) fail('ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL', \"Unexpected argument '\" + token.value + \"'. This command does not take positional arguments\");\n"
8644
+ " result.positionals.push(token.value);\n"
8645
+ " } else if (token.kind === 'option') {\n"
8646
+ " let name = token.name;\n"
8647
+ " if (strict) {\n"
8648
+ " if (!own(options, name)) {\n"
8649
+ " if (allowNegative && name.startsWith('no-') && own(options, name.slice(3)) && optionGet(name.slice(3), 'type') === 'boolean') name = name.slice(3);\n"
8650
+ " else fail('ERR_PARSE_ARGS_UNKNOWN_OPTION', \"Unknown option '\" + token.rawName + \"'\" + (allowPositionals ? \". To specify a positional argument starting with a '-', place it at the end of the command after '--', as in '-- \\\"\" + token.rawName + \"\\\"\" : ''));\n"
7985
8651
  " }\n"
7986
- " if (name === undefined) {\n"
7987
- " if (strict) unknownError(raw);\n"
7988
- " store(ch, undefined, raw);\n"
7989
- " } else {\n"
7990
- " store(name, undefined, raw);\n"
8652
+ " const short = optionGet(name, 'short');\n"
8653
+ " const label = (short ? '-' + short + ', ' : '') + '--' + name;\n"
8654
+ " if (optionGet(name, 'type') === 'string' && typeof token.value !== 'string') fail('ERR_PARSE_ARGS_INVALID_OPTION_VALUE', \"Option '\" + label + \" <value>' argument missing\");\n"
8655
+ " if (optionGet(name, 'type') === 'boolean' && token.value != null) fail('ERR_PARSE_ARGS_INVALID_OPTION_VALUE', \"Option '\" + label + \"' does not take an argument\");\n"
8656
+ " if (!token.inlineValue && token.value != null && token.value.length > 1 && String.prototype.charAt.call(token.value, 0) === '-') {\n"
8657
+ " const example = token.rawName.startsWith('--') ? \"'\" + token.rawName + \"=-XYZ'\" : \"'--\" + token.name + \"=-XYZ' or '\" + token.rawName + \"-XYZ'\";\n"
8658
+ " fail('ERR_PARSE_ARGS_INVALID_OPTION_VALUE', \"Option '\" + token.rawName + \"' argument is ambiguous.\\nDid you forget to specify the option argument for '\" + token.rawName + \"'?\\nTo specify an option argument starting with a dash use \" + example + '.');\n"
7991
8659
  " }\n"
7992
8660
  " }\n"
7993
- " void consumed;\n"
7994
- " continue;\n"
8661
+ " name = token.name;\n"
8662
+ " let value = token.value;\n"
8663
+ " if (name === '__proto__') continue;\n"
8664
+ " if (allowNegative && name.startsWith('no-') && value === undefined) { name = name.slice(3); token.name = name; value = false; }\n"
8665
+ " value = value ?? true;\n"
8666
+ " if (optionGet(name, 'multiple')) {\n"
8667
+ " if (!result.values[name]) result.values[name] = [];\n"
8668
+ " result.values[name].push(value);\n"
8669
+ " } else result.values[name] = value;\n"
7995
8670
  " }\n"
7996
- " if (strict && !allowPositionals) {\n"
7997
- " const e = new TypeError(\"Unexpected argument '\" + arg + \"'. This command does not take positional arguments\");\n"
7998
- " e.code = \"ERR_PARSE_ARGS_UNEXPECTED_POSITIONAL\";\n"
7999
- " throw e;\n"
8000
- " }\n"
8001
- " tokens.push({ kind: \"positional\", index: i, value: arg });\n"
8002
- " result.positionals.push(arg);\n"
8003
8671
  " }\n"
8004
- " for (const name of Object.keys(options)) {\n"
8005
- " const cfg = options[name];\n"
8006
- " if (cfg.default !== undefined && !(name in result.values)) {\n"
8007
- " result.values[name] = cfg.default;\n"
8008
- " }\n"
8672
+ " for (const [name, option] of Object.entries(options)) {\n"
8673
+ " if (name !== '__proto__' && get(option, 'default') !== undefined && result.values[name] === undefined) result.values[name] = get(option, 'default');\n"
8009
8674
  " }\n"
8010
- " if (returnTokens) result.tokens = tokens;\n"
8011
8675
  " return result;\n"
8012
8676
  " };\n"
8013
8677
  " const toUSVString = (s) => String(s).replace(/[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]/g, \"�\");\n"
@@ -8020,6 +8684,10 @@ static const char isl_modules_bootstrap[] =
8020
8684
  " format, formatWithOptions, inspect, inherits, promisify, callbackify,\n"
8021
8685
  " deprecate, debuglog, debug: debuglog, types, isDeepStrictEqual,\n"
8022
8686
  " stripVTControlCharacters, styleText, parseArgs, toUSVString, _extend,\n"
8687
+ " parseEnv: (content) => {\n"
8688
+ " if (typeof content !== 'string') envArgumentError('content', 'of type string', content);\n"
8689
+ " return host.parseEnv(toUSVString(content));\n"
8690
+ " },\n"
8023
8691
  " TextEncoder: globalThis.TextEncoder, TextDecoder: globalThis.TextDecoder,\n"
8024
8692
  " isArray: (v) => Array.isArray(v),\n"
8025
8693
  " };\n"
@@ -8791,9 +9459,8 @@ static const char isl_modules_bootstrap[] =
8791
9459
  " c.default = c;\n"
8792
9460
  " return c;\n"
8793
9461
  " });\n"
8794
- /* node:timers (+ timers/promises) over the island's timer
8795
- * bridge; setImmediate rides a zero-delay timer (Node's check
8796
- * phase does not exist here — documented divergence). */
9462
+ /* node:timers and timers/promises share the native timer heap and
9463
+ * immediate queue through the web prelude's handle objects. */
8797
9464
  " builtins.timers = memo(() => {\n"
8798
9465
  " const t = {\n"
8799
9466
  " setTimeout: globalThis.setTimeout,\n"
@@ -8807,30 +9474,94 @@ static const char isl_modules_bootstrap[] =
8807
9474
  " return t;\n"
8808
9475
  " });\n"
8809
9476
  " builtins['timers/promises'] = memo(() => {\n"
8810
- " const delay = (ms, value, options) => new Promise((resolve, reject) => {\n"
8811
- " const t = globalThis.setTimeout(() => resolve(value), ms);\n"
8812
- " if (options !== undefined && options !== null && options.signal !== undefined && typeof options.signal.addEventListener === 'function') {\n"
8813
- " options.signal.addEventListener('abort', () => {\n"
8814
- " globalThis.clearTimeout(t);\n"
8815
- " const e = new Error('The operation was aborted');\n"
8816
- " e.name = 'AbortError';\n"
8817
- " e.code = 'ABORT_ERR';\n"
8818
- " reject(e);\n"
8819
- " });\n"
9477
+ " const resistant = Symbol.for('scriptc.events.resistStopPropagation');\n"
9478
+ " const checkDelay = (delay) => {\n"
9479
+ " if (delay !== undefined && typeof delay !== 'number') envArgumentError('delay', 'of type number', delay);\n"
9480
+ " };\n"
9481
+ " const checkOptions = (options) => {\n"
9482
+ " if (options === null || typeof options !== 'object' || Array.isArray(options)) envArgumentError('options', 'of type object', options);\n"
9483
+ " if (options.signal !== undefined) {\n"
9484
+ " const signal = options.signal;\n"
9485
+ " if (signal === null || typeof signal !== 'object' || !('aborted' in signal)) envArgumentError('options.signal', 'an instance of AbortSignal', signal);\n"
9486
+ " }\n"
9487
+ " if (options.ref !== undefined) {\n"
9488
+ " const ref = options.ref;\n"
9489
+ " if (typeof ref !== 'boolean') envArgumentError('options.ref', 'of type boolean', ref);\n"
9490
+ " }\n"
9491
+ " const { signal, ref = true } = options;\n"
9492
+ " return { signal, ref };\n"
9493
+ " };\n"
9494
+ " const abortError = (signal) => {\n"
9495
+ " const error = new Error('The operation was aborted', { cause: signal.reason });\n"
9496
+ " error.name = 'AbortError'; error.code = 'ABORT_ERR';\n"
9497
+ " return error;\n"
9498
+ " };\n"
9499
+ " const wait = (immediate, delay, value, options) => {\n"
9500
+ " let signal, ref;\n"
9501
+ " try {\n"
9502
+ " if (!immediate) checkDelay(delay);\n"
9503
+ " ({ signal, ref } = checkOptions(options));\n"
9504
+ " } catch (error) { return Promise.reject(error); }\n"
9505
+ " if (signal && signal.aborted) return Promise.reject(abortError(signal));\n"
9506
+ " let timer, onCancel;\n"
9507
+ " const promise = new Promise((resolve, reject) => {\n"
9508
+ " timer = immediate ? globalThis.setImmediate(resolve, value) : globalThis.setTimeout(resolve, delay, value);\n"
9509
+ " if (!ref) timer.unref();\n"
9510
+ " if (signal) {\n"
9511
+ " onCancel = () => {\n"
9512
+ " if (!timer._destroyed) {\n"
9513
+ " if (immediate) globalThis.clearImmediate(timer); else globalThis.clearTimeout(timer);\n"
9514
+ " reject(abortError(signal));\n"
9515
+ " }\n"
9516
+ " };\n"
9517
+ " signal.addEventListener('abort', onCancel, { __proto__: null, [resistant]: true });\n"
9518
+ " }\n"
9519
+ " });\n"
9520
+ " return onCancel ? promise.finally(() => signal.removeEventListener('abort', onCancel)) : promise;\n"
9521
+ " };\n"
9522
+ " function setTimeout(delay, value, options = {}) { return wait(false, delay, value, options); }\n"
9523
+ " function setImmediate(value, options = {}) { return wait(true, undefined, value, options); }\n"
9524
+ " async function* setInterval(delay, value, options = {}) {\n"
9525
+ " checkDelay(delay);\n"
9526
+ " const { signal, ref } = checkOptions(options);\n"
9527
+ " if (signal && signal.aborted) throw abortError(signal);\n"
9528
+ " let timer, onCancel;\n"
9529
+ " try {\n"
9530
+ " let notYielded = 0, callback;\n"
9531
+ " timer = globalThis.setInterval(() => {\n"
9532
+ " notYielded++;\n"
9533
+ " if (callback) { callback(); callback = undefined; }\n"
9534
+ " }, delay);\n"
9535
+ " if (!ref) timer.unref();\n"
9536
+ " if (signal) {\n"
9537
+ " onCancel = () => {\n"
9538
+ " globalThis.clearInterval(timer);\n"
9539
+ " if (callback) { callback(Promise.reject(abortError(signal))); callback = undefined; }\n"
9540
+ " };\n"
9541
+ " signal.addEventListener('abort', onCancel, { __proto__: null, once: true, [resistant]: true });\n"
9542
+ " }\n"
9543
+ " while (!(signal && signal.aborted)) {\n"
9544
+ " if (notYielded === 0) await new Promise(resolve => callback = resolve);\n"
9545
+ " for (; notYielded > 0; notYielded--) yield value;\n"
9546
+ " }\n"
9547
+ " throw abortError(signal);\n"
9548
+ " } finally {\n"
9549
+ " globalThis.clearInterval(timer);\n"
9550
+ " if (signal) signal.removeEventListener('abort', onCancel);\n"
8820
9551
  " }\n"
8821
- " });\n"
9552
+ " }\n"
9553
+ " const schedulerBrand = Symbol('kScheduler');\n"
9554
+ " const checkScheduler = (receiver) => {\n"
9555
+ " if (!receiver[schedulerBrand]) { const error = new TypeError('Value of \"this\" must be of type Scheduler'); error.code = 'ERR_INVALID_THIS'; throw error; }\n"
9556
+ " };\n"
9557
+ " class Scheduler {\n"
9558
+ " constructor() { const error = new TypeError('Illegal constructor'); error.code = 'ERR_ILLEGAL_CONSTRUCTOR'; throw error; }\n"
9559
+ " yield() { checkScheduler(this); return setImmediate(); }\n"
9560
+ " wait(delay, options) { checkScheduler(this); return setTimeout(delay, undefined, options); }\n"
9561
+ " }\n"
9562
+ " const scheduler = Object.create(Scheduler.prototype); scheduler[schedulerBrand] = true;\n"
8822
9563
  " const tp = {\n"
8823
- " setTimeout: delay,\n"
8824
- " setImmediate: (value) => delay(0, value),\n"
8825
- " setInterval: (ms, value, options) => ({\n"
8826
- " async *[Symbol.asyncIterator]() {\n"
8827
- " for (;;) {\n"
8828
- " await delay(ms, undefined, options);\n"
8829
- " yield value;\n"
8830
- " }\n"
8831
- " },\n"
8832
- " }),\n"
8833
- " scheduler: { wait: (ms) => delay(ms), yield: () => delay(0) },\n"
9564
+ " setTimeout, setImmediate, setInterval, scheduler,\n"
8834
9565
  " };\n"
8835
9566
  " tp.default = tp;\n"
8836
9567
  " return tp;\n"
@@ -9224,9 +9955,54 @@ static const char isl_modules_bootstrap[] =
9224
9955
  " s.emit = () => false;\n"
9225
9956
  " return s;\n"
9226
9957
  " };\n"
9958
+ " const envPrototype = Object.create(Object.prototype);\n"
9959
+ " Object.defineProperty(envPrototype, 'constructor', { value: Object, writable: true, configurable: true });\n"
9960
+ " const envTarget = Object.create(envPrototype);\n"
9961
+ " const env = new Proxy(envTarget, {\n"
9962
+ " get: (target, key, receiver) => {\n"
9963
+ " if (typeof key === 'symbol') return Reflect.get(target, key, receiver);\n"
9964
+ " const value = host.envGet(key);\n"
9965
+ " return value === undefined ? Reflect.get(target, key, receiver) : value;\n"
9966
+ " },\n"
9967
+ " set: (_, key, value) => {\n"
9968
+ " if (typeof key === 'symbol' || typeof value === 'symbol') throw new TypeError('Cannot convert a Symbol value to a string');\n"
9969
+ " return host.envSet(key, String(value));\n"
9970
+ " },\n"
9971
+ " deleteProperty: (_, key) => {\n"
9972
+ " if (typeof key === 'symbol') return true;\n"
9973
+ " return host.envDelete(key);\n"
9974
+ " },\n"
9975
+ " has: (target, key) => typeof key !== 'symbol' && host.envGet(key) !== undefined || Reflect.has(target, key),\n"
9976
+ " ownKeys: () => Reflect.ownKeys(host.env()),\n"
9977
+ " getOwnPropertyDescriptor: (_, key) => {\n"
9978
+ " if (typeof key === 'symbol') return undefined;\n"
9979
+ " const value = host.envGet(key);\n"
9980
+ " return value === undefined ? undefined : { value, writable: true, enumerable: true, configurable: true };\n"
9981
+ " },\n"
9982
+ " defineProperty: (_, key, descriptor) => {\n"
9983
+ " if (!descriptor.configurable || !descriptor.writable || !descriptor.enumerable || !('value' in descriptor) || 'get' in descriptor || 'set' in descriptor) {\n"
9984
+ " const error = new TypeError(\"'process.env' only accepts a configurable, writable, and enumerable data descriptor\");\n"
9985
+ " error.code = 'ERR_INVALID_OBJECT_DEFINE_PROPERTY';\n"
9986
+ " throw error;\n"
9987
+ " }\n"
9988
+ " if (typeof key === 'symbol' || typeof descriptor.value === 'symbol') throw new TypeError('Cannot convert a Symbol value to a string');\n"
9989
+ " return host.envSet(key, String(descriptor.value));\n"
9990
+ " },\n"
9991
+ " preventExtensions: () => { throw new TypeError('Cannot prevent extensions'); },\n"
9992
+ " });\n"
9993
+ " const loadEnvFile = (path) => {\n"
9994
+ " if (path instanceof globalThis.URL) path = host.urlToPath(path.href);\n"
9995
+ " const bytes = path instanceof Uint8Array;\n"
9996
+ " if (path != null && typeof path !== 'string' && !bytes) envArgumentError('path', 'of type string or an instance of Buffer or URL', path);\n"
9997
+ " return host.loadEnvFile(path, bytes, bytes && builtins.buffer().Buffer.isBuffer(path));\n"
9998
+ " };\n"
9227
9999
  " const p = {\n"
9228
10000
  " argv,\n"
9229
- " env: host.env(),\n"
10001
+ " env, loadEnvFile,\n"
10002
+ " chdir: (directory) => {\n"
10003
+ " if (typeof directory !== 'string') envArgumentError('directory', 'of type string', directory);\n"
10004
+ " return host.chdir(directory);\n"
10005
+ " },\n"
9230
10006
  " platform: host.platform(),\n"
9231
10007
  " execPath: argv[0],\n"
9232
10008
  " execArgv: [],\n"
@@ -9337,15 +10113,9 @@ static const char isl_modules_bootstrap[] =
9337
10113
  /* Node's Buffer global (and `global` itself) — embedded CJS
9338
10114
  * reaches both without requiring anything. */
9339
10115
  " globalThis.Buffer = builtins.buffer().Buffer;\n"
9340
- /* setImmediate/clearImmediate globals (zero-delay timers — no
9341
- * check phase in the island; documented divergence), and the
9342
- * global console upgraded to Node's util.format semantics for
10116
+ /* The global console upgraded to Node's util.format semantics for
9343
10117
  * npm builds (the web prelude's String() console stays for
9344
10118
  * non-npm islands). */
9345
- " if (globalThis.setImmediate === undefined) {\n"
9346
- " globalThis.setImmediate = (fn, ...args) => globalThis.setTimeout(fn, 0, ...args);\n"
9347
- " globalThis.clearImmediate = (t) => globalThis.clearTimeout(t);\n"
9348
- " }\n"
9349
10119
  " {\n"
9350
10120
  " const fmt = (...a) => builtins.util().formatWithOptions({}, ...a);\n"
9351
10121
  " const to = (fd, prefix) => (...a) => { host.write(fd, (prefix || '') + fmt(...a) + '\\n'); };\n"
@@ -9410,6 +10180,13 @@ static void isl_modules_boot(void) {
9410
10180
  JS_SetPropertyStr(isl_ctx, host, "resolve", JS_NewCFunction(isl_ctx, isl_host_resolve, "resolve", 2));
9411
10181
  JS_SetPropertyStr(isl_ctx, host, "argv", JS_NewCFunction(isl_ctx, isl_host_argv, "argv", 0));
9412
10182
  JS_SetPropertyStr(isl_ctx, host, "env", JS_NewCFunction(isl_ctx, isl_host_env, "env", 0));
10183
+ JS_SetPropertyStr(isl_ctx, host, "chdir", JS_NewCFunction(isl_ctx, isl_host_chdir, "chdir", 1));
10184
+ JS_SetPropertyStr(isl_ctx, host, "envGet", JS_NewCFunction(isl_ctx, isl_host_env_get, "envGet", 1));
10185
+ JS_SetPropertyStr(isl_ctx, host, "envSet", JS_NewCFunction(isl_ctx, isl_host_env_set, "envSet", 2));
10186
+ JS_SetPropertyStr(isl_ctx, host, "envDelete", JS_NewCFunction(isl_ctx, isl_host_env_delete, "envDelete", 1));
10187
+ JS_SetPropertyStr(isl_ctx, host, "parseEnv", JS_NewCFunction(isl_ctx, isl_host_parse_env, "parseEnv", 1));
10188
+ JS_SetPropertyStr(isl_ctx, host, "transcode", JS_NewCFunction(isl_ctx, isl_host_transcode, "transcode", 3));
10189
+ JS_SetPropertyStr(isl_ctx, host, "loadEnvFile", JS_NewCFunction(isl_ctx, isl_host_load_env_file, "loadEnvFile", 2));
9413
10190
  JS_SetPropertyStr(isl_ctx, host, "write", JS_NewCFunction(isl_ctx, isl_host_write, "write", 2));
9414
10191
  JS_SetPropertyStr(isl_ctx, host, "readStdin",
9415
10192
  JS_NewCFunction(isl_ctx, isl_host_read_stdin, "readStdin", 0));
@@ -9428,6 +10205,7 @@ static void isl_modules_boot(void) {
9428
10205
  JS_SetPropertyStr(isl_ctx, host, "promiseState", JS_NewCFunction(isl_ctx, isl_host_promise_state, "promiseState", 1));
9429
10206
  JS_SetPropertyStr(isl_ctx, host, "digest", JS_NewCFunction(isl_ctx, isl_host_digest, "digest", 2));
9430
10207
  JS_SetPropertyStr(isl_ctx, host, "hmac", JS_NewCFunction(isl_ctx, isl_host_hmac, "hmac", 3));
10208
+ JS_SetPropertyStr(isl_ctx, host, "scrypt", JS_NewCFunction(isl_ctx, isl_host_scrypt, "scrypt", 7));
9431
10209
  JS_SetPropertyStr(isl_ctx, host, "fs", JS_NewCFunction(isl_ctx, isl_host_fs, "fs", 4));
9432
10210
  JS_SetPropertyStr(isl_ctx, host, "fsConstants", JS_NewCFunction(isl_ctx, isl_host_fs_constants, "fsConstants", 0));
9433
10211
  JS_SetPropertyStr(isl_ctx, host, "path", JS_NewCFunction(isl_ctx, isl_host_path, "path", 4));
@@ -9819,20 +10597,34 @@ static JSValue isl_url_parse_host(JSContext *ctx, JSValueConst this_val,
9819
10597
  int argc, JSValueConst *argv) {
9820
10598
  (void)this_val;
9821
10599
  if (argc < 1) return JS_ThrowTypeError(ctx, "Invalid URL");
9822
- size_t len;
9823
- const char *s = JS_ToCStringLen(ctx, &len, argv[0]);
9824
- if (!s) return JS_EXCEPTION;
9825
- ScrStr *in = scr_str_new(s, len);
9826
- JS_FreeCString(ctx, s);
9827
- ScrUrl *u = scr_url_new(in);
10600
+ ScrStr *in = isl_arg_str(ctx, argv[0]);
10601
+ if (!in) return JS_EXCEPTION;
10602
+ ScrStr *base = argc > 1 && !JS_IsUndefined(argv[1]) ? isl_arg_str(ctx, argv[1]) : NULL;
10603
+ if (argc > 1 && !JS_IsUndefined(argv[1]) && !base) {
10604
+ scr_str_release(in);
10605
+ return JS_EXCEPTION;
10606
+ }
10607
+ ScrUrl *u = base ? scr_url_new_base(in, base) : scr_url_new(in);
9828
10608
  scr_str_release(in);
9829
- if (!u) return isl_throw_pending(ctx); /* the parser's catchable TypeError */
10609
+ scr_str_release(base);
10610
+ if (!u) {
10611
+ if (argc > 2 && JS_ToBool(ctx, argv[2])) {
10612
+ scr_exc_clear();
10613
+ return JS_NULL;
10614
+ }
10615
+ return isl_throw_pending(ctx);
10616
+ }
9830
10617
  ScrStr *href = scr_url_href(u);
9831
10618
  ScrStr *protocol = scr_url_protocol(u);
9832
10619
  ScrStr *pathname = scr_url_pathname(u);
9833
10620
  ScrStr *host = scr_url_host(u);
9834
10621
  ScrStr *hostname = scr_url_hostname(u);
9835
10622
  ScrStr *search = scr_url_search(u);
10623
+ ScrStr *origin = scr_url_origin(u);
10624
+ ScrStr *username = scr_url_username(u);
10625
+ ScrStr *password = scr_url_password(u);
10626
+ ScrStr *hash = scr_url_hash(u);
10627
+ ScrStr *port = scr_url_port(u);
9836
10628
  scr_url_release(u);
9837
10629
  JSValue arr = JS_NewArray(ctx);
9838
10630
  JS_SetPropertyUint32(ctx, arr, 0, JS_NewStringLen(ctx, href->data, href->len));
@@ -9841,12 +10633,22 @@ static JSValue isl_url_parse_host(JSContext *ctx, JSValueConst this_val,
9841
10633
  JS_SetPropertyUint32(ctx, arr, 3, JS_NewStringLen(ctx, host->data, host->len));
9842
10634
  JS_SetPropertyUint32(ctx, arr, 4, JS_NewStringLen(ctx, hostname->data, hostname->len));
9843
10635
  JS_SetPropertyUint32(ctx, arr, 5, JS_NewStringLen(ctx, search->data, search->len));
10636
+ JS_SetPropertyUint32(ctx, arr, 6, JS_NewStringLen(ctx, origin->data, origin->len));
10637
+ JS_SetPropertyUint32(ctx, arr, 7, JS_NewStringLen(ctx, username->data, username->len));
10638
+ JS_SetPropertyUint32(ctx, arr, 8, JS_NewStringLen(ctx, password->data, password->len));
10639
+ JS_SetPropertyUint32(ctx, arr, 9, JS_NewStringLen(ctx, hash->data, hash->len));
10640
+ JS_SetPropertyUint32(ctx, arr, 10, JS_NewStringLen(ctx, port->data, port->len));
9844
10641
  scr_str_release(href);
9845
10642
  scr_str_release(protocol);
9846
10643
  scr_str_release(pathname);
9847
10644
  scr_str_release(host);
9848
10645
  scr_str_release(hostname);
9849
10646
  scr_str_release(search);
10647
+ scr_str_release(origin);
10648
+ scr_str_release(username);
10649
+ scr_str_release(password);
10650
+ scr_str_release(hash);
10651
+ scr_str_release(port);
9850
10652
  return arr;
9851
10653
  }
9852
10654
 
@@ -9854,32 +10656,23 @@ static const char isl_url_src[] =
9854
10656
  "(function (parse) {\n"
9855
10657
  " 'use strict';\n"
9856
10658
  " const def = (o, n, v) => Object.defineProperty(o, n, { value: v, enumerable: true });\n"
10659
+ " const text = (v) => {\n"
10660
+ " if (typeof v === 'symbol') throw new TypeError('Cannot convert a Symbol value to a string');\n"
10661
+ " return `${v}`;\n"
10662
+ " };\n"
9857
10663
  " class URL {\n"
9858
- /* The (input, base) form supports RELATIVE resolution — the Emscripten
9859
- * loader's `new URL("x.wasm", import.meta.url)` — with RFC 3986
9860
- * dot-segment removal over the base's path. Inputs that carry their
9861
- * own scheme ignore the base (per spec); protocol-relative inputs
9862
- * keep a narrow fence. */
9863
10664
  " constructor(input, base) {\n"
9864
- " let s = String(input);\n"
9865
- " const hasScheme = /^[A-Za-z][A-Za-z0-9+.-]*:/;\n"
9866
- " if (base !== undefined && !hasScheme.test(s)) {\n"
9867
- " const b = String(base !== null && typeof base === 'object' && 'href' in base ? base.href : base);\n"
9868
- " const m = hasScheme.test(b) && b.match(/^([A-Za-z][A-Za-z0-9+.-]*:)(\\/\\/[^\\/?#]*)?([^?#]*)/);\n"
9869
- " if (!m) throw new TypeError('Invalid base URL');\n"
9870
- " if (s.startsWith('//')) {\n"
9871
- " throw new TypeError('protocol-relative URLs are not supported in the scriptc island yet');\n"
9872
- " }\n"
9873
- " let path = s.startsWith('/') ? s : (m[3] || '/').replace(/[^\\/]*$/, '') + s;\n"
9874
- " const out = [];\n"
9875
- " for (const seg of path.split('/')) {\n"
9876
- " if (seg === '.') continue;\n"
9877
- " if (seg === '..') { if (out.length > 1) out.pop(); continue; }\n"
9878
- " out.push(seg);\n"
9879
- " }\n"
9880
- " s = m[1] + (m[2] || '') + out.join('/');\n"
9881
- " }\n"
9882
- " const c = parse(s);\n"
10665
+ " if (arguments.length === 0) throw URL._missing();\n"
10666
+ " const s = text(input);\n"
10667
+ " const b = base === undefined ? undefined : text(base);\n"
10668
+ " this._init(parse(s, b));\n"
10669
+ " }\n"
10670
+ " static _missing() {\n"
10671
+ " const error = new TypeError('The \"url\" argument must be specified');\n"
10672
+ " error.code = 'ERR_MISSING_ARGS';\n"
10673
+ " return error;\n"
10674
+ " }\n"
10675
+ " _init(c) {\n"
9883
10676
  /* href and search are LIVE-COUPLED (the one WHATWG mutation loop the
9884
10677
  * a real CLI's API client drives: url.searchParams.set('teamId', …)
9885
10678
  * then fetch(url)): both live in writable slots, the search setter
@@ -9905,18 +10698,11 @@ static const char isl_url_src[] =
9905
10698
  " def(this, 'pathname', c[2]);\n"
9906
10699
  " def(this, 'host', c[3]);\n"
9907
10700
  " def(this, 'hostname', c[4]);\n"
9908
- " def(this, 'port', c[3].length > c[4].length ? c[3].slice(c[4].length + 1) : '');\n"
9909
- " const hashAt = c[0].indexOf('#');\n"
9910
- " def(this, 'hash', hashAt < 0 ? '' : c[0].slice(hashAt));\n"
9911
- " const cred = c[3] !== '' && c[0].startsWith(c[1] + '//')\n"
9912
- " ? c[0].slice(c[1].length + 2, c[0].indexOf(c[3], c[1].length + 2)) : '';\n"
9913
- " const at = cred.lastIndexOf('@');\n"
9914
- " const userinfo = at < 0 ? '' : cred.slice(0, at);\n"
9915
- " const colon = userinfo.indexOf(':');\n"
9916
- " def(this, 'username', colon < 0 ? userinfo : userinfo.slice(0, colon));\n"
9917
- " def(this, 'password', colon < 0 ? '' : userinfo.slice(colon + 1));\n"
9918
- " def(this, 'origin', (c[1] === 'http:' || c[1] === 'https:' || c[1] === 'ws:' || c[1] === 'wss:' || c[1] === 'ftp:')\n"
9919
- " ? c[1] + '//' + c[3] : 'null');\n"
10701
+ " def(this, 'origin', c[6]);\n"
10702
+ " def(this, 'username', c[7]);\n"
10703
+ " def(this, 'password', c[8]);\n"
10704
+ " def(this, 'hash', c[9]);\n"
10705
+ " def(this, 'port', c[10]);\n"
9920
10706
  " }\n"
9921
10707
  /* The search half of the live coupling: normalize the assigned
9922
10708
  * query, splice it into href between the pre-query part and the
@@ -9954,10 +10740,20 @@ static const char isl_url_src[] =
9954
10740
  " toString() { return this.href; }\n"
9955
10741
  " toJSON() { return this.href; }\n"
9956
10742
  " static canParse(input, base) {\n"
9957
- " try { new URL(input, base); return true; } catch (e) { return false; }\n"
10743
+ " if (arguments.length === 0) throw URL._missing();\n"
10744
+ " const s = text(input);\n"
10745
+ " const b = base === undefined ? undefined : text(base);\n"
10746
+ " return parse(s, b, true) !== null;\n"
9958
10747
  " }\n"
9959
10748
  " static parse(input, base) {\n"
9960
- " try { return new URL(input, base); } catch (e) { return null; }\n"
10749
+ " if (arguments.length === 0) throw URL._missing();\n"
10750
+ " const s = text(input);\n"
10751
+ " const b = base === undefined ? undefined : text(base);\n"
10752
+ " const c = parse(s, b, true);\n"
10753
+ " if (c === null) return null;\n"
10754
+ " const result = Object.create(URL.prototype);\n"
10755
+ " result._init(c);\n"
10756
+ " return result;\n"
9961
10757
  " }\n"
9962
10758
  " }\n"
9963
10759
  " globalThis.URL = URL;\n"
@@ -9976,7 +10772,7 @@ static void isl_install_url_class(void) {
9976
10772
  fprintf(stderr, "scriptc: island URL prelude failed to evaluate\n");
9977
10773
  abort(); /* fixed source; failing to parse is a build defect */
9978
10774
  }
9979
- JSValue parse = JS_NewCFunction(isl_ctx, isl_url_parse_host, "__scr_url_parse", 1);
10775
+ JSValue parse = JS_NewCFunction(isl_ctx, isl_url_parse_host, "__scr_url_parse", 3);
9980
10776
  JSValue r = JS_Call(isl_ctx, installer, JS_UNDEFINED, 1, &parse);
9981
10777
  JS_FreeValue(isl_ctx, parse);
9982
10778
  JS_FreeValue(isl_ctx, installer);