From f36851fcffc5cf2e0415f618961ec2e740a830bc Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 1 Apr 2016 14:50:33 +0900 Subject: [PATCH 1/4] spec: Remote object should be referenced by its members --- spec/api-ipc-spec.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index be4f788fb0d0..da4acf887e4b 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -73,6 +73,12 @@ describe('ipc module', function () { assert.equal(delete remoteFunctions.aFunction, true) }) + + it('is referenced by its members', function () { + let stringify = remote.getGlobal('JSON').stringify + gc(); + stringify({}) + }); }) describe('remote value in browser', function () { From 4ebb01f8c9642103276d7e88bb81fcabc0a656f8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 1 Apr 2016 15:26:30 +0900 Subject: [PATCH 2/4] Remote object's members should reference itself --- lib/renderer/api/remote.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/renderer/api/remote.js b/lib/renderer/api/remote.js index 5f60a970ff3a..30341c0f77b7 100644 --- a/lib/renderer/api/remote.js +++ b/lib/renderer/api/remote.js @@ -109,9 +109,16 @@ let setObjectMembers = function (object, metaId, members) { return metaToValue(ret) } } - descriptor.writable = true + descriptor.get = function () { + remoteMemberFunction.ref = object // The member should reference its object. + return remoteMemberFunction + } + // Enable monkey-patch the method + descriptor.set = function (value) { + remoteMemberFunction = value + return value + } descriptor.configurable = true - descriptor.value = remoteMemberFunction } else if (member.type === 'get') { descriptor.get = function () { return metaToValue(ipcRenderer.sendSync('ATOM_BROWSER_MEMBER_GET', metaId, member.name)) From b9ead472a55719c3e6fd295df9b165450c44642d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 1 Apr 2016 15:35:34 +0900 Subject: [PATCH 3/4] spec: Remote object should be referenced by methods in its prototype chain --- spec/api-ipc-spec.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index da4acf887e4b..c98689287cea 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -149,6 +149,13 @@ describe('ipc module', function () { assert(!proto.hasOwnProperty('method')) assert(Object.getPrototypeOf(proto).hasOwnProperty('method')) }) + + it('is referenced by methods in prototype chain', function () { + let method = derived.method + derived = null + gc() + assert.equal(method(), 'method') + }); }) describe('ipc.sender.send', function () { From 39d2b95a33c72321bd5418030daa9392366df527 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 1 Apr 2016 15:45:36 +0900 Subject: [PATCH 4/4] Reference the remote object in its prototype chain's methods --- lib/renderer/api/remote.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/lib/renderer/api/remote.js b/lib/renderer/api/remote.js index 30341c0f77b7..30b66983a7d9 100644 --- a/lib/renderer/api/remote.js +++ b/lib/renderer/api/remote.js @@ -91,8 +91,9 @@ var wrapArgs = function (args, visited) { } // Populate object's members from descriptors. +// The |ref| will be kept referenced by |members|. // This matches |getObjectMemebers| in rpc-server. -let setObjectMembers = function (object, metaId, members) { +let setObjectMembers = function (ref, object, metaId, members) { for (let member of members) { if (object.hasOwnProperty(member.name)) continue @@ -110,7 +111,7 @@ let setObjectMembers = function (object, metaId, members) { } } descriptor.get = function () { - remoteMemberFunction.ref = object // The member should reference its object. + remoteMemberFunction.ref = ref // The member should reference its object. return remoteMemberFunction } // Enable monkey-patch the method @@ -139,11 +140,11 @@ let setObjectMembers = function (object, metaId, members) { // Populate object's prototype from descriptor. // This matches |getObjectPrototype| in rpc-server. -let setObjectPrototype = function (object, metaId, descriptor) { +let setObjectPrototype = function (ref, object, metaId, descriptor) { if (descriptor === null) return let proto = {} - setObjectMembers(proto, metaId, descriptor.members) - setObjectPrototype(proto, metaId, descriptor.proto) + setObjectMembers(ref, proto, metaId, descriptor.members) + setObjectPrototype(ref, proto, metaId, descriptor.proto) Object.setPrototypeOf(object, proto) } @@ -198,9 +199,9 @@ let metaToValue = function (meta) { } // Populate delegate members. - setObjectMembers(ret, meta.id, meta.members) + setObjectMembers(ret, ret, meta.id, meta.members) // Populate delegate prototype. - setObjectPrototype(ret, meta.id, meta.proto) + setObjectPrototype(ret, ret, meta.id, meta.proto) // Set constructor.name to object's name. Object.defineProperty(ret.constructor, 'name', { value: meta.name })