quickjs 0.9.0 → 0.10.0

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.
@@ -64,10 +64,8 @@ typedef sig_t sighandler_t;
64
64
 
65
65
  #endif
66
66
 
67
- #if !defined(_WIN32)
68
- /* enable the os.Worker API. IT relies on POSIX threads */
67
+ /* enable the os.Worker API. It relies on POSIX threads */
69
68
  #define USE_WORKER
70
- #endif
71
69
 
72
70
  #ifdef USE_WORKER
73
71
  #include <pthread.h>
@@ -114,14 +112,22 @@ typedef struct {
114
112
  size_t sab_tab_len;
115
113
  } JSWorkerMessage;
116
114
 
115
+ typedef struct JSWaker {
116
+ #ifdef _WIN32
117
+ HANDLE handle;
118
+ #else
119
+ int read_fd;
120
+ int write_fd;
121
+ #endif
122
+ } JSWaker;
123
+
117
124
  typedef struct {
118
125
  int ref_count;
119
126
  #ifdef USE_WORKER
120
127
  pthread_mutex_t mutex;
121
128
  #endif
122
129
  struct list_head msg_queue; /* list of JSWorkerMessage.link */
123
- int read_fd;
124
- int write_fd;
130
+ JSWaker waker;
125
131
  } JSWorkerMessagePipe;
126
132
 
127
133
  typedef struct {
@@ -2138,82 +2144,81 @@ static void call_handler(JSContext *ctx, JSValueConst func)
2138
2144
  JS_FreeValue(ctx, ret);
2139
2145
  }
2140
2146
 
2141
- #if defined(_WIN32)
2147
+ #ifdef USE_WORKER
2142
2148
 
2143
- static int js_os_poll(JSContext *ctx)
2149
+ #ifdef _WIN32
2150
+
2151
+ static int js_waker_init(JSWaker *w)
2144
2152
  {
2145
- JSRuntime *rt = JS_GetRuntime(ctx);
2146
- JSThreadState *ts = JS_GetRuntimeOpaque(rt);
2147
- int min_delay, console_fd;
2148
- int64_t cur_time, delay;
2149
- JSOSRWHandler *rh;
2150
- struct list_head *el;
2153
+ w->handle = CreateEvent(NULL, TRUE, FALSE, NULL);
2154
+ return w->handle ? 0 : -1;
2155
+ }
2151
2156
 
2152
- /* XXX: handle signals if useful */
2157
+ static void js_waker_signal(JSWaker *w)
2158
+ {
2159
+ SetEvent(w->handle);
2160
+ }
2153
2161
 
2154
- if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers))
2155
- return -1; /* no more events */
2162
+ static void js_waker_clear(JSWaker *w)
2163
+ {
2164
+ ResetEvent(w->handle);
2165
+ }
2156
2166
 
2157
- /* XXX: only timers and basic console input are supported */
2158
- if (!list_empty(&ts->os_timers)) {
2159
- cur_time = get_time_ms();
2160
- min_delay = 10000;
2161
- list_for_each(el, &ts->os_timers) {
2162
- JSOSTimer *th = list_entry(el, JSOSTimer, link);
2163
- delay = th->timeout - cur_time;
2164
- if (delay <= 0) {
2165
- JSValue func;
2166
- /* the timer expired */
2167
- func = th->func;
2168
- th->func = JS_UNDEFINED;
2169
- free_timer(rt, th);
2170
- call_handler(ctx, func);
2171
- JS_FreeValue(ctx, func);
2172
- return 0;
2173
- } else if (delay < min_delay) {
2174
- min_delay = delay;
2175
- }
2176
- }
2177
- } else {
2178
- min_delay = -1;
2179
- }
2167
+ static void js_waker_close(JSWaker *w)
2168
+ {
2169
+ CloseHandle(w->handle);
2170
+ w->handle = INVALID_HANDLE_VALUE;
2171
+ }
2180
2172
 
