const frameToGuest = {}
// Copy attribute of |parent| to |child| if it is not defined in |child|.
-const mergeOptions = function (child, parent) {
- let key, value
- for (key in parent) {
+const mergeOptions = function (child, parent, visited) {
+ // Check for circular reference.
+ if (visited == null) visited = new Set()
+ if (visited.has(parent)) return
+
+ visited.add(parent)
+ for (const key in parent) {
if (!hasProp.call(parent, key)) continue
- value = parent[key]
- if (!(key in child)) {
- if (typeof value === 'object') {
- child[key] = mergeOptions({}, value)
- } else {
- child[key] = value
- }
+ if (key in child) continue
+
+ const value = parent[key]
+ if (typeof value === 'object') {
+ child[key] = mergeOptions({}, value, visited)
+ } else {
+ child[key] = value
}
}
+ visited.delete(parent)
+
return child
}
w = BrowserWindow.fromId(ipcRenderer.sendSync('create-window-with-options-cycle'))
w.loadURL('file://' + fixtures + '/pages/window-open.html')
w.webContents.once('new-window', (event, url, frameName, disposition, options) => {
- assert.deepEqual(options, {
- show: false,
- foo: {
- bar: null
+ assert.equal(options.show, false)
+ assert.deepEqual(options.foo, {
+ bar: null,
+ baz: {
+ hello: {
+ world: true
+ }
}
})
done()
// nulled out at the IPC layer
const foo = {}
foo.bar = foo
+ foo.baz = {
+ hello: {
+ world: true
+ }
+ }
const window = new BrowserWindow({show: false, foo: foo})
event.returnValue = window.id
})