Separate stored objects by the render view.

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.
This commit is contained in:
Cheng Zhao 2013-04-26 21:14:29 +08:00
parent e91d4c7c99
commit dded164052
2 changed files with 35 additions and 33 deletions

View file

@ -1,22 +1,22 @@
module.exports = IDWeakMap = require 'id_weak_map'
class ObjectsRegistry
@nextId = 0
constructor: -> globalStore = {}
@objects = [] globalMap = new IDWeakMap
getNextId: -> getStoreForRenderView = (process_id, routing_id) ->
++ObjectsRegistry.nextId key = "#{process_id}_#{routing_id}"
globalStore[key] = {} unless globalStore[key]?
globalStore[key]
add: (obj) -> exports.add = (process_id, routing_id, obj) ->
id = @getNextId() id = globalMap.add obj
@objects[id] = obj store = getStoreForRenderView process_id, routing_id
store[id] = obj
id id
remove: (id) -> exports.get = (process_id, routing_id, id) ->
obj = @objects[id] globalMap.get id
delete @objects[id]
obj
get: (id) -> exports.remove = (process_id, routing_id, id) ->
@objects[id] store = getStoreForRenderView process_id, routing_id
delete store[id]

View file

@ -1,21 +1,20 @@
ipc = require 'ipc' ipc = require 'ipc'
path = require 'path' path = require 'path'
ObjectsRegistry = require './objects_registry.js' objectsRegistry = require './objects_registry.js'
objectsRegistry = new ObjectsRegistry
class PlainObject class PlainObject
constructor: (value) -> constructor: (process_id, routing_id, value) ->
@type = typeof value @type = typeof value
@type = 'value' if value is null @type = 'value' if value is null
@type = 'array' if Array.isArray value @type = 'array' if Array.isArray value
if @type is 'array' if @type is 'array'
@members = [] @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' else if @type is 'object' or @type is 'function'
@name = value.constructor.name @name = value.constructor.name
@id = objectsRegistry.add value @id = objectsRegistry.add process_id, routing_id, value
value.id = @id
@members = [] @members = []
@members.push { name: prop, type: typeof field } for prop, field of value @members.push { name: prop, type: typeof field } for prop, field of value
@ -24,44 +23,47 @@ class PlainObject
@value = value @value = value
ipc.on 'ATOM_INTERNAL_REQUIRE', (event, process_id, routing_id, module) -> 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) -> ipc.on 'ATOM_INTERNAL_CONSTRUCTOR', (event, process_id, routing_id, id, args) ->
try try
constructor = objectsRegistry.get id constructor = objectsRegistry.get process_id, routing_id, id
# Call new with array of arguments. # Call new with array of arguments.
# http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible # http://stackoverflow.com/questions/1606797/use-of-apply-with-new-operator-is-this-possible
obj = new (Function::bind.apply(constructor, [null].concat(args))) 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 catch e
event.result = type: 'error', value: e.message event.result = type: 'error', value: e.message
ipc.on 'ATOM_INTERNAL_FUNCTION_CALL', (event, process_id, routing_id, id, args) -> ipc.on 'ATOM_INTERNAL_FUNCTION_CALL', (event, process_id, routing_id, id, args) ->
try try
ret = objectsRegistry.get(id).apply global, args func = objectsRegistry.get process_id, routing_id, id
event.result = new PlainObject(ret) ret = func.apply global, args
event.result = new PlainObject(process_id, routing_id, ret)
catch e catch e
event.result = type: 'error', value: e.message event.result = type: 'error', value: e.message
ipc.on 'ATOM_INTERNAL_MEMBER_CALL', (event, process_id, routing_id, id, method, args) -> ipc.on 'ATOM_INTERNAL_MEMBER_CALL', (event, process_id, routing_id, id, method, args) ->
try try
obj = objectsRegistry.get id obj = objectsRegistry.get process_id, routing_id, id
ret = obj[method].apply(obj, args) ret = obj[method].apply(obj, args)
event.result = new PlainObject(ret) event.result = new PlainObject(process_id, routing_id, ret)
catch e catch e
event.result = type: 'error', value: e.message event.result = type: 'error', value: e.message
ipc.on 'ATOM_INTERNAL_MEMBER_SET', (event, process_id, routing_id, id, name, value) -> ipc.on 'ATOM_INTERNAL_MEMBER_SET', (event, process_id, routing_id, id, name, value) ->
try try
objectsRegistry.get(id)[name] = value obj = objectsRegistry.get process_id, routing_id, id
obj[name] = value
catch e catch e
event.result = type: 'error', value: e.message event.result = type: 'error', value: e.message
ipc.on 'ATOM_INTERNAL_MEMBER_GET', (event, process_id, routing_id, id, name) -> ipc.on 'ATOM_INTERNAL_MEMBER_GET', (event, process_id, routing_id, id, name) ->
try 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 catch e
event.result = type: 'error', value: e.message event.result = type: 'error', value: e.message
ipc.on 'ATOM_INTERNAL_DESTROY', (process_id, routing_id, id) -> ipc.on 'ATOM_INTERNAL_DESTROY', (process_id, routing_id, id) ->
objectsRegistry.remove id objectsRegistry.remove process_id, routing_id, id