2181
- console_fd = -1;
2182
- list_for_each(el, &ts->os_rw_handlers) {
2183
- rh = list_entry(el, JSOSRWHandler, link);
2184
- if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) {
2185
- console_fd = rh->fd;
2173
+ #else // !_WIN32
2174
+
2175
+ static int js_waker_init(JSWaker *w)
2176
+ {
2177
+ int fds[2];
2178
+
2179
+ if (pipe(fds) < 0)
2180
+ return -1;
2181
+ w->read_fd = fds[0];
2182
+ w->write_fd = fds[1];
2183
+ return 0;
2184
+ }
2185
+
2186
+ static void js_waker_signal(JSWaker *w)
2187
+ {
2188
+ int ret;
2189
+
2190
+ for(;;) {
2191
+ ret = write(w->write_fd, "", 1);
2192
+ if (ret == 1)
2193
+ break;
2194
+ if (ret < 0 && (errno != EAGAIN || errno != EINTR))
2186
2195
  break;
2187
- }
2188
2196
  }
2197
+ }
2189
2198
 
2190
- if (console_fd >= 0) {
2191
- DWORD ti, ret;
2192
- HANDLE handle;
2193
- if (min_delay == -1)
2194
- ti = INFINITE;
2195
- else
2196
- ti = min_delay;
2197
- handle = (HANDLE)_get_osfhandle(console_fd);
2198
- ret = WaitForSingleObject(handle, ti);
2199
- if (ret == WAIT_OBJECT_0) {
2200
- list_for_each(el, &ts->os_rw_handlers) {
2201
- rh = list_entry(el, JSOSRWHandler, link);
2202
- if (rh->fd == console_fd && !JS_IsNull(rh->rw_func[0])) {
2203
- call_handler(ctx, rh->rw_func[0]);
2204
- /* must stop because the list may have been modified */
2205
- break;
2206
- }
2207
- }
2208
- }
2209
- } else {
2210
- Sleep(min_delay);
2199
+ static void js_waker_clear(JSWaker *w)
2200
+ {
2201
+ uint8_t buf[16];
2202
+ int ret;
2203
+
2204
+ for(;;) {
2205
+ ret = read(w->read_fd, buf, sizeof(buf));
2206
+ if (ret >= 0)
2207
+ break;
2208
+ if (errno != EAGAIN && errno != EINTR)
2209
+ break;
2211
2210
  }
2212
- return 0;
2213
2211
  }
2214
- #else
2215
2212
 
2216
- #ifdef USE_WORKER
2213
+ static void js_waker_close(JSWaker *w)
2214
+ {
2215
+ close(w->read_fd);
2216
+ close(w->write_fd);
2217
+ w->read_fd = -1;
2218
+ w->write_fd = -1;
2219
+ }
2220
+
2221
+ #endif // _WIN32
2217
2222
 
2218
2223
  static void js_free_message(JSWorkerMessage *msg);
2219
2224
 
@@ -2235,17 +2240,8 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx,
2235
2240
  /* remove the message from the queue */
2236
2241
  list_del(&msg->link);
2237
2242
 
2238
- if (list_empty(&ps->msg_queue)) {
2239
- uint8_t buf[16];
2240
- int ret;
2241
- for(;;) {
2242
- ret = read(ps->read_fd, buf, sizeof(buf));
2243
- if (ret >= 0)
2244
- break;
2245
- if (errno != EAGAIN && errno != EINTR)
2246
- break;
2247
- }
2248
- }
2243
+ if (list_empty(&ps->msg_queue))
2244
+ js_waker_clear(&ps->waker);
2249
2245
 
2250
2246
  pthread_mutex_unlock(&ps->mutex);
2251
2247
 
@@ -2288,7 +2284,104 @@ static int handle_posted_message(JSRuntime *rt, JSContext *ctx,
2288
2284
  {
2289
2285
  return 0;
2290
2286
  }
2291
- #endif
2287
+ #endif /* !USE_WORKER */
2288
+
2289
+ #if defined(_WIN32)
2290
+
2291
+ static int js_os_poll(JSContext *ctx)
2292
+ {
2293
+ JSRuntime *rt = JS_GetRuntime(ctx);
2294
+ JSThreadState *ts = JS_GetRuntimeOpaque(rt);
2295
+ int min_delay, count;
2296
+ int64_t cur_time, delay;
2297
+ JSOSRWHandler *rh;
2298
+ struct list_head *el;
2299
+ HANDLE handles[MAXIMUM_WAIT_OBJECTS]; // 64
2300
+
2301
+ /* XXX: handle signals if useful */
2302
+
2303
+ if (list_empty(&ts->os_rw_handlers) && list_empty(&ts->os_timers) &&
2304
+ list_empty(&ts->port_list)) {
2305
+ return -1; /* no more events */
2306
+ }
2307
+
2308
+ if (!list_empty(&ts->os_timers)) {
2309
+ cur_time = get_time_ms();
2310
+ min_delay = 10000;
2311
+ list_for_each(el, &ts->os_timers) {
2312
+ JSOSTimer *th = list_entry(el, JSOSTimer, link);
2313
+ delay = th->timeout - cur_time;
2314
+ if (delay <= 0) {
2315
+ JSValue func;
2316
+ /* the timer expired */
2317
+ func = th->func;
2318
+ th->func = JS_UNDEFINED;
2319
+ free_timer(rt, th);
2320
+ call_handler(ctx, func);
2321
+ JS_FreeValue(ctx, func);
2322
+ return 0;
2323
+ } else if (delay < min_delay) {
2324
+ min_delay = delay;
2325
+ }
2326
+ }
2327
+ } else {
2328
+ min_delay = -1;
2329
+ }
2330
+
2331
+ count = 0;
2332
+ list_for_each(el, &ts->os_rw_handlers) {
2333
+ rh = list_entry(el, JSOSRWHandler, link);
2334
+ if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) {
2335
+ handles[count++] = (HANDLE)_get_osfhandle(rh->fd); // stdin
2336
+ if (count == (int)countof(handles))
2337
+ break;
2338
+ }
2339
+ }
2340
+
2341
+ list_for_each(el, &ts->port_list) {
2342
+ JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link);
2343
+ if (JS_IsNull(port->on_message_func))
2344
+ continue;
2345
+ handles[count++] = port->recv_pipe->waker.handle;
2346
+ if (count == (int)countof(handles))
2347
+ break;
2348
+ }
2349
+
2350
+ if (count > 0) {
2351
+ DWORD ret, timeout = INFINITE;
2352
+ if (min_delay != -1)
2353
+ timeout = min_delay;
2354
+ ret = WaitForMultipleObjects(count, handles, FALSE, timeout);
2355
+
2356
+ if (ret < count) {
2357
+ list_for_each(el, &ts->os_rw_handlers) {
2358
+ rh = list_entry(el, JSOSRWHandler, link);
2359
+ if (rh->fd == 0 && !JS_IsNull(rh->rw_func[0])) {
2360
+ call_handler(ctx, rh->rw_func[0]);
2361
+ /* must stop because the list may have been modified */
2362
+ goto done;
2363
+ }
2364
+ }
2365
+
2366
+ list_for_each(el, &ts->port_list) {
2367
+ JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link);
2368
+ if (!JS_IsNull(port->on_message_func)) {
2369
+ JSWorkerMessagePipe *ps = port->recv_pipe;
2370
+ if (ps->waker.handle == handles[ret]) {
2371
+ if (handle_posted_message(rt, ctx, port))
2372
+ goto done;
2373
+ }
2374
+ }
2375
+ }
2376
+ }
2377
+ } else {
2378
+ Sleep(min_delay);
2379
+ }
2380
+ done:
2381
+ return 0;
2382
+ }
2383
+
2384
+ #else
2292
2385
 
