@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.
- package/dist/THIRD_PARTY_NOTICES +1 -1
- package/dist/bin/scriptc +0 -0
- package/dist/bin/scriptc.json +1 -1
- package/dist/lib/declarations/scriptc-node-fallback.d.ts +59 -4
- package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
- package/dist/lib/llvm/package.json +1 -1
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-x64/package.json +1 -1
- package/dist/lib/runtime-darwin-x64/runtime-pack.json +177 -177
- package/dist/lib/runtime-sources/package.json +1 -1
- package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
- package/dist/lib/runtime-sources/src/scr_async.c +12 -4
- package/dist/lib/runtime-sources/src/scr_async_dyn.c +118 -24
- package/dist/lib/runtime-sources/src/scr_bytes.c +226 -0
- package/dist/lib/runtime-sources/src/scr_bytes_io.c +52 -5
- package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
- package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +181 -43
- package/dist/lib/runtime-sources/src/scr_fetch.c +45 -1
- package/dist/lib/runtime-sources/src/scr_file_handle.c +31 -0
- package/dist/lib/runtime-sources/src/scr_island.c +1188 -392
- package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -9
- package/dist/lib/runtime-sources/src/scr_json.c +449 -52
- package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
- package/dist/lib/runtime-sources/src/scr_lib.c +816 -34
- package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
- package/dist/lib/runtime-sources/src/scr_regex.c +42 -5
- package/dist/lib/runtime-sources/src/scr_runtime.h +67 -8
- package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +12 -12
- package/dist/lib/runtime-sources/src/scr_url.c +34 -7
- package/dist/lib/runtime-sources/src/scr_web.c +129 -26
- package/package.json +1 -1
|
@@ -1259,8 +1259,10 @@ static void scr_fiber_finish(ScrFiber *self) {
|
|
|
1259
1259
|
* (moved from the fiber's cell into the promise). */
|
|
1260
1260
|
scr_promise_reject_from_cell(p, &self->exc);
|
|
1261
1261
|
}
|
|
1262
|
-
/*
|
|
1263
|
-
|
|
1262
|
+
/* A returned checked promise may still be resolving after its function
|
|
1263
|
+
* body finishes. Its resolver owns settlement and must not wake awaiters
|
|
1264
|
+
* until adoption completes (WASI continuations cannot park a C stack). */
|
|
1265
|
+
if (p->state != SCR_PROM_PENDING) scr_promise_settle_wake(p);
|
|
1264
1266
|
self->done = true;
|
|
1265
1267
|
}
|
|
1266
1268
|
|
|
@@ -2146,6 +2148,7 @@ void scr_fs_rename_thunk0(ScrClosure *cb, ScrError *err) {
|
|
|
2146
2148
|
* the emitted callback adapter. */
|
|
2147
2149
|
typedef struct ScrCryptoBytesOp {
|
|
2148
2150
|
ScrBytes *value;
|
|
2151
|
+
ScrError *error;
|
|
2149
2152
|
ScrClosure *cb;
|
|
2150
2153
|
ScrCryptoBytesFn fn;
|
|
2151
2154
|
struct ScrCryptoBytesOp *next;
|
|
@@ -2161,6 +2164,7 @@ static void scr_crypto_bytes_shutdown(void) {
|
|
|
2161
2164
|
ScrCryptoBytesOp *op = scr_crypto_bytes_head;
|
|
2162
2165
|
scr_crypto_bytes_head = op->next;
|
|
2163
2166
|
scr_bytes_release(op->value);
|
|
2167
|
+
scr_error_release(op->error);
|
|
2164
2168
|
scr_closure_release(op->cb);
|
|
2165
2169
|
free(op);
|
|
2166
2170
|
}
|
|
@@ -2178,16 +2182,18 @@ static bool scr_crypto_bytes_dispatch(void) {
|
|
|
2178
2182
|
scr_crypto_bytes_head = op->next;
|
|
2179
2183
|
if (scr_crypto_bytes_head == NULL) scr_crypto_bytes_tail = &scr_crypto_bytes_head;
|
|
2180
2184
|
scr_crypto_bytes_pending_count--;
|
|
2181
|
-
op->fn(op->cb, op->value); /* adapter consumes value */
|
|
2185
|
+
op->fn(op->cb, op->error, op->value); /* adapter consumes value */
|
|
2186
|
+
scr_error_release(op->error);
|
|
2182
2187
|
scr_closure_release(op->cb);
|
|
2183
2188
|
free(op);
|
|
2184
2189
|
return true;
|
|
2185
2190
|
}
|
|
2186
2191
|
|
|
2187
|
-
void scr_crypto_defer_bytes(ScrBytes *value, ScrClosure *cb, ScrCryptoBytesFn fn) {
|
|
2192
|
+
void scr_crypto_defer_bytes(ScrBytes *value, ScrError *error, ScrClosure *cb, ScrCryptoBytesFn fn) {
|
|
2188
2193
|
if (!scr_crypto_bytes_cleanup_registered) {
|
|
2189
2194
|
if (atexit(scr_crypto_bytes_shutdown) != 0) {
|
|
2190
2195
|
scr_bytes_release(value);
|
|
2196
|
+
scr_error_release(error);
|
|
2191
2197
|
scr_closure_release(cb);
|
|
2192
2198
|
scr_trap("scriptc: could not register crypto callback cleanup\n");
|
|
2193
2199
|
}
|
|
@@ -2196,10 +2202,12 @@ void scr_crypto_defer_bytes(ScrBytes *value, ScrClosure *cb, ScrCryptoBytesFn fn
|
|
|
2196
2202
|
ScrCryptoBytesOp *op = malloc(sizeof *op);
|
|
2197
2203
|
if (!op) {
|
|
2198
2204
|
scr_bytes_release(value);
|
|
2205
|
+
scr_error_release(error);
|
|
2199
2206
|
scr_closure_release(cb);
|
|
2200
2207
|
scr_trap("scriptc: out of memory\n");
|
|
2201
2208
|
}
|
|
2202
2209
|
op->value = value;
|
|
2210
|
+
op->error = error;
|
|
2203
2211
|
op->cb = cb;
|
|
2204
2212
|
op->fn = fn;
|
|
2205
2213
|
op->next = NULL;
|
|
@@ -421,6 +421,24 @@ typedef struct {
|
|
|
421
421
|
ScrDyn *onf, *onr, *onfin; /* owned or NULL */
|
|
422
422
|
} ScrDynThenPack;
|
|
423
423
|
|
|
424
|
+
typedef struct {
|
|
425
|
+
ScrPromise *src, *dst;
|
|
426
|
+
ScrDyn *result;
|
|
427
|
+
} ScrDynFinallyPack;
|
|
428
|
+
|
|
429
|
+
static void scr_dyn_finally_entry(ScrFiber *self, void *opaque) {
|
|
430
|
+
(void)self;
|
|
431
|
+
ScrDynFinallyPack *pack = opaque;
|
|
432
|
+
ScrDyn *result = scr_await_dyn(pack->result->v.promise);
|
|
433
|
+
if (scr_exc_pending()) scr_promise_reject_pending(pack->dst);
|
|
434
|
+
else scr_promise_adapt_copy(pack->dst, pack->src);
|
|
435
|
+
scr_dyn_release(result);
|
|
436
|
+
scr_dyn_release(pack->result);
|
|
437
|
+
scr_promise_release(pack->src);
|
|
438
|
+
scr_promise_release(pack->dst);
|
|
439
|
+
free(pack);
|
|
440
|
+
}
|
|
441
|
+
|
|
424
442
|
static void scr_dyn_then_entry(ScrFiber *self, void *ap) {
|
|
425
443
|
(void)self;
|
|
426
444
|
ScrDynThenPack *a = (ScrDynThenPack *)ap;
|
|
@@ -428,7 +446,7 @@ static void scr_dyn_then_entry(ScrFiber *self, void *ap) {
|
|
|
428
446
|
bool rejected = scr_exc_pending();
|
|
429
447
|
ScrCaught *c = rejected ? scr_exc_take() : NULL;
|
|
430
448
|
ScrDyn *handler = a->onfin ? a->onfin : (rejected ? a->onr : a->onf);
|
|
431
|
-
if (handler != NULL && handler
|
|
449
|
+
if (handler != NULL && scr_dyn_is_callable(handler)) {
|
|
432
450
|
ScrDyn *arg = NULL;
|
|
433
451
|
if (a->onfin == NULL) arg = rejected ? scr_caught_to_dyn(c) : scr_dyn_retain(v);
|
|
434
452
|
ScrDyn *r = scr_dyn_call(handler, arg ? &arg : NULL, arg ? 1 : 0, "handler");
|
|
@@ -437,30 +455,27 @@ static void scr_dyn_then_entry(ScrFiber *self, void *ap) {
|
|
|
437
455
|
/* The handler threw: dst rejects with that. */
|
|
438
456
|
scr_promise_reject_pending(a->dst);
|
|
439
457
|
} else if (a->onfin != NULL) {
|
|
440
|
-
/* finally
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
scr_promise_fulfill_ref(a->dst, scr_dyn_retain(v), scr_dyn_retain_v, scr_dyn_release_v, NULL);
|
|
458
|
+
/* finally returns PromiseResolve(result).then(valueThunk), which
|
|
459
|
+
* the outer reaction adopts. Even an undefined result takes those
|
|
460
|
+
* jobs before propagating the original fulfillment or rejection. */
|
|
461
|
+
if (r->kind != SCR_DYN_PROMISE) {
|
|
462
|
+
ScrPromise *result = scr_promise_new();
|
|
463
|
+
scr_promise_fulfill_ref(result, r, scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v);
|
|
464
|
+
r = scr_dyn_new_promise(result);
|
|
465
|
+
scr_promise_release(result);
|
|
449
466
|
}
|
|
467
|
+
ScrPromise *passthrough = scr_promise_new();
|
|
468
|
+
ScrDynFinallyPack *pack = malloc(sizeof *pack);
|
|
469
|
+
if (!pack) scr_ad_oom();
|
|
470
|
+
pack->src = scr_promise_retain(a->src);
|
|
471
|
+
pack->dst = scr_promise_retain(passthrough);
|
|
472
|
+
pack->result = r;
|
|
473
|
+
ScrPromise *waiter = scr_async_spawn_after(r->v.promise, scr_dyn_finally_entry, pack);
|
|
474
|
+
scr_promise_release(waiter);
|
|
475
|
+
scr_promise_resolve_dyn(a->dst, scr_dyn_new_promise(passthrough));
|
|
476
|
+
scr_promise_release(passthrough);
|
|
450
477
|
} else {
|
|
451
|
-
|
|
452
|
-
while (r != NULL && r->kind == SCR_DYN_PROMISE) {
|
|
453
|
-
ScrDyn *inner = scr_await_dyn(r->v.promise);
|
|
454
|
-
scr_dyn_release(r);
|
|
455
|
-
r = inner;
|
|
456
|
-
if (scr_exc_pending()) {
|
|
457
|
-
scr_promise_reject_pending(a->dst);
|
|
458
|
-
break;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
if (r != NULL) {
|
|
462
|
-
scr_promise_fulfill_ref(a->dst, r, scr_dyn_retain_v, scr_dyn_release_v, NULL);
|
|
463
|
-
}
|
|
478
|
+
scr_promise_resolve_dyn(a->dst, r);
|
|
464
479
|
}
|
|
465
480
|
} else if (rejected) {
|
|
466
481
|
scr_rethrow(c);
|
|
@@ -492,7 +507,7 @@ ScrDyn *scr_dyn_promise_then(ScrPromise *src, ScrDyn *onf, ScrDyn *onr, ScrDyn *
|
|
|
492
507
|
a->onr = onr ? scr_dyn_retain(onr) : NULL;
|
|
493
508
|
a->onfin = onfin ? scr_dyn_retain(onfin) : NULL;
|
|
494
509
|
ScrDyn *boxed = scr_dyn_new_promise(a->dst);
|
|
495
|
-
ScrPromise *waiter =
|
|
510
|
+
ScrPromise *waiter = scr_async_spawn_after(src, scr_dyn_then_entry, a);
|
|
496
511
|
scr_promise_release(waiter); /* the entry never rejects; nobody awaits it */
|
|
497
512
|
return boxed;
|
|
498
513
|
}
|
|
@@ -504,8 +519,10 @@ typedef struct {
|
|
|
504
519
|
static void scr_dyn_resolve_entry(ScrFiber *self, void *opaque) {
|
|
505
520
|
(void)self;
|
|
506
521
|
ScrDynResolvePack *pack = opaque;
|
|
522
|
+
#ifndef __wasi__
|
|
507
523
|
/* Promise resolution schedules a job before attaching its reaction. */
|
|
508
524
|
scr_await_hop();
|
|
525
|
+
#endif
|
|
509
526
|
ScrDyn *value = scr_await_dyn(pack->value->v.promise);
|
|
510
527
|
if (scr_exc_pending()) scr_promise_reject_pending(pack->destination);
|
|
511
528
|
else scr_promise_resolve_dyn(pack->destination, value);
|
|
@@ -514,6 +531,19 @@ static void scr_dyn_resolve_entry(ScrFiber *self, void *opaque) {
|
|
|
514
531
|
free(pack);
|
|
515
532
|
}
|
|
516
533
|
|
|
534
|
+
#ifdef __wasi__
|
|
535
|
+
static void scr_dyn_resolve_job(ScrClosure *closure) {
|
|
536
|
+
ScrPromise *destination = scr_box_get_ref(closure->caps[0]);
|
|
537
|
+
ScrDyn *value = scr_box_get_ref(closure->caps[1]);
|
|
538
|
+
ScrDynResolvePack *pack = malloc(sizeof *pack);
|
|
539
|
+
if (!pack) scr_ad_oom();
|
|
540
|
+
pack->destination = destination;
|
|
541
|
+
pack->value = value;
|
|
542
|
+
ScrPromise *waiter = scr_async_spawn_after(value->v.promise, scr_dyn_resolve_entry, pack);
|
|
543
|
+
scr_promise_release(waiter);
|
|
544
|
+
}
|
|
545
|
+
#endif
|
|
546
|
+
|
|
517
547
|
/* The destination is borrowed; value moves in. An async function may
|
|
518
548
|
* return a native promise hidden behind any/unknown without an explicit
|
|
519
549
|
* await, so its completion must use resolution rather than fulfillment. */
|
|
@@ -529,12 +559,21 @@ void scr_promise_resolve_dyn(ScrPromise *destination, ScrDyn *value) {
|
|
|
529
559
|
scr_dyn_release(value);
|
|
530
560
|
return;
|
|
531
561
|
}
|
|
562
|
+
#ifdef __wasi__
|
|
563
|
+
ScrClosure *job = scr_closure_new((void *)scr_dyn_resolve_job, 2);
|
|
564
|
+
job->caps[0] = scr_box_new_obj(scr_promise_retain_v, scr_promise_release_v, scr_promise_trace_v);
|
|
565
|
+
scr_box_set_ref(job->caps[0], scr_promise_retain(destination));
|
|
566
|
+
job->caps[1] = scr_box_new_obj(scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v);
|
|
567
|
+
scr_box_set_ref(job->caps[1], value);
|
|
568
|
+
scr_queue_microtask(job);
|
|
569
|
+
#else
|
|
532
570
|
ScrDynResolvePack *pack = malloc(sizeof *pack);
|
|
533
571
|
if (!pack) scr_ad_oom();
|
|
534
572
|
pack->destination = scr_promise_retain(destination);
|
|
535
573
|
pack->value = value;
|
|
536
574
|
ScrPromise *waiter = scr_async_spawn(scr_dyn_resolve_entry, pack);
|
|
537
575
|
scr_promise_release(waiter);
|
|
576
|
+
#endif
|
|
538
577
|
}
|
|
539
578
|
|
|
540
579
|
/* `await v` where v is a CHECKED-DYNAMIC value: a dyn promise adopts
|
|
@@ -548,6 +587,13 @@ ScrDyn *scr_await_dyn_value(ScrDyn *v) {
|
|
|
548
587
|
return scr_dyn_retain(v);
|
|
549
588
|
}
|
|
550
589
|
|
|
590
|
+
/* The WASI emitter has already suspended on the value's actual promise,
|
|
591
|
+
* or taken the non-promise microtask hop. Extraction must never suspend a
|
|
592
|
+
* runtime-authored C frame. */
|
|
593
|
+
ScrDyn *scr_await_dyn_value_settled(ScrDyn *value) {
|
|
594
|
+
return value->kind == SCR_DYN_PROMISE ? scr_await_dyn(value->v.promise) : scr_dyn_retain(value);
|
|
595
|
+
}
|
|
596
|
+
|
|
551
597
|
/* ── process warnings (emitWarning + the 'warning' event) ─────────────
|
|
552
598
|
* Gated with the rest of this TU (a deprecation-emitting unit's gate
|
|
553
599
|
* must imply the dynAsync link). Listeners are dyn functions; emission
|
|
@@ -834,6 +880,54 @@ ScrPromise *scr_dyn_promise_of(const ScrDyn *d) {
|
|
|
834
880
|
return d->kind == SCR_DYN_PROMISE ? d->v.promise : NULL;
|
|
835
881
|
}
|
|
836
882
|
|
|
883
|
+
static void scr_dyn_all_result(ScrPromise *destination, ScrPromise *source) {
|
|
884
|
+
ScrArr *values = scr_promise_payload_ref(source);
|
|
885
|
+
ScrDyn *result = scr_dyn_new_arr();
|
|
886
|
+
for (size_t i = 0; i < values->len; i++) scr_dyn_arr_push(result, scr_arr_get_ref(values, (double)i));
|
|
887
|
+
scr_arr_release(values);
|
|
888
|
+
scr_promise_fulfill_ref(destination, result, scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
ScrPromise *scr_dyn_promise_all(const ScrDyn *entries) {
|
|
892
|
+
ScrArr *promises = scr_arr_new_ref(scr_promise_retain_v, scr_promise_release_v, scr_promise_trace_v, entries->v.arr.len);
|
|
893
|
+
ScrArr *values = scr_arr_new_ref(scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v, entries->v.arr.len);
|
|
894
|
+
for (size_t i = 0; i < entries->v.arr.len; i++) {
|
|
895
|
+
ScrDyn *value = entries->v.arr.items[i];
|
|
896
|
+
ScrPromise *source;
|
|
897
|
+
if (value->kind == SCR_DYN_PROMISE) source = scr_promise_retain(value->v.promise);
|
|
898
|
+
else {
|
|
899
|
+
source = scr_promise_new();
|
|
900
|
+
if (value->kind == SCR_DYN_OBJ || value->kind == SCR_DYN_FUNC || value->kind == SCR_DYN_PROXY) {
|
|
901
|
+
ScrStr *key = scr_str_new("then", 4);
|
|
902
|
+
ScrDyn *then = value->kind == SCR_DYN_PROXY ? scr_dyn_proxy_get(value, key)
|
|
903
|
+
: value->kind == SCR_DYN_FUNC ? scr_dyn_fn_get(value, "then", 4) : scr_dyn_obj_read(value, "then", 4);
|
|
904
|
+
scr_str_release(key);
|
|
905
|
+
if (then && then->kind == SCR_DYN_FUNC) {
|
|
906
|
+
static const char message[] = "Promise.all over custom thenables is not supported yet";
|
|
907
|
+
scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
|
|
908
|
+
}
|
|
909
|
+
scr_dyn_release(then);
|
|
910
|
+
}
|
|
911
|
+
if (scr_exc_pending()) scr_promise_reject_pending(source);
|
|
912
|
+
else scr_promise_fulfill_ref(source, scr_dyn_retain(value), scr_dyn_retain_v, scr_dyn_release_v, scr_dyn_trace_v);
|
|
913
|
+
}
|
|
914
|
+
/* Each element contributes a reaction job, even an already fulfilled
|
|
915
|
+
* plain value. The aggregate preserves input order and Node's hops. */
|
|
916
|
+
scr_promise_mark_handled(source);
|
|
917
|
+
ScrDyn *reaction = scr_dyn_promise_then(source, NULL, NULL, NULL);
|
|
918
|
+
scr_arr_push_ref(promises, scr_promise_retain(reaction->v.promise));
|
|
919
|
+
scr_dyn_release(reaction);
|
|
920
|
+
scr_promise_release(source);
|
|
921
|
+
}
|
|
922
|
+
ScrPromise *all = scr_promise_all(promises, values, scr_promise_all_store_ref);
|
|
923
|
+
ScrPromise *result = scr_promise_new();
|
|
924
|
+
scr_promise_race_add(result, all, scr_dyn_all_result);
|
|
925
|
+
scr_promise_release(all);
|
|
926
|
+
scr_arr_release(values);
|
|
927
|
+
scr_arr_release(promises);
|
|
928
|
+
return result;
|
|
929
|
+
}
|
|
930
|
+
|
|
837
931
|
/* The checked native WebCrypto digest entry keeps promise and ArrayBuffer results native. */
|
|
838
932
|
static ScrDyn *scr_crypto_digest_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
|
|
839
933
|
(void)closure;
|
|
@@ -57,6 +57,21 @@ double scr_text_decoder_encoding(const ScrDyn *label) {
|
|
|
57
57
|
return -1;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
ScrStr *scr_text_decoder_name(double encoding) {
|
|
61
|
+
static const char *names[] = {
|
|
62
|
+
"ibm866", "iso-8859-2", "iso-8859-3", "iso-8859-4", "iso-8859-5",
|
|
63
|
+
"iso-8859-6", "iso-8859-7", "iso-8859-8", "iso-8859-10", "iso-8859-13",
|
|
64
|
+
"iso-8859-14", "iso-8859-15", "iso-8859-16", "koi8-r", "koi8-u",
|
|
65
|
+
"macintosh", "windows-874", "windows-1250", "windows-1251", "windows-1252",
|
|
66
|
+
"windows-1253", "windows-1254", "windows-1255", "windows-1256", "windows-1257",
|
|
67
|
+
"windows-1258", "x-mac-cyrillic", "x-user-defined", "utf-16le", "utf-16be",
|
|
68
|
+
"gb18030", "big5", "euc-jp", "iso-2022-jp", "shift_jis", "euc-kr",
|
|
69
|
+
"iso-8859-8-i", "gbk",
|
|
70
|
+
};
|
|
71
|
+
const char *name = encoding < 0 ? "utf-8" : names[(unsigned)encoding];
|
|
72
|
+
return scr_str_new(name, strlen(name));
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
#ifdef SCR_RC_AUDIT
|
|
61
76
|
static SCR_TL long scr_live_bytes = 0;
|
|
62
77
|
long scr_bytes_live_count(void) { return scr_live_bytes; }
|
|
@@ -1675,6 +1690,8 @@ static ScrStr *scr_td_iso_2022_jp_decode(const ScrBytes *b, bool fatal) {
|
|
|
1675
1690
|
|
|
1676
1691
|
ScrStr *scr_text_decode_legacy_options(const ScrBytes *b, double encoding_value, bool fatal, bool ignore_bom) {
|
|
1677
1692
|
unsigned encoding = (unsigned)encoding_value;
|
|
1693
|
+
if (encoding == 36) encoding = 7; /* ISO-8859-8-I */
|
|
1694
|
+
if (encoding == 37) encoding = SCR_TD_GB18030; /* GBK */
|
|
1678
1695
|
if (encoding < SCR_TD_SINGLE_COUNT) return scr_td_single_byte(b, encoding, fatal);
|
|
1679
1696
|
switch (encoding) {
|
|
1680
1697
|
case SCR_TD_X_USER_DEFINED: return scr_td_x_user_defined(b, fatal);
|
|
@@ -1712,6 +1729,7 @@ static size_t scr_td_utf8_tail(const uint8_t *bytes, size_t n) {
|
|
|
1712
1729
|
|
|
1713
1730
|
ScrStr *scr_text_decode_stream(ScrDyn *state, const ScrBytes *input,
|
|
1714
1731
|
double encoding, bool fatal, bool ignore_bom, bool stream) {
|
|
1732
|
+
if (encoding == 36) encoding = 7; /* ISO-8859-8-I is a single-byte decoder. */
|
|
1715
1733
|
ScrDyn *saved = scr_dyn_obj_read(state, "pending", 7);
|
|
1716
1734
|
size_t pending = saved->kind == SCR_DYN_BYTES ? saved->v.bytes->len : 0;
|
|
1717
1735
|
if (input->len > SIZE_MAX - pending) scr_bytes_oom();
|
|
@@ -1785,6 +1803,214 @@ static uint32_t scr_bytes_next_cp(const uint8_t *in, size_t *ip) {
|
|
|
1785
1803
|
return cp;
|
|
1786
1804
|
}
|
|
1787
1805
|
|
|
1806
|
+
/* encodeInto consumes complete Unicode scalars while counting UTF-16 units.
|
|
1807
|
+
* Borrow the destination so writes through a subarray retain their aliasing. */
|
|
1808
|
+
ScrDyn *scr_text_encode_into(const ScrDyn *source, const ScrDyn *destination) {
|
|
1809
|
+
if (source->kind != SCR_DYN_STR) {
|
|
1810
|
+
scr_dyn_arg_type_fail("src", "of type string", source);
|
|
1811
|
+
return NULL;
|
|
1812
|
+
}
|
|
1813
|
+
if (destination->kind != SCR_DYN_BYTES || destination->v.bytes->elem != SCR_BYTES_U8 || destination->v.bytes->is_data_view) {
|
|
1814
|
+
scr_dyn_arg_type_fail("dest", "an instance of Uint8Array", destination);
|
|
1815
|
+
return NULL;
|
|
1816
|
+
}
|
|
1817
|
+
const ScrStr *text = source->v.str;
|
|
1818
|
+
ScrBytes *dest = destination->v.bytes;
|
|
1819
|
+
size_t read = 0, written = 0;
|
|
1820
|
+
while (written < text->len) {
|
|
1821
|
+
size_t end = written;
|
|
1822
|
+
uint32_t cp = scr_bytes_next_cp((const uint8_t *)text->data, &end);
|
|
1823
|
+
if (end > dest->len) break;
|
|
1824
|
+
read += cp > 0xffff ? 2 : 1;
|
|
1825
|
+
written = end;
|
|
1826
|
+
}
|
|
1827
|
+
if (written) memcpy(dest->data, text->data, written);
|
|
1828
|
+
ScrDyn *result = scr_dyn_new_obj();
|
|
1829
|
+
scr_dyn_obj_set(result, "read", 4, scr_dyn_new_num((double)read));
|
|
1830
|
+
scr_dyn_obj_set(result, "written", 7, scr_dyn_new_num((double)written));
|
|
1831
|
+
return result;
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
static ScrBytes *scr_buffer_validation_input(const ScrDyn *input) {
|
|
1835
|
+
if ((input->kind == SCR_DYN_BYTES && !input->v.bytes->is_data_view) || scr_array_buffer_is(input)) {
|
|
1836
|
+
return scr_bytes_buffer_source(input);
|
|
1837
|
+
}
|
|
1838
|
+
scr_dyn_arg_type_fail("input", "an instance of ArrayBuffer, Buffer, or TypedArray", input);
|
|
1839
|
+
return NULL;
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
static bool scr_buffer_utf8_valid(const uint8_t *data, size_t len) {
|
|
1843
|
+
size_t i = 0;
|
|
1844
|
+
while (i < len) {
|
|
1845
|
+
unsigned byte = data[i++], count;
|
|
1846
|
+
unsigned low = 0x80, high = 0xbf;
|
|
1847
|
+
if (byte < 0x80) continue;
|
|
1848
|
+
if (byte >= 0xc2 && byte <= 0xdf) count = 1;
|
|
1849
|
+
else if (byte >= 0xe0 && byte <= 0xef) {
|
|
1850
|
+
count = 2;
|
|
1851
|
+
if (byte == 0xe0) low = 0xa0;
|
|
1852
|
+
if (byte == 0xed) high = 0x9f;
|
|
1853
|
+
} else if (byte >= 0xf0 && byte <= 0xf4) {
|
|
1854
|
+
count = 3;
|
|
1855
|
+
if (byte == 0xf0) low = 0x90;
|
|
1856
|
+
if (byte == 0xf4) high = 0x8f;
|
|
1857
|
+
} else return false;
|
|
1858
|
+
if (count > len - i || data[i] < low || data[i] > high) return false;
|
|
1859
|
+
i++;
|
|
1860
|
+
for (unsigned j = 1; j < count; j++, i++) if (data[i] < 0x80 || data[i] > 0xbf) return false;
|
|
1861
|
+
}
|
|
1862
|
+
return true;
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
bool scr_buffer_is_ascii(const ScrDyn *input) {
|
|
1866
|
+
ScrBytes *bytes = scr_buffer_validation_input(input);
|
|
1867
|
+
if (!bytes) return false;
|
|
1868
|
+
bool result = true;
|
|
1869
|
+
for (size_t i = 0; i < bytes->len; i++) if (bytes->data[i] > 0x7f) { result = false; break; }
|
|
1870
|
+
scr_bytes_release(bytes);
|
|
1871
|
+
return result;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
bool scr_buffer_is_utf8(const ScrDyn *input) {
|
|
1875
|
+
ScrBytes *bytes = scr_buffer_validation_input(input);
|
|
1876
|
+
if (!bytes) return false;
|
|
1877
|
+
bool result = scr_buffer_utf8_valid(bytes->data, bytes->len);
|
|
1878
|
+
scr_bytes_release(bytes);
|
|
1879
|
+
return result;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
/* Node's ICU wrapper recognizes Buffer encoding aliases. Empty inputs return
|
|
1883
|
+
* before resolving either encoding. The four actual converter families are
|
|
1884
|
+
* implemented here without adding an ICU dependency to a native binary. */
|
|
1885
|
+
enum { SCR_TC_UTF8, SCR_TC_ASCII, SCR_TC_LATIN1, SCR_TC_UTF16 };
|
|
1886
|
+
|
|
1887
|
+
static int scr_transcode_encoding(const ScrDyn *value) {
|
|
1888
|
+
if (value->kind == SCR_DYN_NULL || value->kind == SCR_DYN_UNDEF ||
|
|
1889
|
+
(value->kind == SCR_DYN_STR && value->v.str->len == 0)) return SCR_TC_UTF8;
|
|
1890
|
+
if (value->kind != SCR_DYN_STR) return -1;
|
|
1891
|
+
const ScrStr *name = value->v.str;
|
|
1892
|
+
static const struct { const char *name; int encoding; } aliases[] = {
|
|
1893
|
+
{"utf8", SCR_TC_UTF8}, {"utf-8", SCR_TC_UTF8}, {"ascii", SCR_TC_ASCII},
|
|
1894
|
+
{"latin1", SCR_TC_LATIN1}, {"binary", SCR_TC_LATIN1},
|
|
1895
|
+
{"utf16le", SCR_TC_UTF16}, {"utf-16le", SCR_TC_UTF16},
|
|
1896
|
+
{"ucs2", SCR_TC_UTF16}, {"ucs-2", SCR_TC_UTF16},
|
|
1897
|
+
};
|
|
1898
|
+
for (size_t i = 0; i < sizeof aliases / sizeof aliases[0]; i++) {
|
|
1899
|
+
if (strlen(aliases[i].name) != name->len) continue;
|
|
1900
|
+
bool match = true;
|
|
1901
|
+
for (size_t j = 0; j < name->len; j++) {
|
|
1902
|
+
unsigned char c = (unsigned char)name->data[j];
|
|
1903
|
+
if (c >= 'A' && c <= 'Z') c += 'a' - 'A';
|
|
1904
|
+
if (c != (unsigned char)aliases[i].name[j]) { match = false; break; }
|
|
1905
|
+
}
|
|
1906
|
+
if (match) return aliases[i].encoding;
|
|
1907
|
+
}
|
|
1908
|
+
return -1;
|
|
1909
|
+
}
|
|
1910
|
+
|
|
1911
|
+
static ScrBytes *scr_transcode_error(bool invalid_data) {
|
|
1912
|
+
const char *code = invalid_data ? "U_INVALID_CHAR_FOUND" : "U_ILLEGAL_ARGUMENT_ERROR";
|
|
1913
|
+
char message[100];
|
|
1914
|
+
int length = snprintf(message, sizeof message, "Unable to transcode Buffer [%s]", code);
|
|
1915
|
+
ScrStr *text = scr_str_new(message, (size_t)length);
|
|
1916
|
+
ScrError *error = scr_error_new(SCR_ERR_ERROR, text);
|
|
1917
|
+
scr_str_release(text);
|
|
1918
|
+
scr_error_set_code(error, code);
|
|
1919
|
+
scr_throw_obj(error, &scr_error_retain_v, &scr_error_release_v, scr_error_trace_arg());
|
|
1920
|
+
return NULL;
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
/* ICU's pinned substitute callback skips unmappable default-ignorable code
|
|
1924
|
+
* points. Mappable Latin-1 characters (including soft hyphen) still survive. */
|
|
1925
|
+
static bool scr_transcode_ignorable(uint32_t cp) {
|
|
1926
|
+
return cp == 0xad || cp == 0x34f || cp == 0x61c || cp == 0x115f || cp == 0x1160 ||
|
|
1927
|
+
(cp >= 0x17b4 && cp <= 0x17b5) || (cp >= 0x180b && cp <= 0x180f) ||
|
|
1928
|
+
(cp >= 0x200b && cp <= 0x200f) || (cp >= 0x202a && cp <= 0x202e) ||
|
|
1929
|
+
(cp >= 0x2060 && cp <= 0x206f) || cp == 0x3164 ||
|
|
1930
|
+
(cp >= 0xfe00 && cp <= 0xfe0f) || cp == 0xfeff || cp == 0xffa0 ||
|
|
1931
|
+
(cp >= 0xfff0 && cp <= 0xfff8) || (cp >= 0x1bca0 && cp <= 0x1bca3) ||
|
|
1932
|
+
(cp >= 0x1d173 && cp <= 0x1d17a) || (cp >= 0xe0000 && cp <= 0xe0fff);
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
static size_t scr_transcode_put(uint8_t *out, size_t index, uint32_t cp, int encoding) {
|
|
1936
|
+
if (encoding == SCR_TC_ASCII || encoding == SCR_TC_LATIN1) {
|
|
1937
|
+
unsigned limit = encoding == SCR_TC_ASCII ? 0x7f : 0xff;
|
|
1938
|
+
if (cp <= limit) out[index++] = (uint8_t)cp;
|
|
1939
|
+
else if (!scr_transcode_ignorable(cp)) out[index++] = '?';
|
|
1940
|
+
} else if (encoding == SCR_TC_UTF16) {
|
|
1941
|
+
if (cp > 0xffff) {
|
|
1942
|
+
uint32_t high = 0xd800 + ((cp - 0x10000) >> 10);
|
|
1943
|
+
out[index++] = (uint8_t)high;
|
|
1944
|
+
out[index++] = (uint8_t)(high >> 8);
|
|
1945
|
+
cp = 0xdc00 + ((cp - 0x10000) & 0x3ff);
|
|
1946
|
+
}
|
|
1947
|
+
out[index++] = (uint8_t)cp;
|
|
1948
|
+
out[index++] = (uint8_t)(cp >> 8);
|
|
1949
|
+
} else if (cp < 0x80) out[index++] = (uint8_t)cp;
|
|
1950
|
+
else if (cp < 0x800) {
|
|
1951
|
+
out[index++] = 0xc0 | (cp >> 6); out[index++] = 0x80 | (cp & 63);
|
|
1952
|
+
} else if (cp < 0x10000) {
|
|
1953
|
+
out[index++] = 0xe0 | (cp >> 12); out[index++] = 0x80 | ((cp >> 6) & 63); out[index++] = 0x80 | (cp & 63);
|
|
1954
|
+
} else {
|
|
1955
|
+
out[index++] = 0xf0 | (cp >> 18); out[index++] = 0x80 | ((cp >> 12) & 63);
|
|
1956
|
+
out[index++] = 0x80 | ((cp >> 6) & 63); out[index++] = 0x80 | (cp & 63);
|
|
1957
|
+
}
|
|
1958
|
+
return index;
|
|
1959
|
+
}
|
|
1960
|
+
|
|
1961
|
+
ScrBytes *scr_buffer_transcode(const ScrDyn *source, const ScrDyn *from, const ScrDyn *to) {
|
|
1962
|
+
if (source->kind != SCR_DYN_BYTES || source->v.bytes->elem != SCR_BYTES_U8 || source->v.bytes->is_data_view) {
|
|
1963
|
+
scr_dyn_arg_type_fail("source", "an instance of Buffer or Uint8Array", source);
|
|
1964
|
+
return NULL;
|
|
1965
|
+
}
|
|
1966
|
+
const ScrBytes *input = source->v.bytes;
|
|
1967
|
+
size_t len = input->len;
|
|
1968
|
+
if (!len) { ScrBytes *empty = scr_bytes_alloc(SCR_BYTES_U8, 0); empty->is_buffer = true; return empty; }
|
|
1969
|
+
int from_encoding = scr_transcode_encoding(from), to_encoding = scr_transcode_encoding(to);
|
|
1970
|
+
if (from_encoding < 0 || to_encoding < 0) return scr_transcode_error(false);
|
|
1971
|
+
if (len > (SIZE_MAX - 4) / 4) scr_bytes_oom();
|
|
1972
|
+
ScrBytes *result = scr_bytes_alloc(SCR_BYTES_U8, len * 4 + 4);
|
|
1973
|
+
result->is_buffer = true;
|
|
1974
|
+
size_t written = 0;
|
|
1975
|
+
if (from_encoding == SCR_TC_UTF8) {
|
|
1976
|
+
if (to_encoding == SCR_TC_UTF16 && !scr_buffer_utf8_valid(input->data, len)) {
|
|
1977
|
+
scr_bytes_release(result); return scr_transcode_error(true);
|
|
1978
|
+
}
|
|
1979
|
+
ScrStr *text = scr_str_from_utf8_lossy(input->data, len);
|
|
1980
|
+
for (size_t i = 0; i < text->len;) {
|
|
1981
|
+
uint32_t cp = scr_bytes_next_cp((const uint8_t *)text->data, &i);
|
|
1982
|
+
written = scr_transcode_put(result->data, written, cp, to_encoding);
|
|
1983
|
+
}
|
|
1984
|
+
scr_str_release(text);
|
|
1985
|
+
} else if (from_encoding == SCR_TC_UTF16) {
|
|
1986
|
+
size_t end = to_encoding == SCR_TC_UTF16 ? len : len & ~(size_t)1;
|
|
1987
|
+
if (to_encoding == SCR_TC_UTF8 && end == 0) { scr_bytes_release(result); return scr_transcode_error(true); }
|
|
1988
|
+
for (size_t i = 0; i < end;) {
|
|
1989
|
+
uint32_t cp = 0xfffd;
|
|
1990
|
+
bool invalid = false;
|
|
1991
|
+
if (i + 1 < end) {
|
|
1992
|
+
cp = input->data[i] | ((uint32_t)input->data[i + 1] << 8);
|
|
1993
|
+
i += 2;
|
|
1994
|
+
if (cp >= 0xd800 && cp <= 0xdbff) {
|
|
1995
|
+
uint32_t next = i + 1 < end ? input->data[i] | ((uint32_t)input->data[i + 1] << 8) : 0;
|
|
1996
|
+
if (next >= 0xdc00 && next <= 0xdfff) { cp = 0x10000 + ((cp - 0xd800) << 10) + next - 0xdc00; i += 2; }
|
|
1997
|
+
else { cp = 0xfffd; invalid = true; }
|
|
1998
|
+
} else if (cp >= 0xdc00 && cp <= 0xdfff) { cp = 0xfffd; invalid = true; }
|
|
1999
|
+
} else { i++; invalid = true; }
|
|
2000
|
+
if (invalid && to_encoding == SCR_TC_UTF8) { scr_bytes_release(result); return scr_transcode_error(true); }
|
|
2001
|
+
written = scr_transcode_put(result->data, written, cp, to_encoding);
|
|
2002
|
+
}
|
|
2003
|
+
} else {
|
|
2004
|
+
for (size_t i = 0; i < len; i++) {
|
|
2005
|
+
uint32_t cp = input->data[i];
|
|
2006
|
+
if (from_encoding == SCR_TC_ASCII && cp > 0x7f && to_encoding != SCR_TC_UTF16) cp = 0xfffd;
|
|
2007
|
+
written = scr_transcode_put(result->data, written, cp, to_encoding);
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
result->len = written;
|
|
2011
|
+
return result;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1788
2014
|
static bool scr_enc_is(const ScrStr *enc, const char *name) {
|
|
1789
2015
|
size_t n = strlen(name);
|
|
1790
2016
|
return enc->len == n && memcmp(enc->data, name, n) == 0;
|
|
@@ -469,21 +469,60 @@ static void scr_fs_cb_schedule(const ScrDyn *callback, ScrDyn *result, const Scr
|
|
|
469
469
|
|
|
470
470
|
static bool scr_fs_read_validate(const ScrDyn *, const ScrDyn *, const ScrDyn *, const ScrDyn *, const ScrDyn *);
|
|
471
471
|
static bool scr_fs_encoding_chk(const ScrDyn *);
|
|
472
|
+
static bool scr_fs_int_range_chk(const ScrDyn *, const char *, double, double, const char *);
|
|
473
|
+
static bool scr_fs_mode_chk(const ScrDyn *, const char *);
|
|
474
|
+
|
|
475
|
+
static ScrArr *scr_fs_cb_vectors(const ScrDyn *buffers) {
|
|
476
|
+
ScrDyn *snapshot = buffers->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(buffers)
|
|
477
|
+
? scr_dyn_typed_ref_materialize(buffers) : NULL;
|
|
478
|
+
const ScrDyn *array = snapshot ? snapshot : buffers;
|
|
479
|
+
if (array->kind != SCR_DYN_ARR) {
|
|
480
|
+
scr_dyn_arg_type_fail("buffers", "an instance of Array", buffers);
|
|
481
|
+
scr_dyn_release(snapshot);
|
|
482
|
+
return NULL;
|
|
483
|
+
}
|
|
484
|
+
ScrArr *out = scr_arr_new_ref(scr_bytes_retain_v, scr_bytes_release_v, NULL, array->v.arr.len);
|
|
485
|
+
for (size_t i = 0; i < array->v.arr.len; i++) {
|
|
486
|
+
const ScrDyn *buffer = array->v.arr.items[i];
|
|
487
|
+
if (!scr_dyn_bytes_is(buffer, SCR_BYTES_U8)) {
|
|
488
|
+
scr_dyn_arg_type_fail("buffers", "an Array of ArrayBufferView", buffers);
|
|
489
|
+
scr_arr_release(out);
|
|
490
|
+
scr_dyn_release(snapshot);
|
|
491
|
+
return NULL;
|
|
492
|
+
}
|
|
493
|
+
/* push_ref consumes the reference produced by unbox. */
|
|
494
|
+
scr_arr_push_ref(out, scr_dyn_bytes_unbox(buffer));
|
|
495
|
+
}
|
|
496
|
+
scr_dyn_release(snapshot);
|
|
497
|
+
return out;
|
|
498
|
+
}
|
|
472
499
|
|
|
473
500
|
static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc) {
|
|
474
501
|
const char *op = member->data;
|
|
502
|
+
bool vector = !strcmp(op, "readv") || !strcmp(op, "writev");
|
|
503
|
+
bool newControl = !strcmp(op, "fdatasync") || !strcmp(op, "fchmod") || !strcmp(op, "ftruncate");
|
|
504
|
+
if ((vector || newControl) && !scr_fs_int_range_chk(scr_fs_cb_arg(args, argc, 0), "fd", 0, 2147483647.0, ">= 0 && <= 2147483647")) return NULL;
|
|
505
|
+
ScrArr *vectors = vector ? scr_fs_cb_vectors(scr_fs_cb_arg(args, argc, 1)) : NULL;
|
|
506
|
+
if (vector && !vectors) return NULL;
|
|
475
507
|
bool fileCallback = !strcmp(op, "readFile") || !strcmp(op, "mkdtemp");
|
|
476
508
|
const ScrDyn *callback = argc >= (fileCallback ? 2u : 1u) ? args[argc - 1] : scr_dyn_undefined();
|
|
477
|
-
if (!scr_fs_cb_chk(callback, fileCallback ? "cb" : "callback")) return NULL;
|
|
509
|
+
if (!scr_fs_cb_chk(callback, fileCallback || vector ? "cb" : "callback")) { scr_arr_release(vectors); return NULL; }
|
|
478
510
|
size_t count = argc - 1;
|
|
479
511
|
#define ARG(index) scr_fs_cb_arg(args, count, index)
|
|
480
512
|
if (!strcmp(op, "readFile") && !scr_fs_encoding_chk(ARG(1))) return NULL;
|
|
481
513
|
if (!strcmp(op, "read") && count >= 4 && !scr_fs_read_validate(ARG(0), ARG(1), ARG(2), ARG(3), ARG(4))) return NULL;
|
|
482
|
-
bool descriptor =
|
|
514
|
+
bool descriptor = vector || newControl || !strcmp(op, "close") || !strcmp(op, "fstat") || !strcmp(op, "fsync") || !strcmp(op, "read") || !strcmp(op, "write");
|
|
483
515
|
ScrStr *path = descriptor ? NULL : scr_fs_cb_path(ARG(0), !strcmp(op, "mkdtemp") ? "prefix" : "path");
|
|
484
516
|
if (!descriptor && !path) return NULL;
|
|
485
517
|
double fd = descriptor ? scr_fs_cb_number(ARG(0), "fd", -1) : -1;
|
|
486
|
-
if (scr_exc_pending()) { scr_str_release(path); return NULL; }
|
|
518
|
+
if (scr_exc_pending()) { scr_str_release(path); scr_arr_release(vectors); return NULL; }
|
|
519
|
+
if (newControl && strcmp(op, "fdatasync")) {
|
|
520
|
+
const ScrDyn *value = ARG(1);
|
|
521
|
+
if (strcmp(op, "ftruncate") || value->kind != SCR_DYN_UNDEF) {
|
|
522
|
+
bool chmod = !strcmp(op, "fchmod");
|
|
523
|
+
if (chmod ? !scr_fs_mode_chk(value, "mode") : !scr_fs_int_range_chk(value, "len", -9007199254740991.0, 9007199254740991.0, ">= -9007199254740991 && <= 9007199254740991")) return NULL;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
487
526
|
ScrDyn *result = NULL;
|
|
488
527
|
const ScrDyn *buffer = NULL;
|
|
489
528
|
if (!strcmp(op, "readFile")) {
|
|
@@ -535,6 +574,14 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
|
|
535
574
|
else if (!strcmp(op, "fstat")) result = scr_fs_cb_stats(NULL, fd, ARG(1), false);
|
|
536
575
|
else if (!strcmp(op, "close")) scr_fs_close(fd);
|
|
537
576
|
else if (!strcmp(op, "fsync")) scr_fs_fsync(fd);
|
|
577
|
+
else if (!strcmp(op, "fdatasync")) scr_fs_fdatasync(fd);
|
|
578
|
+
else if (!strcmp(op, "fchmod")) scr_fs_fchmod(fd, ARG(1)->kind == SCR_DYN_STR ? (double)strtol(ARG(1)->v.str->data, NULL, 8) : ARG(1)->v.num);
|
|
579
|
+
else if (vector) {
|
|
580
|
+
double position = ARG(2)->kind == SCR_DYN_NUM ? ARG(2)->v.num : -1;
|
|
581
|
+
result = scr_dyn_new_num(!strcmp(op, "readv") ? scr_fs_readv_sync(fd, vectors, position) : scr_fs_writev_sync(fd, vectors, position));
|
|
582
|
+
scr_arr_release(vectors);
|
|
583
|
+
buffer = ARG(1);
|
|
584
|
+
}
|
|
538
585
|
else if (!strcmp(op, "open")) {
|
|
539
586
|
double opened = scr_fs_cb_open(path, ARG(1), scr_fs_cb_number(ARG(2), "mode", 0666), "r");
|
|
540
587
|
if (!scr_exc_pending()) result = scr_dyn_new_num(opened);
|
|
@@ -624,8 +671,8 @@ static ScrDyn *scr_fs_cb_invoke(ScrStr *member, ScrDyn *const *args, size_t argc
|
|
|
624
671
|
} else if (!strcmp(op, "truncate") || !strcmp(op, "ftruncate")) {
|
|
625
672
|
double length = scr_fs_cb_number(ARG(1), "len", 0);
|
|
626
673
|
if (!scr_exc_pending()) {
|
|
627
|
-
|
|
628
|
-
if (
|
|
674
|
+
if (descriptor) scr_fs_ftruncate(fd, length);
|
|
675
|
+
else if (truncate(path->data, (off_t)length) < 0) scr_fs_throw(errno, "truncate", path);
|
|
629
676
|
}
|
|
630
677
|
} else if (!strcmp(op, "readlink")) {
|
|
631
678
|
#ifndef _WIN32
|
|
@@ -9,7 +9,7 @@ void scr_crypto_random_bytes_async(double size, ScrClosure *cb, ScrCryptoBytesFn
|
|
|
9
9
|
scr_closure_release(cb);
|
|
10
10
|
return;
|
|
11
11
|
}
|
|
12
|
-
scr_crypto_defer_bytes(value, cb, fn);
|
|
12
|
+
scr_crypto_defer_bytes(value, NULL, cb, fn);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
void scr_crypto_pbkdf2_async(ScrBytes *password, ScrBytes *salt,
|
|
@@ -20,5 +20,25 @@ void scr_crypto_pbkdf2_async(ScrBytes *password, ScrBytes *salt,
|
|
|
20
20
|
scr_closure_release(cb);
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
-
scr_crypto_defer_bytes(value, cb, fn);
|
|
23
|
+
scr_crypto_defer_bytes(value, NULL, cb, fn);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void scr_crypto_hkdf_async(ScrStr *digest, ScrBytes *ikm, ScrBytes *salt,
|
|
27
|
+
ScrBytes *info, double keylen, ScrClosure *cb, ScrCryptoBytesFn fn) {
|
|
28
|
+
ScrBytes *value = scr_crypto_hkdf_bytes(digest, ikm, salt, info, keylen);
|
|
29
|
+
if (scr_exc_pending()) { scr_closure_release(cb); return; }
|
|
30
|
+
if (value->len == 0) {
|
|
31
|
+
scr_bytes_release(value);
|
|
32
|
+
ScrStr *message = scr_str_new("Deriving bits failed", 20);
|
|
33
|
+
ScrError *error = scr_error_new(SCR_ERR_ERROR, message);
|
|
34
|
+
scr_str_release(message);
|
|
35
|
+
scr_crypto_defer_bytes(NULL, error, cb, fn);
|
|
36
|
+
} else scr_crypto_defer_bytes(value, NULL, cb, fn);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void scr_crypto_scrypt_async(ScrBytes *password, ScrBytes *salt, double keylen,
|
|
40
|
+
ScrDyn *options, ScrClosure *cb, ScrCryptoBytesFn fn) {
|
|
41
|
+
ScrBytes *value = scr_crypto_scrypt(password, salt, keylen, options);
|
|
42
|
+
if (scr_exc_pending()) { scr_closure_release(cb); return; }
|
|
43
|
+
scr_crypto_defer_bytes(value, NULL, cb, fn);
|
|
24
44
|
}
|