mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-01 07:33:12 +08:00
Merge remote-tracking branch 'origin/ni/i4-deferred' into tmp-merge
This commit is contained in:
@@ -499,13 +499,27 @@ static const ScrNodeBridgeHost ni_host = {
|
||||
&scr_ni_host_shared_tdz,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint32_t event, listener;
|
||||
const char *name;
|
||||
int arg;
|
||||
} NiEmit;
|
||||
|
||||
static void ni_emit_job(void *p) {
|
||||
NiEmit *e = p;
|
||||
ni_bridge->emit(e->event, e->listener, e->name, e->arg);
|
||||
}
|
||||
|
||||
/* An island listener of a process event, on Node's stack (an exit listener
|
||||
* runs from the runtime's exit sequence, on whatever stack called it). */
|
||||
void scr_node_island_emit(uint32_t event, uint32_t listener, ScrStr *name, int arg) {
|
||||
if (ni_bridge == NULL) return;
|
||||
char *n = malloc(name->len + 1);
|
||||
if (n == NULL) ni_oom();
|
||||
memcpy(n, name->data, name->len);
|
||||
n[name->len] = '\0';
|
||||
ni_bridge->emit(event, listener, n, arg);
|
||||
NiEmit e = {event, listener, n, arg};
|
||||
ni_on_node_stack(ni_emit_job, &e);
|
||||
free(n);
|
||||
}
|
||||
|
||||
@@ -548,7 +562,75 @@ static int ni_run_loop(int continue_turn) {
|
||||
return a.code;
|
||||
}
|
||||
|
||||
/* The bridge as the hosted loop sees it: Node's loop runs on Node's stack. */
|
||||
/* The bridge as the hosted loop sees it. Every entry that runs JavaScript
|
||||
* (scheduling a tick, timer or immediate goes through the bootstrap's
|
||||
* helpers; a checkpoint drains queues; Node's loop) runs on Node's stack,
|
||||
* below the mark when it comes from an async fiber that a host callback
|
||||
* resumed, like every other entry: V8 scans only Node's stack, so no frame
|
||||
* of Node may live on a fiber's stack or the main thread's. */
|
||||
typedef struct {
|
||||
int op;
|
||||
uint32_t a, b;
|
||||
double d0, d1;
|
||||
int i0;
|
||||
uint32_t result;
|
||||
} NiHosted;
|
||||
|
||||
enum {
|
||||
NI_H_MICROTASK,
|
||||
NI_H_TICK,
|
||||
NI_H_TIMER,
|
||||
NI_H_TIMER_CLEAR,
|
||||
NI_H_TIMER_REF,
|
||||
NI_H_TIMER_REFRESH,
|
||||
NI_H_IMMEDIATE,
|
||||
NI_H_IMMEDIATE_CLEAR,
|
||||
NI_H_IMMEDIATE_REF,
|
||||
NI_H_CHECKPOINT,
|
||||
};
|
||||
|
||||
static void ni_hosted_job(void *p) {
|
||||
NiHosted *h = p;
|
||||
switch (h->op) {
|
||||
case NI_H_MICROTASK: ni_bridge->microtask(h->a); break;
|
||||
case NI_H_TICK: ni_bridge->tick(h->a); break;
|
||||
case NI_H_TIMER: h->result = ni_bridge->timer(h->d0, h->d1, h->i0, h->a); break;
|
||||
case NI_H_TIMER_CLEAR: ni_bridge->timer_clear(h->a); break;
|
||||
case NI_H_TIMER_REF: ni_bridge->timer_ref(h->a, h->i0); break;
|
||||
case NI_H_TIMER_REFRESH: ni_bridge->timer_refresh(h->a); break;
|
||||
case NI_H_IMMEDIATE: h->result = ni_bridge->immediate(h->i0, h->a); break;
|
||||
case NI_H_IMMEDIATE_CLEAR: ni_bridge->immediate_clear(h->a); break;
|
||||
case NI_H_IMMEDIATE_REF: ni_bridge->immediate_ref(h->a, h->i0); break;
|
||||
case NI_H_CHECKPOINT: ni_bridge->checkpoint(h->i0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t ni_hosted_run(int op, uint32_t a, double d0, double d1, int i0) {
|
||||
NiHosted h = {op, a, 0, d0, d1, i0, 0};
|
||||
ni_on_node_stack(ni_hosted_job, &h);
|
||||
return h.result;
|
||||
}
|
||||
|
||||
static void ni_h_microtask(uint32_t token) { ni_hosted_run(NI_H_MICROTASK, token, 0, 0, 0); }
|
||||
static void ni_h_tick(uint32_t token) { ni_hosted_run(NI_H_TICK, token, 0, 0, 0); }
|
||||
static uint32_t ni_h_timer(double delay, double repeat, int ref, uint32_t token) {
|
||||
return ni_hosted_run(NI_H_TIMER, token, delay, repeat, ref);
|
||||
}
|
||||
static void ni_h_timer_clear(uint32_t h) { ni_hosted_run(NI_H_TIMER_CLEAR, h, 0, 0, 0); }
|
||||
static void ni_h_timer_ref(uint32_t h, int ref) { ni_hosted_run(NI_H_TIMER_REF, h, 0, 0, ref); }
|
||||
static void ni_h_timer_refresh(uint32_t h) { ni_hosted_run(NI_H_TIMER_REFRESH, h, 0, 0, 0); }
|
||||
static uint32_t ni_h_immediate(int ref, uint32_t token) {
|
||||
return ni_hosted_run(NI_H_IMMEDIATE, token, 0, 0, ref);
|
||||
}
|
||||
static void ni_h_immediate_clear(uint32_t h) { ni_hosted_run(NI_H_IMMEDIATE_CLEAR, h, 0, 0, 0); }
|
||||
static void ni_h_immediate_ref(uint32_t h, int ref) {
|
||||
ni_hosted_run(NI_H_IMMEDIATE_REF, h, 0, 0, ref);
|
||||
}
|
||||
static void ni_h_checkpoint(int microtasks_first) {
|
||||
ni_hosted_run(NI_H_CHECKPOINT, 0, 0, 0, microtasks_first);
|
||||
}
|
||||
|
||||
static ScrNodeBridge ni_hosted;
|
||||
|
||||
/* ── loading Node ─────────────────────────────────────────────────────── */
|
||||
@@ -622,6 +704,16 @@ static void ni_start(void) {
|
||||
scr_atexit(ni_stop_atexit);
|
||||
ni_hosted = *bridge;
|
||||
ni_hosted.run_loop = &ni_run_loop;
|
||||
ni_hosted.microtask = &ni_h_microtask;
|
||||
ni_hosted.tick = &ni_h_tick;
|
||||
ni_hosted.timer = &ni_h_timer;
|
||||
ni_hosted.timer_clear = &ni_h_timer_clear;
|
||||
ni_hosted.timer_ref = &ni_h_timer_ref;
|
||||
ni_hosted.timer_refresh = &ni_h_timer_refresh;
|
||||
ni_hosted.immediate = &ni_h_immediate;
|
||||
ni_hosted.immediate_clear = &ni_h_immediate_clear;
|
||||
ni_hosted.immediate_ref = &ni_h_immediate_ref;
|
||||
ni_hosted.checkpoint = &ni_h_checkpoint;
|
||||
scr_loop_host(&ni_hosted, since);
|
||||
/* NI-7: deferred island modules evaluate now, before the operation that
|
||||
* needed Node, in their import order. */
|
||||
|
||||
Reference in New Issue
Block a user