2293
2386
  static int js_os_poll(JSContext *ctx)
2294
2387
  {
@@ -2364,8 +2457,8 @@ static int js_os_poll(JSContext *ctx)
2364
2457
  JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link);
2365
2458
  if (!JS_IsNull(port->on_message_func)) {
2366
2459
  JSWorkerMessagePipe *ps = port->recv_pipe;
2367
- fd_max = max_int(fd_max, ps->read_fd);
2368
- FD_SET(ps->read_fd, &rfds);
2460
+ fd_max = max_int(fd_max, ps->waker.read_fd);
2461
+ FD_SET(ps->waker.read_fd, &rfds);
2369
2462
  }
2370
2463
  }
2371
2464
 
@@ -2391,14 +2484,14 @@ static int js_os_poll(JSContext *ctx)
2391
2484
  JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link);
2392
2485
  if (!JS_IsNull(port->on_message_func)) {
2393
2486
  JSWorkerMessagePipe *ps = port->recv_pipe;
2394
- if (FD_ISSET(ps->read_fd, &rfds)) {
2487
+ if (FD_ISSET(ps->waker.read_fd, &rfds)) {
2395
2488
  if (handle_posted_message(rt, ctx, port))
2396
2489
  goto done;
2397
2490
  }
2398
2491
  }
2399
2492
  }
