remote: track listeners for browser side
authorRobo <hop2deep@gmail.com>
Tue, 27 Oct 2015 22:15:46 +0000 (03:45 +0530)
committerRobo <hop2deep@gmail.com>
Thu, 29 Oct 2015 12:21:56 +0000 (17:51 +0530)
atom/browser/lib/rpc-server.coffee
atom/common/api/lib/callbacks-registry.coffee
spec/api-ipc-spec.coffee

index 6b1f95a..c4d9183 100644 (file)
@@ -3,6 +3,9 @@ path = require 'path'
 objectsRegistry = require './objects-registry.js'
 v8Util = process.atomBinding 'v8_util'
 
+# caches callback with their registry ID.
+rendererCallbacks = {}
+
 # Convert a real value into meta data.
 valueToMeta = (sender, value, optimizeSimpleObject=false) ->
   meta = type: typeof value
@@ -74,6 +77,8 @@ unwrapArgs = (sender, args) ->
         objectsRegistry.once "clear-#{sender.getId()}", ->
           rendererReleased = true
 
+        return rendererCallbacks[meta.id] if rendererCallbacks[meta.id]?
+
         ret = ->
           if rendererReleased
             throw new Error("Attempting to call a function in a renderer window
@@ -81,7 +86,9 @@ unwrapArgs = (sender, args) ->
           sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments)
         v8Util.setDestructor ret, ->
           return if rendererReleased
+          delete rendererCallbacks[meta.id]
           sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id
+        rendererCallbacks[meta.id] = ret
         ret
       else throw new TypeError("Unknown type: #{meta.type}")
 
index d4c37f0..5151640 100644 (file)
@@ -7,6 +7,10 @@ class CallbacksRegistry
   add: (callback) ->
     id = ++@nextId
 
+    for id,value of @callbacks
+      if value == callback
+        return id
+
     # Capture the location of the function and put it in the ID string,
     # so that release errors can be tracked down easily.
     regexp = /at (.*)/gi
index 142f06c..1155aa7 100644 (file)
@@ -88,3 +88,16 @@ describe 'ipc module', ->
         w.destroy()
         done()
       w.loadUrl 'file://' + path.join(fixtures, 'api', 'send-sync-message.html')
+
+  describe 'remote listeners', ->
+    it 'can be added and removed correctly', ->
+      count = 0
+      w = new BrowserWindow(show: false)
+      listener = () ->
+        count += 1
+        w.removeListener 'blur', listener
+      w.on 'blur', listener
+      w.emit 'blur'
+      w.emit 'blur'
+      assert.equal count, 1
+      w.destroy()