From cc921fed1eda30ce482c5f3d7ddda4d5b5797a4d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 26 Apr 2013 22:25:30 +0800 Subject: [PATCH] Add remote.getObject API to get object in browser by it's ID. --- browser/api/atom_api_event_emitter.cc | 6 ------ browser/atom/objects_registry.coffee | 18 ++++++++++++++++-- browser/atom/rpc_server.coffee | 23 ++++++++++++++++------- renderer/api/lib/remote.coffee | 7 ++++++- 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/browser/api/atom_api_event_emitter.cc b/browser/api/atom_api_event_emitter.cc index ae39a7c..5d2efcf 100644 --- a/browser/api/atom_api_event_emitter.cc +++ b/browser/api/atom_api_event_emitter.cc @@ -30,12 +30,6 @@ EventEmitter::EventEmitter(v8::Handle wrapper) { } EventEmitter::~EventEmitter() { - // process.emit('ATOM_BROWSER_INTERNAL_DELETE', this). - v8::Handle args[] = { - v8::String::New("ATOM_BROWSER_INTERNAL_DELETE"), - handle_, - }; - node::MakeCallback(node::process, "emit", 2, args); } bool EventEmitter::Emit(const std::string& name, base::ListValue* args) { diff --git a/browser/atom/objects_registry.coffee b/browser/atom/objects_registry.coffee index 3584b0a..1f838ab 100644 --- a/browser/atom/objects_registry.coffee +++ b/browser/atom/objects_registry.coffee @@ -8,13 +8,27 @@ getStoreForRenderView = (process_id, routing_id) -> globalStore[key] = {} unless globalStore[key]? globalStore[key] -exports.add = (process_id, routing_id, obj) -> +process.on 'ATOM_BROWSER_INTERNAL_NEW', (obj) -> + # For objects created in browser scripts, keep a weak reference here. id = globalMap.add obj + obj.id = id + +exports.add = (process_id, routing_id, obj) -> + # Some native types may already been added to globalMap, in that case we + # don't add it twice. + id = obj.id ? globalMap.add obj + store = getStoreForRenderView process_id, routing_id + + # It's possible that a render view may want to get the same remote object + # twice, since we only allow one reference of one object per render view, + # we throw when the object is already referenced. + throw new Error("Object #{id} is already referenced") if store[id]? + store[id] = obj id -exports.get = (process_id, routing_id, id) -> +exports.get = (id) -> globalMap.get id exports.remove = (process_id, routing_id, id) -> diff --git a/browser/atom/rpc_server.coffee b/browser/atom/rpc_server.coffee index e9d386e..693dc1f 100644 --- a/browser/atom/rpc_server.coffee +++ b/browser/atom/rpc_server.coffee @@ -14,7 +14,6 @@ class PlainObject else if @type is 'object' or @type is 'function' @name = value.constructor.name @id = objectsRegistry.add process_id, routing_id, value - value.id = @id @members = [] @members.push { name: prop, type: typeof field } for prop, field of value @@ -23,11 +22,14 @@ class PlainObject @value = value ipc.on 'ATOM_INTERNAL_REQUIRE', (event, process_id, routing_id, module) -> - event.result = new PlainObject(process_id, routing_id, require(module)) + try + event.result = new PlainObject(process_id, routing_id, require(module)) + catch e + event.result = type: 'error', value: e.message ipc.on 'ATOM_INTERNAL_CONSTRUCTOR', (event, process_id, routing_id, id, args) -> try - constructor = objectsRegistry.get process_id, routing_id, id + constructor = objectsRegistry.get 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))) @@ -37,7 +39,7 @@ ipc.on 'ATOM_INTERNAL_CONSTRUCTOR', (event, process_id, routing_id, id, args) -> ipc.on 'ATOM_INTERNAL_FUNCTION_CALL', (event, process_id, routing_id, id, args) -> try - func = objectsRegistry.get process_id, routing_id, id + func = objectsRegistry.get id ret = func.apply global, args event.result = new PlainObject(process_id, routing_id, ret) catch e @@ -45,7 +47,7 @@ ipc.on 'ATOM_INTERNAL_FUNCTION_CALL', (event, process_id, routing_id, id, args) ipc.on 'ATOM_INTERNAL_MEMBER_CALL', (event, process_id, routing_id, id, method, args) -> try - obj = objectsRegistry.get process_id, routing_id, id + obj = objectsRegistry.get id ret = obj[method].apply(obj, args) event.result = new PlainObject(process_id, routing_id, ret) catch e @@ -53,17 +55,24 @@ ipc.on 'ATOM_INTERNAL_MEMBER_CALL', (event, process_id, routing_id, id, method, ipc.on 'ATOM_INTERNAL_MEMBER_SET', (event, process_id, routing_id, id, name, value) -> try - obj = objectsRegistry.get process_id, routing_id, id + obj = objectsRegistry.get 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 - obj = objectsRegistry.get process_id, routing_id, id + obj = objectsRegistry.get id event.result = new PlainObject(process_id, routing_id, obj[name]) catch e event.result = type: 'error', value: e.message +ipc.on 'ATOM_INTERNAL_GET_OBJECT', (event, process_id, routing_id, id) -> + try + obj = objectsRegistry.get id + event.result = new PlainObject(process_id, routing_id, obj) + catch e + event.result = type: 'error', value: e.message + ipc.on 'ATOM_INTERNAL_DESTROY', (process_id, routing_id, id) -> objectsRegistry.remove process_id, routing_id, id diff --git a/renderer/api/lib/remote.coffee b/renderer/api/lib/remote.coffee index 9653d2b..088fc1e 100644 --- a/renderer/api/lib/remote.coffee +++ b/renderer/api/lib/remote.coffee @@ -3,7 +3,7 @@ v8_util = process.atom_binding 'v8_util' generateFromPainObject = (plain) -> switch plain.type - when 'error' then throw new Error('Remote Error: ' + plain.value) + when 'error' then throw new Error(plain.value) when 'value' then plain.value when 'array' then (generateFromPainObject(el) for el in plain.members) else @@ -56,3 +56,8 @@ generateFromPainObject = (plain) -> exports.require = (module) -> plain = ipc.sendChannelSync 'ATOM_INTERNAL_REQUIRE', module generateFromPainObject plain + +# Get object with specified id. +exports.getObject = (id) -> + plain = ipc.sendChannelSync 'ATOM_INTERNAL_GET_OBJECT', id + generateFromPainObject plain -- 2.7.4