2400
2493
  }
2401
- done:
2494
+ done:
2402
2495
  return 0;
2403
2496
  }
2404
2497
  #endif /* !_WIN32 */
@@ -3220,6 +3313,7 @@ typedef struct {
3220
3313
  char *filename; /* module filename */
3221
3314
  char *basename; /* module base name */
3222
3315
  JSWorkerMessagePipe *recv_pipe, *send_pipe;
3316
+ int strip_flags;
3223
3317
  } WorkerFuncArgs;
3224
3318
 
3225
3319
  typedef struct {
@@ -3268,22 +3362,17 @@ static void js_sab_dup(void *opaque, void *ptr)
3268
3362
  static JSWorkerMessagePipe *js_new_message_pipe(void)
3269
3363
  {
3270
3364
  JSWorkerMessagePipe *ps;
3271
- int pipe_fds[2];
3272
-
3273
- if (pipe(pipe_fds) < 0)
3274
- return NULL;
3275
3365
 
3276
3366
  ps = malloc(sizeof(*ps));
3277
- if (!ps) {
3278
- close(pipe_fds[0]);
3279
- close(pipe_fds[1]);
3367
+ if (!ps)
3368
+ return NULL;
3369
+ if (js_waker_init(&ps->waker)) {
3370
+ free(ps);
3280
3371
  return NULL;
3281
3372
  }
3282
3373
  ps->ref_count = 1;
3283
3374
  init_list_head(&ps->msg_queue);
3284
3375
  pthread_mutex_init(&ps->mutex, NULL);
3285
- ps->read_fd = pipe_fds[0];
3286
- ps->write_fd = pipe_fds[1];
3287
3376
  return ps;
3288
3377
  }
3289
3378
 
@@ -3322,8 +3411,7 @@ static void js_free_message_pipe(JSWorkerMessagePipe *ps)
3322
3411
  js_free_message(msg);
3323
3412
  }
3324
3413
  pthread_mutex_destroy(&ps->mutex);
3325
- close(ps->read_fd);
3326
- close(ps->write_fd);
3414
+ js_waker_close(&ps->waker);
3327
3415
  free(ps);
3328
3416
  }
3329
3417
  }
@@ -3367,6 +3455,7 @@ static void *worker_func(void *opaque)
3367
3455
  fprintf(stderr, "JS_NewRuntime failure");
3368
3456
  exit(1);
3369
3457
  }
3458
+ JS_SetStripInfo(rt, args->strip_flags);
3370
3459
  js_std_init_handlers(rt);
3371
3460
 
3372
3461
  JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);
@@ -3484,6 +3573,8 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target,
3484
3573
  if (!args->send_pipe)
3485
3574
  goto oom_fail;
3486
3575
 
3576
+ args->strip_flags = JS_GetStripInfo(rt);
3577
+
3487
3578
  obj = js_worker_ctor_internal(ctx, new_target,
3488
3579
  args->send_pipe, args->recv_pipe);
3489
3580
  if (JS_IsException(obj))
