@@ -341,6 +341,7 @@ typedef enum {
341341 JS_GC_OBJ_TYPE_VAR_REF,
342342 JS_GC_OBJ_TYPE_ASYNC_FUNCTION,
343343 JS_GC_OBJ_TYPE_JS_CONTEXT,
344+ JS_GC_OBJ_TYPE_MODULE,
344345} JSGCObjectTypeEnum;
345346
346347/* header for GC objects. GC objects are C data structures with a
@@ -805,7 +806,7 @@ typedef enum {
805806} JSModuleStatus;
806807
807808struct JSModuleDef {
808- JSRefCountHeader header; /* must come first, 32-bit */
809+ JSGCObjectHeader header; /* must come first */
809810 JSAtom module_name;
810811 struct list_head link;
811812
@@ -857,7 +858,7 @@ struct JSModuleDef {
857858
858859typedef struct JSJobEntry {
859860 struct list_head link;
860- JSContext *ctx ;
861+ JSContext *realm ;
861862 JSJobFunc *job_func;
862863 int argc;
863864 JSValue argv[0];
@@ -1222,7 +1223,7 @@ static void js_async_function_resolve_mark(JSRuntime *rt, JSValueConst val,
12221223static JSValue JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
12231224 const char *input, size_t input_len,
12241225 const char *filename, int flags, int scope_idx);
1225- static void js_free_module_def(JSContext *ctx , JSModuleDef *m);
1226+ static void js_free_module_def(JSRuntime *rt , JSModuleDef *m);
12261227static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
12271228 JS_MarkFunc *mark_func);
12281229static JSValue js_import_meta(JSContext *ctx);
@@ -1782,7 +1783,7 @@ int JS_EnqueueJob(JSContext *ctx, JSJobFunc *job_func,
17821783 e = js_malloc(ctx, sizeof(*e) + argc * sizeof(JSValue));
17831784 if (!e)
17841785 return -1;
1785- e->ctx = ctx;
1786+ e->realm = JS_DupContext( ctx) ;
17861787 e->job_func = job_func;
17871788 e->argc = argc;
17881789 for(i = 0; i < argc; i++) {
@@ -1798,7 +1799,10 @@ BOOL JS_IsJobPending(JSRuntime *rt)
17981799}
17991800
18001801/* return < 0 if exception, 0 if no job pending, 1 if a job was
1801- executed successfully. the context of the job is stored in '*pctx' */
1802+ executed successfully. The context of the job is stored in '*pctx'
1803+ if pctx != NULL. It may be NULL if the context was already
1804+ destroyed or if no job was pending. The 'pctx' parameter is now
1805+ absolete. */
18021806int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
18031807{
18041808 JSContext *ctx;
@@ -1807,15 +1811,16 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
18071811 int i, ret;
18081812
18091813 if (list_empty(&rt->job_list)) {
1810- *pctx = NULL;
1814+ if (pctx)
1815+ *pctx = NULL;
18111816 return 0;
18121817 }
18131818
18141819 /* get the first pending job and execute it */
18151820 e = list_entry(rt->job_list.next, JSJobEntry, link);
18161821 list_del(&e->link);
1817- ctx = e->ctx ;
1818- res = e->job_func(e-> ctx, e->argc, (JSValueConst *)e->argv);
1822+ ctx = e->realm ;
1823+ res = e->job_func(ctx, e->argc, (JSValueConst *)e->argv);
18191824 for(i = 0; i < e->argc; i++)
18201825 JS_FreeValue(ctx, e->argv[i]);
18211826 if (JS_IsException(res))
@@ -1824,7 +1829,13 @@ int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx)
18241829 ret = 1;
18251830 JS_FreeValue(ctx, res);
18261831 js_free(ctx, e);
1827- *pctx = ctx;
1832+ if (pctx) {
1833+ if (ctx->header.ref_count > 1)
1834+ *pctx = ctx;
1835+ else
1836+ *pctx = NULL;
1837+ }
1838+ JS_FreeContext(ctx);
18281839 return ret;
18291840}
18301841
@@ -1905,6 +1916,7 @@ void JS_FreeRuntime(JSRuntime *rt)
19051916 JSJobEntry *e = list_entry(el, JSJobEntry, link);
19061917 for(i = 0; i < e->argc; i++)
19071918 JS_FreeValueRT(rt, e->argv[i]);
1919+ JS_FreeContext(e->realm);
19081920 js_free_rt(rt, e);
19091921 }
19101922 init_list_head(&rt->job_list);
@@ -2180,7 +2192,13 @@ static void js_free_modules(JSContext *ctx, JSFreeModuleEnum flag)
21802192 JSModuleDef *m = list_entry(el, JSModuleDef, link);
21812193 if (flag == JS_FREE_MODULE_ALL ||
21822194 (flag == JS_FREE_MODULE_NOT_RESOLVED && !m->resolved)) {
2183- js_free_module_def(ctx, m);
2195+ /* warning: the module may be referenced elsewhere. It
2196+ could be simpler to use an array instead of a list for
2197+ 'ctx->loaded_modules' */
2198+ list_del(&m->link);
2199+ m->link.prev = NULL;
2200+ m->link.next = NULL;
2201+ JS_FreeValue(ctx, JS_MKPTR(JS_TAG_MODULE, m));
21842202 }
21852203 }
21862204}
@@ -2198,11 +2216,9 @@ static void JS_MarkContext(JSRuntime *rt, JSContext *ctx,
21982216 int i;
21992217 struct list_head *el;
22002218
2201- /* modules are not seen by the GC, so we directly mark the objects
2202- referenced by each module */
22032219 list_for_each(el, &ctx->loaded_modules) {
22042220 JSModuleDef *m = list_entry(el, JSModuleDef, link);
2205- js_mark_module_def (rt, m , mark_func);
2221+ JS_MarkValue (rt, JS_MKPTR(JS_TAG_MODULE, m) , mark_func);
22062222 }
22072223
22082224 JS_MarkValue(rt, ctx->global_obj, mark_func);
@@ -5783,6 +5799,9 @@ static void free_gc_object(JSRuntime *rt, JSGCObjectHeader *gp)
57835799 case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
57845800 __async_func_free(rt, (JSAsyncFunctionState *)gp);
57855801 break;
5802+ case JS_GC_OBJ_TYPE_MODULE:
5803+ js_free_module_def(rt, (JSModuleDef *)gp);
5804+ break;
57865805 default:
57875806 abort();
57885807 }
@@ -5847,6 +5866,7 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
58475866 break;
58485867 case JS_TAG_OBJECT:
58495868 case JS_TAG_FUNCTION_BYTECODE:
5869+ case JS_TAG_MODULE:
58505870 {
58515871 JSGCObjectHeader *p = JS_VALUE_GET_PTR(v);
58525872 if (rt->gc_phase != JS_GC_PHASE_REMOVE_CYCLES) {
@@ -5859,9 +5879,6 @@ void __JS_FreeValueRT(JSRuntime *rt, JSValue v)
58595879 }
58605880 }
58615881 break;
5862- case JS_TAG_MODULE:
5863- abort(); /* never freed here */
5864- break;
58655882 case JS_TAG_BIG_INT:
58665883 {
58675884 JSBigInt *p = JS_VALUE_GET_PTR(v);
@@ -5935,6 +5952,7 @@ void JS_MarkValue(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func)
59355952 switch(JS_VALUE_GET_TAG(val)) {
59365953 case JS_TAG_OBJECT:
59375954 case JS_TAG_FUNCTION_BYTECODE:
5955+ case JS_TAG_MODULE:
59385956 mark_func(rt, JS_VALUE_GET_PTR(val));
59395957 break;
59405958 default:
@@ -6047,6 +6065,12 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp,
60476065 JS_MarkContext(rt, ctx, mark_func);
60486066 }
60496067 break;
6068+ case JS_GC_OBJ_TYPE_MODULE:
6069+ {
6070+ JSModuleDef *m = (JSModuleDef *)gp;
6071+ js_mark_module_def(rt, m, mark_func);
6072+ }
6073+ break;
60506074 default:
60516075 abort();
60526076 }
@@ -6143,6 +6167,7 @@ static void gc_free_cycles(JSRuntime *rt)
61436167 case JS_GC_OBJ_TYPE_JS_OBJECT:
61446168 case JS_GC_OBJ_TYPE_FUNCTION_BYTECODE:
61456169 case JS_GC_OBJ_TYPE_ASYNC_FUNCTION:
6170+ case JS_GC_OBJ_TYPE_MODULE:
61466171#ifdef DUMP_GC_FREE
61476172 if (!header_done) {
61486173 printf("Freeing cycles:\n");
@@ -6165,7 +6190,8 @@ static void gc_free_cycles(JSRuntime *rt)
61656190 p = list_entry(el, JSGCObjectHeader, link);
61666191 assert(p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT ||
61676192 p->gc_obj_type == JS_GC_OBJ_TYPE_FUNCTION_BYTECODE ||
6168- p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION);
6193+ p->gc_obj_type == JS_GC_OBJ_TYPE_ASYNC_FUNCTION ||
6194+ p->gc_obj_type == JS_GC_OBJ_TYPE_MODULE);
61696195 if (p->gc_obj_type == JS_GC_OBJ_TYPE_JS_OBJECT &&
61706196 ((JSObject *)p)->weakref_count != 0) {
61716197 /* keep the object because there are weak references to it */
@@ -13747,6 +13773,9 @@ static __maybe_unused void JS_DumpGCObject(JSRuntime *rt, JSGCObjectHeader *p)
1374713773 case JS_GC_OBJ_TYPE_JS_CONTEXT:
1374813774 printf("[js_context]");
1374913775 break;
13776+ case JS_GC_OBJ_TYPE_MODULE:
13777+ printf("[module]");
13778+ break;
1375013779 default:
1375113780 printf("[unknown %d]", p->gc_obj_type);
1375213781 break;
@@ -28216,7 +28245,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
2821628245 return -1;
2821728246}
2821828247
28219- /* 'name' is freed */
28248+ /* 'name' is freed. The module is referenced by 'ctx->loaded_modules' */
2822028249static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
2822128250{
2822228251 JSModuleDef *m;
@@ -28226,6 +28255,7 @@ static JSModuleDef *js_new_module_def(JSContext *ctx, JSAtom name)
2822628255 return NULL;
2822728256 }
2822828257 m->header.ref_count = 1;
28258+ add_gc_object(ctx->rt, &m->header, JS_GC_OBJ_TYPE_MODULE);
2822928259 m->module_name = name;
2823028260 m->module_ns = JS_UNDEFINED;
2823128261 m->func_obj = JS_UNDEFINED;
@@ -28267,47 +28297,56 @@ static void js_mark_module_def(JSRuntime *rt, JSModuleDef *m,
2826728297 JS_MarkValue(rt, m->private_value, mark_func);
2826828298}
2826928299
28270- static void js_free_module_def(JSContext *ctx , JSModuleDef *m)
28300+ static void js_free_module_def(JSRuntime *rt , JSModuleDef *m)
2827128301{
2827228302 int i;
2827328303
28274- JS_FreeAtom(ctx , m->module_name);
28304+ JS_FreeAtomRT(rt , m->module_name);
2827528305
2827628306 for(i = 0; i < m->req_module_entries_count; i++) {
2827728307 JSReqModuleEntry *rme = &m->req_module_entries[i];
28278- JS_FreeAtom(ctx , rme->module_name);
28279- JS_FreeValue(ctx , rme->attributes);
28308+ JS_FreeAtomRT(rt , rme->module_name);
28309+ JS_FreeValueRT(rt , rme->attributes);
2828028310 }
28281- js_free(ctx , m->req_module_entries);
28311+ js_free_rt(rt , m->req_module_entries);
2828228312
2828328313 for(i = 0; i < m->export_entries_count; i++) {
2828428314 JSExportEntry *me = &m->export_entries[i];
2828528315 if (me->export_type == JS_EXPORT_TYPE_LOCAL)
28286- free_var_ref(ctx-> rt, me->u.local.var_ref);
28287- JS_FreeAtom(ctx , me->export_name);
28288- JS_FreeAtom(ctx , me->local_name);
28316+ free_var_ref(rt, me->u.local.var_ref);
28317+ JS_FreeAtomRT(rt , me->export_name);
28318+ JS_FreeAtomRT(rt , me->local_name);
2828928319 }
28290- js_free(ctx , m->export_entries);
28320+ js_free_rt(rt , m->export_entries);
2829128321
28292- js_free(ctx , m->star_export_entries);
28322+ js_free_rt(rt , m->star_export_entries);
2829328323
2829428324 for(i = 0; i < m->import_entries_count; i++) {
2829528325 JSImportEntry *mi = &m->import_entries[i];
28296- JS_FreeAtom(ctx , mi->import_name);
28326+ JS_FreeAtomRT(rt , mi->import_name);
2829728327 }
28298- js_free(ctx , m->import_entries);
28299- js_free(ctx , m->async_parent_modules);
28328+ js_free_rt(rt , m->import_entries);
28329+ js_free_rt(rt , m->async_parent_modules);
2830028330
28301- JS_FreeValue(ctx, m->module_ns);
28302- JS_FreeValue(ctx, m->func_obj);
28303- JS_FreeValue(ctx, m->eval_exception);
28304- JS_FreeValue(ctx, m->meta_obj);
28305- JS_FreeValue(ctx, m->promise);
28306- JS_FreeValue(ctx, m->resolving_funcs[0]);
28307- JS_FreeValue(ctx, m->resolving_funcs[1]);
28308- JS_FreeValue(ctx, m->private_value);
28309- list_del(&m->link);
28310- js_free(ctx, m);
28331+ JS_FreeValueRT(rt, m->module_ns);
28332+ JS_FreeValueRT(rt, m->func_obj);
28333+ JS_FreeValueRT(rt, m->eval_exception);
28334+ JS_FreeValueRT(rt, m->meta_obj);
28335+ JS_FreeValueRT(rt, m->promise);
28336+ JS_FreeValueRT(rt, m->resolving_funcs[0]);
28337+ JS_FreeValueRT(rt, m->resolving_funcs[1]);
28338+ JS_FreeValueRT(rt, m->private_value);
28339+ /* during the GC the finalizers are called in an arbitrary
28340+ order so the module may no longer be referenced by the JSContext list */
28341+ if (m->link.next) {
28342+ list_del(&m->link);
28343+ }
28344+ remove_gc_object(&m->header);
28345+ if (rt->gc_phase == JS_GC_PHASE_REMOVE_CYCLES && m->header.ref_count != 0) {
28346+ list_add_tail(&m->header.link, &rt->gc_zero_ref_count_list);
28347+ } else {
28348+ js_free_rt(rt, m);
28349+ }
2831128350}
2831228351
2831328352static int add_req_module_entry(JSContext *ctx, JSModuleDef *m,
@@ -35804,7 +35843,7 @@ static JSValue __JS_EvalInternal(JSContext *ctx, JSValueConst this_obj,
3580435843 fail1:
3580535844 /* XXX: should free all the unresolved dependencies */
3580635845 if (m)
35807- js_free_module_def (ctx, m );
35846+ JS_FreeValue (ctx, JS_MKPTR(JS_TAG_MODULE, m) );
3580835847 return JS_EXCEPTION;
3580935848}
3581035849
@@ -37516,7 +37555,7 @@ static JSValue JS_ReadModule(BCReaderState *s)
3751637555 return obj;
3751737556 fail:
3751837557 if (m) {
37519- js_free_module_def (ctx, m );
37558+ JS_FreeValue (ctx, JS_MKPTR(JS_TAG_MODULE, m) );
3752037559 }
3752137560 return JS_EXCEPTION;
3752237561}
@@ -55663,7 +55702,7 @@ typedef struct JSFinRecEntry {
5566355702typedef struct JSFinalizationRegistryData {
5566455703 JSWeakRefHeader weakref_header;
5566555704 struct list_head entries; /* list of JSFinRecEntry.link */
55666- JSContext *ctx ;
55705+ JSContext *realm ;
5566755706 JSValue cb;
5566855707} JSFinalizationRegistryData;
5566955708
@@ -55680,6 +55719,7 @@ static void js_finrec_finalizer(JSRuntime *rt, JSValue val)
5568055719 js_free_rt(rt, fre);
5568155720 }
5568255721 JS_FreeValueRT(rt, frd->cb);
55722+ JS_FreeContext(frd->realm);
5568355723 list_del(&frd->weakref_header.link);
5568455724 js_free_rt(rt, frd);
5568555725 }
@@ -55696,6 +55736,7 @@ static void js_finrec_mark(JSRuntime *rt, JSValueConst val,
5569655736 JS_MarkValue(rt, fre->held_val, mark_func);
5569755737 }
5569855738 JS_MarkValue(rt, frd->cb, mark_func);
55739+ mark_func(rt, &frd->realm->header);
5569955740 }
5570055741}
5570155742
@@ -55721,7 +55762,7 @@ static void finrec_delete_weakref(JSRuntime *rt, JSWeakRefHeader *wh)
5572155762 JSValueConst args[2];
5572255763 args[0] = frd->cb;
5572355764 args[1] = fre->held_val;
55724- JS_EnqueueJob(frd->ctx , js_finrec_job, 2, args);
55765+ JS_EnqueueJob(frd->realm , js_finrec_job, 2, args);
5572555766
5572655767 js_weakref_free(rt, fre->target);
5572755768 js_weakref_free(rt, fre->token);
@@ -55756,7 +55797,7 @@ static JSValue js_finrec_constructor(JSContext *ctx, JSValueConst new_target,
5575655797 frd->weakref_header.weakref_type = JS_WEAKREF_TYPE_FINREC;
5575755798 list_add_tail(&frd->weakref_header.link, &ctx->rt->weakref_list);
5575855799 init_list_head(&frd->entries);
55759- frd->ctx = ctx; /* XXX: JS_DupContext() ? */
55800+ frd->realm = JS_DupContext(ctx);
5576055801 frd->cb = JS_DupValue(ctx, cb);
5576155802 JS_SetOpaque(obj, frd);
5576255803 return obj;
0 commit comments