diff options
author | bptato <nincsnevem662@gmail.com> | 2025-03-24 20:46:32 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2025-03-24 20:54:19 +0100 |
commit | d0cce7fac9367192f7f84a3f4b12db108becaf23 (patch) | |
tree | 31abed69998f36b9a08890f28ce0665edbb9495a | |
parent | c9e5d37ccbb59c1235775c6b745132f8dee44565 (diff) | |
download | chawan-d0cce7fac9367192f7f84a3f4b12db108becaf23.tar.gz |
event: fix some refcounting bugs
* only free callback after setting it to undefined (just in case JS observes the free with WeakMap etc.) * do not directly call callback; QJS really doesn't seem to like it when it deletes itself with removeEventListener * fix a leak with handleEvent
-rw-r--r-- | src/html/event.nim | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/src/html/event.nim b/src/html/event.nim index 271cf89c..dde850bf 100644 --- a/src/html/event.nim +++ b/src/html/event.nim @@ -73,7 +73,7 @@ type inputType {.jsget.}: string EventTarget* = ref object of RootObj - eventListeners*: seq[EventListener] + eventListeners: seq[EventListener] EventListener* = ref object # if callback is undefined, the listener has been removed @@ -322,8 +322,12 @@ proc invoke(ctx: JSContext; listener: EventListener; event: Event): JSValue = let jsTarget = ctx.toJS(event.currentTarget) let jsEvent = ctx.toJS(event) if JS_IsFunction(ctx, listener.callback): - let ret = JS_Call(ctx, listener.callback, jsTarget, 1, + # Apparently it's a bad idea to call a function that can then delete + # the reference it was called from. + let callback = JS_DupValue(ctx, listener.callback) + let ret = JS_Call(ctx, callback, jsTarget, 1, jsEvent.toJSValueArray()) + JS_FreeValue(ctx, callback) JS_FreeValue(ctx, jsTarget) JS_FreeValue(ctx, jsEvent) return ret @@ -334,6 +338,7 @@ proc invoke(ctx: JSContext; listener: EventListener; event: Event): JSValue = JS_FreeValue(ctx, jsEvent) return handler let ret = JS_Call(ctx, handler, jsTarget, 1, jsEvent.toJSValueArray()) + JS_FreeValue(ctx, handler) JS_FreeValue(ctx, jsTarget) JS_FreeValue(ctx, jsEvent) return ret @@ -353,8 +358,9 @@ proc addAnEventListener(ctx: JSContext; target: EventTarget; proc removeAnEventListener(eventTarget: EventTarget; ctx: JSContext; i: int) = let listener = eventTarget.eventListeners[i] - JS_FreeValue(ctx, listener.callback) + let callback = listener.callback listener.callback = JS_UNDEFINED + JS_FreeValue(ctx, callback) eventTarget.eventListeners.delete(i) proc flatten(ctx: JSContext; options: JSValueConst): bool = @@ -393,7 +399,7 @@ proc removeInternalEventListener(ctx: JSContext; eventTarget: EventTarget; if i != -1: eventTarget.removeAnEventListener(ctx, i) -proc addInternalEventListener*(ctx: JSContext; eventTarget: EventTarget; +proc addInternalEventListener(ctx: JSContext; eventTarget: EventTarget; ctype: StaticAtom; callback: JSValueConst) = ctx.removeInternalEventListener(eventTarget, ctype) ctx.addAnEventListener(eventTarget, EventListener( |