@@ -3568,17 +3659,8 @@ static JSValue js_worker_postMessage(JSContext *ctx, JSValueConst this_val,
3568
3659
  ps = worker->send_pipe;
3569
3660
  pthread_mutex_lock(&ps->mutex);
3570
3661
  /* indicate that data is present */
3571
- if (list_empty(&ps->msg_queue)) {
3572
- uint8_t ch = '\0';
3573
- int ret;
3574
- for(;;) {
3575
- ret = write(ps->write_fd, &ch, 1);
3576
- if (ret == 1)
3577
- break;
3578
- if (ret < 0 && (errno != EAGAIN || errno != EINTR))
3579
- break;
3580
- }
3581
- }
3662
+ if (list_empty(&ps->msg_queue))
3663
+ js_waker_signal(&ps->waker);
3582
3664
  list_add_tail(&msg->link, &ps->msg_queue);
3583
3665
  pthread_mutex_unlock(&ps->mutex);
3584
3666
  return JS_UNDEFINED;
@@ -3825,9 +3907,18 @@ static JSValue js_print(JSContext *ctx, JSValueConst this_val,
3825
3907
  return JS_UNDEFINED;
3826
3908
  }
3827
3909
 
3910
+ static JSValue js_console_log(JSContext *ctx, JSValueConst this_val,
3911
+ int argc, JSValueConst *argv)
3912
+ {
3913
+ JSValue ret;
3914
+ ret = js_print(ctx, this_val, argc, argv);
3915
+ fflush(stdout);
3916
+ return ret;
3917
+ }
3918
+
3828
3919
  void js_std_add_helpers(JSContext *ctx, int argc, char **argv)
3829
3920
  {
3830
- JSValue global_obj, console, args;
3921
+ JSValue global_obj, console, args, performance;
3831
3922
  int i;
3832
3923
 
3833
3924
  /* XXX: should these global definitions be enumerable? */
@@ -3835,9 +3926,14 @@ void js_std_add_helpers(JSContext *ctx, int argc, char **argv)
3835
3926
 
3836
3927
  console = JS_NewObject(ctx);
3837
3928
  JS_SetPropertyStr(ctx, console, "log",
3838
- JS_NewCFunction(ctx, js_print, "log", 1));
3929
+ JS_NewCFunction(ctx, js_console_log, "log", 1));
3839
3930
  JS_SetPropertyStr(ctx, global_obj, "console", console);
3840
3931
 
3932
+ performance = JS_NewObject(ctx);
3933
+ JS_SetPropertyStr(ctx, performance, "now",
3934
+ JS_NewCFunction(ctx, js_os_now, "now", 0));
3935
+ JS_SetPropertyStr(ctx, global_obj, "performance", performance);
3936
+
3841
3937
  /* same methods as the mozilla JS shell */
3842
3938
  if (argc >= 0) {
3843
3939
  args = JS_NewArray(ctx);
@@ -3961,6 +4057,7 @@ void js_std_promise_rejection_tracker(JSContext *ctx, JSValueConst promise,
3961
4057
  if (!is_handled) {
3962
4058
  fprintf(stderr, "Possibly unhandled promise rejection: ");
3963
4059
  js_std_dump_error1(ctx, reason);
4060
+ exit(1);
3964
4061
  }
3965
4062
  }
3966
4063
 
@@ -110,6 +110,7 @@ DEF( return, 1, 1, 0, none)
110
110
  DEF( return_undef, 1, 0, 0, none)
111
111
  DEF(check_ctor_return, 1, 1, 2, none)
112
112
  DEF( check_ctor, 1, 0, 0, none)
113
+ DEF( init_ctor, 1, 0, 1, none)
113
114
  DEF( check_brand, 1, 2, 2, none) /* this_obj func -> this_obj func */
114
115
  DEF( add_brand, 1, 2, 0, none) /* this_obj home_obj -> */
115
116
  DEF( return_async, 1, 1, 0, none)
@@ -195,7 +196,6 @@ DEF( with_put_var, 10, 2, 1, atom_label_u8) /* must be in the same order a
195
196
  DEF(with_delete_var, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
196
197
  DEF( with_make_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
197
198
  DEF( with_get_ref, 10, 1, 0, atom_label_u8) /* must be in the same order as scope_xxx */
198
- DEF(with_get_ref_undef, 10, 1, 0, atom_label_u8)
199
199
 
200
200
  DEF( make_loc_ref, 7, 0, 2, atom_u16)
201
201
  DEF( make_arg_ref, 7, 0, 2, atom_u16)
@@ -207,8 +207,9 @@ DEF( for_of_start, 1, 1, 3, none)
207
207
  DEF(for_await_of_start, 1, 1, 3, none)
208
208
  DEF( for_in_next, 1, 1, 3, none)
209
209
  DEF( for_of_next, 2, 3, 5, u8)
210
+ DEF(for_await_of_next, 1, 3, 4, none) /* iter next catch_offset -> iter next catch_offset obj */
210
211
  DEF(iterator_check_object, 1, 1, 1, none)
211
- DEF(iterator_get_value_done, 1, 1, 2, none)
212
+ DEF(iterator_get_value_done, 1, 2, 3, none) /* catch_offset obj -> catch_offset value done */
212
213
  DEF( iterator_close, 1, 3, 0, none)
213
214
  DEF( iterator_next, 1, 4, 4, none)
214
215
  DEF( iterator_call, 2, 4, 5, u8)