Separate stored objects by the render view.
authorCheng Zhao <zcbenz@gmail.com>
Fri, 26 Apr 2013 13:14:29 +0000 (21:14 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Fri, 26 Apr 2013 13:14:29 +0000 (21:14 +0800)
When a render view is closed, it's not guarrenteed that all objects'
weak callback would be called. So we must clean up all objects manually
after the render view gets closed.

browser/atom/objects_registry.coffee
browser/atom/rpc_server.coffee

index 9bc0875..3584b0a 100644 (file)
@@ -1,22 +1,22 @@
-module.exports =
-class ObjectsRegistry
-  @nextId = 0
+IDWeakMap = require 'id_weak_map'
 
-  constructor: ->
-    @objects = []
+globalStore = {}
+globalMap = new IDWeakMap
 
-  getNextId: ->
-    ++ObjectsRegistry.nextId
+getStoreForRenderView = (process_id, routing_id) ->
+  key = "#{process_id}_#{routing_id}"
+  globalStore[key] = {} unless globalStore[key]?
+  globalStore[key]
 
-  add: (obj) ->
-    id = @getNextId()
-    @objects[id] = obj
-    id
+exports.add = (process_id, routing_id, obj) ->
+  id = globalMap.add obj
+  store = getStoreForRenderView process_id, routing_id
+  store[id] = obj
+  id
 
-  remove: (id) ->
-    obj = @objects[id]
-    delete @objects[id]
-    obj
+exports.get = (process_id, routing_id, id) ->
+  globalMap.get id
 
-  get: (id) ->
-    @objects[id]
+exports.remove = (process_id, routing_id, id) ->
+  store = getStoreForRenderView process_id, routing_id
+  delete store[id]
index 76a5ccb..e9d386e 100644 (file)
@@ -1,21 +1,20 @@
 ipc = require 'ipc'
 path = require 'path'
-ObjectsRegistry = require './objects_registry.js'
-
-objectsRegistry = new ObjectsRegistry
+objectsRegistry = require './objects_registry.js'
 
 class PlainObject
-  constructor: (value) ->
+  constructor: (process_id, routing_id, value) ->
     @type = typeof value
     @type = 'value' if value is null
     @type = 'array' if Array.isArray value
 
     if @type is 'array'
       @members = []
-      @members.push new PlainObject(el) for el in value
+      @members.push new PlainObject(process_id, routing_id, el) for el in value
     else if @type is 'object' or @type is 'function'
       @name = value.constructor.name
-      @id = objectsRegistry.add value
+      @id = objectsRegistry.add process_id, routing_id, value
+      value.id = @id
 
       @members = []
       @members.push { name: prop, type: typeof field } for prop, field of value
@@ -24,44 +23,47 @@ class PlainObject
       @value = value
 
 ipc.on 'ATOM_INTERNAL_REQUIRE', (event, process_id, routing_id, module) ->
-  event.result = new PlainObject(require(module))
+  event.result = new PlainObject(process_id, routing_id, require(module))
 
 ipc.on 'ATOM_INTERNAL_CONSTRUCTOR', (event, process_id, routing_id, id, args) ->
   try
-    constructor = objectsRegistry.get id
+    constructor = objectsRegistry.get process_id, routing_id, id
     # Call new with array of arguments.
     # http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
     obj = new (Function::bind.apply(constructor, [null].concat(args)))
-    event.result = new PlainObject(obj)
+    event.result = new PlainObject(process_id, routing_id, obj)
   catch e
     event.result = type: 'error', value: e.message
 
 ipc.on 'ATOM_INTERNAL_FUNCTION_CALL', (event, process_id, routing_id, id, args) ->
   try
-    ret = objectsRegistry.get(id).apply global, args
-    event.result = new PlainObject(ret)
+    func = objectsRegistry.get process_id, routing_id, id
+    ret = func.apply global, args
+    event.result = new PlainObject(process_id, routing_id, ret)
   catch e
     event.result = type: 'error', value: e.message
 
 ipc.on 'ATOM_INTERNAL_MEMBER_CALL', (event, process_id, routing_id, id, method, args) ->
   try
-    obj = objectsRegistry.get id
+    obj = objectsRegistry.get process_id, routing_id, id
     ret = obj[method].apply(obj, args)
-    event.result = new PlainObject(ret)
+    event.result = new PlainObject(process_id, routing_id, ret)
   catch e
     event.result = type: 'error', value: e.message
 
 ipc.on 'ATOM_INTERNAL_MEMBER_SET', (event, process_id, routing_id, id, name, value) ->
   try
-    objectsRegistry.get(id)[name] = value
+    obj = objectsRegistry.get process_id, routing_id, id
+    obj[name] = value
   catch e
     event.result = type: 'error', value: e.message
 
 ipc.on 'ATOM_INTERNAL_MEMBER_GET', (event, process_id, routing_id, id, name) ->
   try
-    event.result = new PlainObject(objectsRegistry.get(id)[name])
+    obj = objectsRegistry.get process_id, routing_id, id
+    event.result = new PlainObject(process_id, routing_id, obj[name])
   catch e
     event.result = type: 'error', value: e.message
 
 ipc.on 'ATOM_INTERNAL_DESTROY', (process_id, routing_id, id) ->
-  objectsRegistry.remove id
+  objectsRegistry.remove process_id, routing_id, id