@@ -261,6 +261,7 @@ struct JSRuntime {
261261 JSGCPhaseEnum gc_phase : 8;
262262 size_t malloc_gc_threshold;
263263 struct list_head weakref_list; /* list of JSWeakRefHeader.link */
264+ struct list_head weakref_keepalive_list; /* strong refs kept until the current host job completes */
264265#ifdef DUMP_LEAKS
265266 struct list_head string_list; /* list of JSString.link */
266267#endif
@@ -339,6 +340,11 @@ typedef struct JSStackFrame {
339340 JSValue *cur_sp;
340341} JSStackFrame;
341342
343+ typedef struct JSWeakRefKeepAliveEntry {
344+ struct list_head link;
345+ JSValue value;
346+ } JSWeakRefKeepAliveEntry;
347+
342348typedef enum {
343349 JS_GC_OBJ_TYPE_JS_OBJECT,
344350 JS_GC_OBJ_TYPE_FUNCTION_BYTECODE,
@@ -1669,6 +1675,7 @@ JSRuntime *JS_NewRuntime2(const JSMallocFunctions *mf, void *opaque)
16691675 init_list_head(&rt->gc_zero_ref_count_list);
16701676 rt->gc_phase = JS_GC_PHASE_NONE;
16711677 init_list_head(&rt->weakref_list);
1678+ init_list_head(&rt->weakref_keepalive_list);
16721679
16731680#ifdef DUMP_LEAKS
16741681 init_list_head(&rt->string_list);
@@ -1990,6 +1997,7 @@ void JS_FreeRuntime(JSRuntime *rt)
19901997 js_free_rt(rt, e);
19911998 }
19921999 init_list_head(&rt->job_list);
2000+ JS_ClearWeakRefKeepAlives(rt);
19932001
19942002 /* don't remove the weak objects to avoid create new jobs with
19952003 FinalizationRegistry */
@@ -59255,6 +59263,7 @@ static JSValue js_weakref_constructor(JSContext *ctx, JSValueConst new_target,
5925559263 wrd->target = js_weakref_new(ctx, arg);
5925659264 wrd->weakref_header.weakref_type = JS_WEAKREF_TYPE_WEAKREF;
5925759265 list_add_tail(&wrd->weakref_header.link, &ctx->rt->weakref_list);
59266+ JS_KeepWeakRefTargetAlive(ctx, arg);
5925859267 JS_SetOpaque(obj, wrd);
5925959268 return obj;
5926059269}
@@ -59524,6 +59533,35 @@ JSValue JS_WeakRef_Deref(JSContext *ctx, JSValueConst this_val) {
5952459533 return js_weakref_deref(ctx, this_val, 0, NULL);
5952559534}
5952659535
59536+ void JS_KeepWeakRefTargetAlive(JSContext *ctx, JSValueConst value)
59537+ {
59538+ JSRuntime *rt;
59539+ JSWeakRefKeepAliveEntry *entry;
59540+
59541+ if (!js_weakref_is_target(value))
59542+ return;
59543+
59544+ rt = JS_GetRuntime(ctx);
59545+ entry = js_malloc(ctx, sizeof(*entry));
59546+ if (!entry)
59547+ return;
59548+
59549+ entry->value = JS_DupValue(ctx, value);
59550+ list_add_tail(&entry->link, &rt->weakref_keepalive_list);
59551+ }
59552+
59553+ void JS_ClearWeakRefKeepAlives(JSRuntime *rt)
59554+ {
59555+ struct list_head *el, *el1;
59556+
59557+ list_for_each_safe(el, el1, &rt->weakref_keepalive_list) {
59558+ JSWeakRefKeepAliveEntry *entry = list_entry(el, JSWeakRefKeepAliveEntry, link);
59559+ list_del(&entry->link);
59560+ JS_FreeValueRT(rt, entry->value);
59561+ js_free_rt(rt, entry);
59562+ }
59563+ }
59564+
5952759565int JS_GetLength(JSContext *ctx, JSValueConst obj, int64_t *pres) {
5952859566 return js_get_length64(ctx, pres, obj);
5952959567}
@@ -59577,4 +59615,3 @@ int JS_FreezeObject(JSContext *ctx, JSValueConst obj)
5957759615size_t JS_GetGCThreshold(JSRuntime *rt) {
5957859616 return rt->malloc_gc_threshold;
5957959617}
59580-
0 commit comments