about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2023-09-04 13:10:09 +0200
committerbptato <nincsnevem662@gmail.com>2023-09-04 13:12:58 +0200
commitd5bb0eac7d8fdfba4214c1c8daa9523aa11e3277 (patch)
tree35ead738aa8b3f8537b88b69eae2e5133ba83c48
parent0314e97a6dff29e6e06789baf3cc70ed1566f71e (diff)
downloadchawan-d5bb0eac7d8fdfba4214c1c8daa9523aa11e3277.tar.gz
tojs: fix memory leak
Welp.
GC_ref should only be called if a new reference is being created.
This is what we did until 48f1306f, where this regression slipped in.
-rw-r--r--src/js/tojs.nim17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/js/tojs.nim b/src/js/tojs.nim
index 050af5e6..ca38bd2b 100644
--- a/src/js/tojs.nim
+++ b/src/js/tojs.nim
@@ -154,7 +154,7 @@ proc defineUnforgeable*(ctx: JSContext, this: JSValue) =
   ctxOpaque.unforgeable.withValue(classid, uf):
     JS_SetPropertyFunctionList(ctx, this, addr uf[][0], cint(uf[].len))
 
-proc toJSP0(ctx: JSContext, p, tp: pointer): JSValue =
+proc toJSP0(ctx: JSContext, p, tp: pointer, needsref: var bool): JSValue =
   JS_GetRuntime(ctx).getOpaque().plist.withValue(p, obj):
     # a JSValue already points to this object.
     return JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, obj[]))
@@ -164,15 +164,19 @@ proc toJSP0(ctx: JSContext, p, tp: pointer): JSValue =
   # We are "constructing" a new JS object, so we must add unforgeable
   # properties here.
   defineUnforgeable(ctx, jsObj) # not an exception
+  needsref = true
   return jsObj
 
 proc toJSRefObj(ctx: JSContext, obj: ref object): JSValue =
   if obj == nil:
     return JS_NULL
   let p = cast[pointer](obj)
-  GC_ref(obj)
   let tp = getTypePtr(obj)
-  return toJSP0(ctx, p, tp)
+  var needsref = false
+  let val = toJSP0(ctx, p, tp, needsref)
+  if needsref:
+    GC_ref(obj)
+  return val
 
 proc toJS*(ctx: JSContext, obj: ref object): JSValue =
   return toJSRefObj(ctx, obj)
@@ -259,9 +263,12 @@ proc toJSP(ctx: JSContext, parent: ref object, child: var object): JSValue =
     (proc() =
       GC_unref(parent))
   )
-  GC_ref(parent)
   let tp = getTypePtr(child)
-  return toJSP0(ctx, p, tp)
+  var needsref = false
+  let val = toJSP0(ctx, p, tp, needsref)
+  if needsref:
+    GC_ref(parent)
+  return val
 
 proc toJSP(ctx: JSContext, parent: ptr object, child: var object): JSValue =
   let p = addr child