Use Proxy for accessing properties of remote function
This commit is contained in:
parent
8b38018ab4
commit
d226b7bc6c
4 changed files with 25 additions and 28 deletions
|
@ -51,18 +51,6 @@ let getObjectPrototype = function (object) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include properties on member methods
|
|
||||||
const addFunctionProperties = (sender, value, members) => {
|
|
||||||
members.forEach((member) => {
|
|
||||||
if (member.type !== 'method') return
|
|
||||||
const method = value[member.name]
|
|
||||||
member.members = getObjectMembers(method)
|
|
||||||
if (member.members.length > 0) {
|
|
||||||
member.id = objectsRegistry.add(sender, method)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert a real value into meta data.
|
// Convert a real value into meta data.
|
||||||
let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
||||||
// Determine the type of value.
|
// Determine the type of value.
|
||||||
|
@ -102,7 +90,6 @@ let valueToMeta = function (sender, value, optimizeSimpleObject = false) {
|
||||||
meta.id = objectsRegistry.add(sender, value)
|
meta.id = objectsRegistry.add(sender, value)
|
||||||
meta.members = getObjectMembers(value)
|
meta.members = getObjectMembers(value)
|
||||||
meta.proto = getObjectPrototype(value)
|
meta.proto = getObjectPrototype(value)
|
||||||
addFunctionProperties(sender, value, meta.members)
|
|
||||||
} else if (meta.type === 'buffer') {
|
} else if (meta.type === 'buffer') {
|
||||||
meta.value = Array.prototype.slice.call(value, 0)
|
meta.value = Array.prototype.slice.call(value, 0)
|
||||||
} else if (meta.type === 'promise') {
|
} else if (meta.type === 'promise') {
|
||||||
|
|
|
@ -99,7 +99,7 @@ const setObjectMembers = function (ref, object, metaId, members) {
|
||||||
|
|
||||||
let descriptor = { enumerable: member.enumerable }
|
let descriptor = { enumerable: member.enumerable }
|
||||||
if (member.type === 'method') {
|
if (member.type === 'method') {
|
||||||
let remoteMemberFunction = function () {
|
const remoteMemberFunction = function () {
|
||||||
if (this && this.constructor === remoteMemberFunction) {
|
if (this && this.constructor === remoteMemberFunction) {
|
||||||
// Constructor call.
|
// Constructor call.
|
||||||
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments))
|
let ret = ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', metaId, member.name, wrapArgs(arguments))
|
||||||
|
@ -110,13 +110,22 @@ const setObjectMembers = function (ref, object, metaId, members) {
|
||||||
return metaToValue(ret)
|
return metaToValue(ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrap function in proxy for accessing remote properties
|
||||||
|
let descriptorFunction = new Proxy(remoteMemberFunction, {
|
||||||
|
get: (target, property, receiver) => {
|
||||||
|
if (target.hasOwnProperty(property)) return target[property]
|
||||||
|
return metaToValue(ipcRenderer.sendSync('ELECTRON_BROWSER_MEMBER_GET', metaId, member.name))[property]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
descriptor.get = function () {
|
descriptor.get = function () {
|
||||||
remoteMemberFunction.ref = ref // The member should reference its object.
|
descriptorFunction.ref = ref // The member should reference its object.
|
||||||
return remoteMemberFunction
|
return descriptorFunction
|
||||||
}
|
}
|
||||||
// Enable monkey-patch the method
|
// Enable monkey-patch the method
|
||||||
descriptor.set = function (value) {
|
descriptor.set = function (value) {
|
||||||
remoteMemberFunction = value
|
descriptorFunction = value
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
descriptor.configurable = true
|
descriptor.configurable = true
|
||||||
|
@ -135,18 +144,9 @@ const setObjectMembers = function (ref, object, metaId, members) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.defineProperty(object, member.name, descriptor)
|
Object.defineProperty(object, member.name, descriptor)
|
||||||
addFunctionProperties(object, member)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include properties on member methods
|
|
||||||
const addFunctionProperties = (object, member) => {
|
|
||||||
if (member.type !== 'method') return
|
|
||||||
if (member.members == null || member.members.length === 0) return
|
|
||||||
const method = object[member.name]
|
|
||||||
setObjectMembers(method, method, member.id, member.members)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate object's prototype from descriptor.
|
// Populate object's prototype from descriptor.
|
||||||
// This matches |getObjectPrototype| in rpc-server.
|
// This matches |getObjectPrototype| in rpc-server.
|
||||||
const setObjectPrototype = function (ref, object, metaId, descriptor) {
|
const setObjectPrototype = function (ref, object, metaId, descriptor) {
|
||||||
|
|
|
@ -59,9 +59,11 @@ describe('ipc module', function () {
|
||||||
|
|
||||||
a = remote.require(path.join(fixtures, 'module', 'function-with-properties.js'))
|
a = remote.require(path.join(fixtures, 'module', 'function-with-properties.js'))
|
||||||
assert.equal(typeof a, 'object')
|
assert.equal(typeof a, 'object')
|
||||||
assert.equal(typeof a.foo, 'function')
|
assert.equal(a.foo(), 'hello')
|
||||||
assert.equal(a.foo.bar, 'baz')
|
assert.equal(a.foo.bar, 'baz')
|
||||||
assert.equal(a.foo.nested.prop, 'yes')
|
assert.equal(a.foo.nested.prop, 'yes')
|
||||||
|
assert.equal(a.foo.method1(), 'world')
|
||||||
|
assert.equal(a.foo.method1.prop1(), 123)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should work with static class members', function () {
|
it('should work with static class members', function () {
|
||||||
|
|
10
spec/fixtures/module/function-with-properties.js
vendored
10
spec/fixtures/module/function-with-properties.js
vendored
|
@ -1,8 +1,16 @@
|
||||||
function foo () {}
|
function foo () {
|
||||||
|
return 'hello'
|
||||||
|
}
|
||||||
foo.bar = 'baz'
|
foo.bar = 'baz'
|
||||||
foo.nested = {
|
foo.nested = {
|
||||||
prop: 'yes'
|
prop: 'yes'
|
||||||
}
|
}
|
||||||
|
foo.method1 = function () {
|
||||||
|
return 'world'
|
||||||
|
}
|
||||||
|
foo.method1.prop1 = function () {
|
||||||
|
return 123
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
foo: foo
|
foo: foo
|
||||||
|
|
Loading…
Reference in a new issue