Maintain visted objects as a stack for cycle detection
This commit is contained in:
parent
71a8bac12a
commit
564b0cace5
1 changed files with 35 additions and 28 deletions
|
@ -5,32 +5,41 @@ const {ipcRenderer, isPromise, CallbacksRegistry} = require('electron')
|
|||
|
||||
const callbacksRegistry = new CallbacksRegistry()
|
||||
|
||||
var remoteObjectCache = v8Util.createIDWeakMap()
|
||||
const remoteObjectCache = v8Util.createIDWeakMap()
|
||||
|
||||
// Check for circular reference.
|
||||
var isCircular = function (field, visited) {
|
||||
const isCircular = function (field, visited) {
|
||||
if (visited.has(field)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (typeof field === 'object') {
|
||||
if (visited.includes(field)) {
|
||||
return true
|
||||
}
|
||||
visited.push(field)
|
||||
visited.add(field)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Convert the arguments object into an array of meta data.
|
||||
var wrapArgs = function (args, visited) {
|
||||
var valueToMeta
|
||||
const wrapArgs = function (args, visited) {
|
||||
if (visited == null) {
|
||||
visited = []
|
||||
visited = new Set()
|
||||
}
|
||||
valueToMeta = function (value) {
|
||||
var field, prop, ret
|
||||
if (Array.isArray(value)) {
|
||||
|
||||
const valueToMeta = function (value) {
|
||||
if (isCircular(value, visited)) {
|
||||
return {
|
||||
type: 'array',
|
||||
value: isCircular(value, visited) ? [] : wrapArgs(value, visited)
|
||||
type: 'value',
|
||||
value: null
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
let meta = {
|
||||
type: 'array',
|
||||
value: wrapArgs(value, visited)
|
||||
}
|
||||
visited.delete(value)
|
||||
return meta
|
||||
} else if (Buffer.isBuffer(value)) {
|
||||
return {
|
||||
type: 'buffer',
|
||||
|
@ -56,19 +65,19 @@ var wrapArgs = function (args, visited) {
|
|||
}
|
||||
}
|
||||
|
||||
ret = {
|
||||
let meta = {
|
||||
type: 'object',
|
||||
name: value.constructor != null ? value.constructor.name : '',
|
||||
members: []
|
||||
}
|
||||
for (prop in value) {
|
||||
field = value[prop]
|
||||
ret.members.push({
|
||||
for (let prop in value) {
|
||||
meta.members.push({
|
||||
name: prop,
|
||||
value: valueToMeta(isCircular(field, visited) ? null : field)
|
||||
value: valueToMeta(value[prop])
|
||||
})
|
||||
}
|
||||
return ret
|
||||
visited.delete(value)
|
||||
return meta
|
||||
} else if (typeof value === 'function' && v8Util.getHiddenValue(value, 'returnValue')) {
|
||||
return {
|
||||
type: 'function-with-return-value',
|
||||
|
@ -93,7 +102,7 @@ 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 (ref, object, metaId, members) {
|
||||
const setObjectMembers = function (ref, object, metaId, members) {
|
||||
for (let member of members) {
|
||||
if (object.hasOwnProperty(member.name)) continue
|
||||
|
||||
|
@ -140,7 +149,7 @@ let setObjectMembers = function (ref, object, metaId, members) {
|
|||
|
||||
// Populate object's prototype from descriptor.
|
||||
// This matches |getObjectPrototype| in rpc-server.
|
||||
let setObjectPrototype = function (ref, object, metaId, descriptor) {
|
||||
const setObjectPrototype = function (ref, object, metaId, descriptor) {
|
||||
if (descriptor === null) return
|
||||
let proto = {}
|
||||
setObjectMembers(ref, proto, metaId, descriptor.members)
|
||||
|
@ -149,7 +158,7 @@ let setObjectPrototype = function (ref, object, metaId, descriptor) {
|
|||
}
|
||||
|
||||
// Convert meta data from browser into real value.
|
||||
let metaToValue = function (meta) {
|
||||
const metaToValue = function (meta) {
|
||||
var el, i, len, ref1, results, ret
|
||||
switch (meta.type) {
|
||||
case 'value':
|
||||
|
@ -218,7 +227,7 @@ let metaToValue = function (meta) {
|
|||
}
|
||||
|
||||
// Construct a plain object from the meta.
|
||||
var metaToPlainObject = function (meta) {
|
||||
const metaToPlainObject = function (meta) {
|
||||
var i, len, obj, ref1
|
||||
obj = (function () {
|
||||
switch (meta.type) {
|
||||
|
@ -290,8 +299,7 @@ exports.__defineGetter__('process', function () {
|
|||
|
||||
// Create a funtion that will return the specifed value when called in browser.
|
||||
exports.createFunctionWithReturnValue = function (returnValue) {
|
||||
var func
|
||||
func = function () {
|
||||
const func = function () {
|
||||
return returnValue
|
||||
}
|
||||
v8Util.setHiddenValue(func, 'returnValue', true)
|
||||
|
@ -300,7 +308,6 @@ exports.createFunctionWithReturnValue = function (returnValue) {
|
|||
|
||||
// Get the guest WebContents from guestInstanceId.
|
||||
exports.getGuestWebContents = function (guestInstanceId) {
|
||||
var meta
|
||||
meta = ipcRenderer.sendSync('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId)
|
||||
const meta = ipcRenderer.sendSync('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', guestInstanceId)
|
||||
return metaToValue(meta)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue