fix: use webContentsId with contextId together (#13749)
After after using `processId-contextCounter` as contextId, it may happen that contexts in different WebContents sharing the same renderer process get the same contextId. Using webContentsId as part of key in ObjectsRegistry can fix this.
This commit is contained in:
parent
d7b41462af
commit
3094f62f0b
7 changed files with 26 additions and 53 deletions
|
@ -2,6 +2,10 @@
|
|||
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
|
||||
const getOwnerKey = (webContents, contextId) => {
|
||||
return `${webContents.id}-${contextId}`
|
||||
}
|
||||
|
||||
class ObjectsRegistry {
|
||||
constructor () {
|
||||
this.nextId = 0
|
||||
|
@ -11,7 +15,7 @@ class ObjectsRegistry {
|
|||
this.storage = {}
|
||||
|
||||
// Stores the IDs of objects referenced by WebContents.
|
||||
// (webContentsId) => [id]
|
||||
// (ownerKey) => [id]
|
||||
this.owners = {}
|
||||
}
|
||||
|
||||
|
@ -22,9 +26,10 @@ class ObjectsRegistry {
|
|||
const id = this.saveToStorage(obj)
|
||||
|
||||
// Add object to the set of referenced objects.
|
||||
let owner = this.owners[contextId]
|
||||
const ownerKey = getOwnerKey(webContents, contextId)
|
||||
let owner = this.owners[ownerKey]
|
||||
if (!owner) {
|
||||
owner = this.owners[contextId] = new Set()
|
||||
owner = this.owners[ownerKey] = new Set()
|
||||
this.registerDeleteListener(webContents, contextId)
|
||||
}
|
||||
if (!owner.has(id)) {
|
||||
|
@ -44,8 +49,9 @@ class ObjectsRegistry {
|
|||
// Dereference an object according to its ID.
|
||||
// Note that an object may be double-freed (cleared when page is reloaded, and
|
||||
// then garbage collected in old page).
|
||||
remove (contextId, id) {
|
||||
let owner = this.owners[contextId]
|
||||
remove (webContents, contextId, id) {
|
||||
const ownerKey = getOwnerKey(webContents, contextId)
|
||||
let owner = this.owners[ownerKey]
|
||||
if (owner) {
|
||||
// Remove the reference in owner.
|
||||
owner.delete(id)
|
||||
|
@ -55,13 +61,14 @@ class ObjectsRegistry {
|
|||
}
|
||||
|
||||
// Clear all references to objects refrenced by the WebContents.
|
||||
clear (contextId) {
|
||||
let owner = this.owners[contextId]
|
||||
clear (webContents, contextId) {
|
||||
const ownerKey = getOwnerKey(webContents, contextId)
|
||||
let owner = this.owners[ownerKey]
|
||||
if (!owner) return
|
||||
|
||||
for (let id of owner) this.dereference(id)
|
||||
|
||||
delete this.owners[contextId]
|
||||
delete this.owners[ownerKey]
|
||||
}
|
||||
|
||||
// Private: Saves the object into storage and assigns an ID for it.
|
||||
|
@ -91,13 +98,13 @@ class ObjectsRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
// Private: Clear the storage when webContents is reloaded/navigated.
|
||||
// Private: Clear the storage when renderer process is destroyed.
|
||||
registerDeleteListener (webContents, contextId) {
|
||||
const processId = webContents.getProcessId()
|
||||
const listener = (event, deletedProcessId) => {
|
||||
if (deletedProcessId === processId) {
|
||||
webContents.removeListener('render-view-deleted', listener)
|
||||
this.clear(contextId)
|
||||
this.clear(webContents, contextId)
|
||||
}
|
||||
}
|
||||
webContents.on('render-view-deleted', listener)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue