Skip to content

Commit 0039a63

Browse files
committed
QJS patches for GPAC 2.5-dev
1 parent b06ad35 commit 0039a63

File tree

6 files changed

+160
-71
lines changed

6 files changed

+160
-71
lines changed

GPAC_README.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# QuickJS in GPAC
2-
Base version is quickjs-2021-03-27 :
3-
https://github.com/bellard/quickjs/commit/b5e62895c619d4ffc75c9d822c8d85f1ece77e5b
2+
Base version is quickjs-2025-10-15 :
3+
https://github.com/bellard/quickjs/commit/eb2c89087def1829ed99630cb14b549d7a98408c
44

55
## Modifications to QuickJS
66
- define CONFIG_VERSION in QuickJS.c
77
- patched for MSVC compil, based on https://github.com/horhof/quickjs/compare/master...samhocevar:task/msvc-support
88
- do not define CONFIG_STACK_CHECK (stack checking breaks multithread support)
9-
- patched for JS_GetOpaque_Nocheck (get opaque data without class_id check, needed in some places in gpac due to original SpiderMonkey design)
109
- patched for exporting JS_AtomIsArrayIndex and JS_IsArrayBuffer
10+
- patched for switch classID on object (for webGL named textures in GPAC)
1111

1212
## Modifications to QuickJS-libc ('os' and 'std' modules)
1313
- moved from pthread to GF_Thread in 'os' module
@@ -16,5 +16,3 @@ Base version is quickjs-2021-03-27 :
1616
- patch js_std_loop to not run forever for main thread
1717
- added MSVC support for most 'os' functions (most importantly exec, waitpid and kill)
1818
- use gpac module loader
19-
- pacthes for sighandler_t and environ
20-

cutils.h

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ static inline int clz32(unsigned int a)
144144
#if defined(_MSC_VER)
145145
unsigned long ret = 0;
146146
_BitScanReverse(&ret, a);
147-
return (int)ret;
147+
return 31 - ret;
148148
#else
149149
return __builtin_clz(a);
150150
#endif
@@ -462,17 +462,50 @@ static inline double uint64_as_float64(uint64_t u64)
462462
return u.d;
463463
}
464464

465+
466+
//taken from QuickJS-NG, original function is not protable due to 0x1p1008
467+
#if defined(_MSC_VER) && !defined(__clang__)
468+
#include <math.h>
469+
#define INF INFINITY
470+
#define NEG_INF -INFINITY
471+
472+
static inline double fromfp16(uint16_t v) {
473+
double d, s;
474+
int e;
475+
if ((v & 0x7C00) == 0x7C00) {
476+
d = (v & 0x3FF) ? NAN : INFINITY;
477+
}
478+
else {
479+
d = (v & 0x3FF) / 1024.;
480+
e = (v & 0x7C00) >> 10;
481+
if (e == 0) {
482+
e = -14;
483+
}
484+
else {
485+
d += 1;
486+
e -= 15;
487+
}
488+
d = scalbn(d, e);
489+
}
490+
s = (v & 0x8000) ? -1.0 : 1.0;
491+
return d * s;
492+
}
493+
#else
494+
465495
static inline double fromfp16(uint16_t v)
466496
{
467-
double d;
468-
uint32_t v1;
469-
v1 = v & 0x7fff;
470-
if (unlikely(v1 >= 0x7c00))
471-
v1 += 0x1f8000; /* NaN or infinity */
472-
d = uint64_as_float64(((uint64_t)(v >> 15) << 63) | ((uint64_t)v1 << (52 - 10)));
473-
return d * 0x1p1008;
497+
double d;
498+
uint32_t v1;
499+
v1 = v & 0x7fff;
500+
if (unlikely(v1 >= 0x7c00))
501+
v1 += 0x1f8000; /* NaN or infinity */
502+
d = uint64_as_float64(((uint64_t)(v >> 15) << 63) | ((uint64_t)v1 << (52 - 10)));
503+
return d * 0x1p1008;
474504
}
475505

506+
#endif
507+
508+
476509
static inline uint16_t tofp16(double d)
477510
{
478511
uint64_t a, addend;

dtoa.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
#include <string.h>
2929
#include <assert.h>
3030
#include <ctype.h>
31+
#if !defined(_MSC_VER)
3132
#include <sys/time.h>
33+
#endif
3234
#include <math.h>
3335
#include <setjmp.h>
3436

quickjs-libc.c

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ typedef SSIZE_T ssize_t;
124124
/* enable the os.Worker API. It relies on POSIX threads */
125125
#define USE_WORKER
126126

127+
#endif
127128

128129
#ifdef USE_WORKER
129130
#include <gpac/thread.h>
@@ -678,8 +679,6 @@ int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val,
678679
}
679680

680681

681-
#ifndef GPAC_DISABLE_QJS_LIBC
682-
683682
static int json_module_init(JSContext *ctx, JSModuleDef *m)
684683
{
685684
JSValue val;
@@ -702,6 +701,9 @@ JSModuleDef *create_json_module(JSContext *ctx, const char *module_name, JSValue
702701
return m;
703702
}
704703

704+
#ifndef GPAC_DISABLE_QJS_LIBC
705+
706+
705707
/* in order to conform with the specification, only the keys should be
706708
tested and not the associated values. */
707709
int js_module_check_attributes(JSContext *ctx, void *opaque,
@@ -733,6 +735,7 @@ int js_module_check_attributes(JSContext *ctx, void *opaque,
733735
JS_FreePropertyEnum(ctx, tab, len);
734736
return ret;
735737
}
738+
#endif
736739

737740
/* return > 0 if the attributes indicate a JSON module */
738741
int js_module_test_json(JSContext *ctx, JSValueConst attributes)
@@ -763,6 +766,8 @@ int js_module_test_json(JSContext *ctx, JSValueConst attributes)
763766
return res;
764767
}
765768

769+
#ifndef GPAC_DISABLE_QJS_LIBC
770+
766771
#ifndef GPAC_HAS_QJS
767772

768773
JSModuleDef *js_module_loader(JSContext *ctx,
@@ -2225,8 +2230,13 @@ static int64_t get_time_ms(void)
22252230
clock_gettime(CLOCK_MONOTONIC, &ts);
22262231
return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000);
22272232
}
2233+
static int64_t get_time_ns(void)
2234+
{
2235+
struct timespec ts;
2236+
clock_gettime(CLOCK_MONOTONIC, &ts);
2237+
return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
2238+
}
22282239

2229-
/* CHECKME
22302240
#elif defined(_WIN32) && defined(_MSC_VER)
22312241
//more portable, but does not work if the date is updated
22322242
static int64_t get_time_ms(void)
@@ -2235,16 +2245,12 @@ static int64_t get_time_ms(void)
22352245

22362246
_ftime(&tb);
22372247
return (int64_t)tb.time * 1000 + (tb.millitm);
2238-
22392248
}
2240-
*/
2241-
22422249
static int64_t get_time_ns(void)
22432250
{
2244-
struct timespec ts;
2245-
clock_gettime(CLOCK_MONOTONIC, &ts);
2246-
return (uint64_t)ts.tv_sec * 1000000000 + ts.tv_nsec;
2251+
return gf_sys_clock_high_res() * 1000;
22472252
}
2253+
22482254
#else
22492255
/* more portable, but does not work if the date is updated */
22502256
static int64_t get_time_ms(void)
@@ -2560,8 +2566,10 @@ static int js_os_poll(JSContext *ctx)
25602566
}
25612567
}
25622568
} else {
2563-
min_delay = -1;
2564-
}
2569+
//min_delay = -1;
2570+
//we need to exit - max 1sec wait
2571+
min_delay = 1000;
2572+
}
25652573

25662574
count = 0;
25672575
list_for_each(el, &ts->os_rw_handlers) {
@@ -2575,7 +2583,7 @@ static int js_os_poll(JSContext *ctx)
25752583

25762584
list_for_each(el, &ts->port_list) {
25772585
JSWorkerMessageHandler *port = list_entry(el, JSWorkerMessageHandler, link);
2578-
if (JS_IsNull(port->on_message_func))
2586+
if (JS_IsNull(port->on_message_func))
25792587
continue;
25802588
handles[count++] = port->recv_pipe->waker.handle;
25812589
if (count == (int)countof(handles))
@@ -2609,13 +2617,18 @@ static int js_os_poll(JSContext *ctx)
26092617
}
26102618
}
26112619
}
2612-
} else {
2613-
Sleep(min_delay);
26142620
}
2615-
done:
2621+
2622+
//do not block if main thread !
2623+
if (!ts->recv_pipe || ts->terminated) {
2624+
return -1;
2625+
}
2626+
2627+
done:
26162628
return 0;
26172629
}
26182630

2631+
26192632
#else
26202633

26212634
static int js_os_poll(JSContext *ctx)
@@ -2732,6 +2745,11 @@ static int js_os_poll(JSContext *ctx)
27322745
}
27332746
}
27342747
}
2748+
2749+
//do not block if main thread !
2750+
else if (!ts->recv_pipe || ts->terminated) {
2751+
return -1;
2752+
}
27352753
done:
27362754
return 0;
27372755
}
@@ -3730,6 +3748,14 @@ static JSValue js_os_waitpid(JSContext *ctx, JSValueConst this_val, int argc, JS
37303748
return obj;
37313749
}
37323750

3751+
/* getpid() -> pid */
3752+
static JSValue js_os_getpid(JSContext *ctx, JSValueConst this_val,
3753+
int argc, JSValueConst *argv)
3754+
{
3755+
return JS_NewInt32(ctx, GetCurrentProcessId());
3756+
}
3757+
3758+
37333759
/* kill(pid, sig) */
37343760
static JSValue js_os_kill(JSContext *ctx, JSValueConst this_val,
37353761
int argc, JSValueConst *argv)
@@ -3834,6 +3860,7 @@ typedef struct {
38343860
char *basename; /* module base name */
38353861
JSWorkerMessagePipe *recv_pipe, *send_pipe;
38363862
int strip_flags;
3863+
JSWorkerData *worker;
38373864
} WorkerFuncArgs;
38383865

38393866
typedef struct {
@@ -3900,10 +3927,6 @@ static JSWorkerMessagePipe *js_new_message_pipe(void)
39003927
char mxName[100];
39013928
sprintf(mxName, "Worker%pMx", ps);
39023929
ps->mutex = gf_mx_new(mxName);
3903-
/* CHECKME
3904-
ps->read_fd = pipe_fds[0];
3905-
ps->write_fd = pipe_fds[1];
3906-
*/
39073930
return ps;
39083931
}
39093932

@@ -3942,12 +3965,8 @@ static void js_free_message_pipe(JSWorkerMessagePipe *ps)
39423965
js_free_message(msg);
39433966
}
39443967

3945-
/* CHECKME
3946-
close(ps->read_fd);
3947-
close(ps->write_fd);
3948-
*/
3949-
gf_mx_del(ps->mutex);
39503968
js_waker_close(&ps->waker);
3969+
gf_mx_del(ps->mutex);
39513970
free(ps);
39523971
}
39533972
}
@@ -3990,7 +4009,7 @@ static unsigned int worker_func(void *opaque)
39904009
{
39914010
WorkerFuncArgs *args = opaque;
39924011
JSRuntime *rt;
3993-
//JSWorkerData *worker;
4012+
JSWorkerData *worker;
39944013
JSThreadState *ts;
39954014
JSContext *ctx;
39964015
JSValue val;
@@ -4009,10 +4028,9 @@ static unsigned int worker_func(void *opaque)
40094028
ts = JS_GetRuntimeOpaque(rt);
40104029
ts->recv_pipe = args->recv_pipe;
40114030
ts->send_pipe = args->send_pipe;
4012-
/* CHECKME
4031+
40134032
worker = args->worker;
40144033
worker->ts = ts;
4015-
*/
40164034

40174035
/* function pointer to avoid linking the whole JS_NewContext() if
40184036
not needed */
@@ -4041,10 +4059,10 @@ static unsigned int worker_func(void *opaque)
40414059
JS_FreeValue(ctx, val);
40424060

40434061
js_std_loop(ctx);
4044-
/* CHECKME
4062+
40454063
worker->ts = NULL;
40464064
worker->msg_handler = NULL;
4047-
*/
4065+
40484066
JS_FreeContext(ctx);
40494067
//do not free JSThreadState yet, it is used to unlink ports in worker finalizer
40504068
js_std_free_handlers_ex(rt, 1);
@@ -4139,13 +4157,13 @@ static JSValue js_worker_ctor(JSContext *ctx, JSValueConst new_target,
41394157
if (JS_IsException(obj))
41404158
goto fail;
41414159

4142-
JSWorkerData *worker = JS_GetOpaque(obj, js_worker_class_id);
4143-
worker->th = gf_th_new("gf_js_worker");
4144-
if (!worker->th) {
4160+
args->worker = JS_GetOpaque(obj, js_worker_class_id);
4161+
args->worker->th = gf_th_new("gf_js_worker");
4162+
if (!args->worker->th) {
41454163
goto oom_fail;
41464164
}
41474165

4148-
ret = gf_th_run(worker->th, worker_func, args);
4166+
ret = gf_th_run(args->worker->th, worker_func, args);
41494167
if (ret != 0) {
41504168
JS_ThrowTypeError(ctx, "could not create worker");
41514169
goto fail;
@@ -4251,7 +4269,7 @@ static JSValue js_worker_set_onmessage(JSContext *ctx, JSValueConst this_val,
42514269
port = worker->msg_handler;
42524270
if (JS_IsNull(func)) {
42534271
if (port) {
4254-
js_free_port(rt, port);
4272+
js_free_port(rt, port);
42554273
worker->msg_handler = NULL;
42564274
}
42574275
} else {
@@ -4801,6 +4819,5 @@ void js_std_eval_binary_json_module(JSContext *ctx,
48014819
exit(1);
48024820
}
48034821
}
4804-
#endif
48054822

48064823
#endif //GPAC_DISABLE_QJS_LIBC

0 commit comments

Comments
 (0)