-
Notifications
You must be signed in to change notification settings - Fork 15k
/
objects-registry.js
107 lines (92 loc) · 2.82 KB
/
objects-registry.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
'use strict'
const v8Util = process.atomBinding('v8_util')
class ObjectsRegistry {
constructor () {
this.nextId = 0
// Stores all objects by ref-counting.
// (id) => {object, count}
this.storage = {}
// Stores the IDs of objects referenced by WebContents.
// (webContentsId) => [id]
this.owners = {}
}
// Register a new object and return its assigned ID. If the object is already
// registered then the already assigned ID would be returned.
add (webContents, contextId, obj) {
// Get or assign an ID to the object.
const id = this.saveToStorage(obj)
// Add object to the set of referenced objects.
let owner = this.owners[contextId]
if (!owner) {
owner = this.owners[contextId] = new Set()
this.registerDeleteListener(webContents, contextId)
}
if (!owner.has(id)) {
owner.add(id)
// Increase reference count if not referenced before.
this.storage[id].count++
}
return id
}
// Get an object according to its ID.
get (id) {
const pointer = this.storage[id]
if (pointer != null) return pointer.object
}
// 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]
if (owner) {
// Remove the reference in owner.
owner.delete(id)
// Dereference from the storage.
this.dereference(id)
}
}
// Clear all references to objects refrenced by the WebContents.
clear (contextId) {
let owner = this.owners[contextId]
if (!owner) return
for (let id of owner) this.dereference(id)
delete this.owners[contextId]
}
// Private: Saves the object into storage and assigns an ID for it.
saveToStorage (object) {
let id = v8Util.getHiddenValue(object, 'atomId')
if (!id) {
id = ++this.nextId
this.storage[id] = {
count: 0,
object: object
}
v8Util.setHiddenValue(object, 'atomId', id)
}
return id
}
// Private: Dereference the object from store.
dereference (id) {
let pointer = this.storage[id]
if (pointer == null) {
return
}
pointer.count -= 1
if (pointer.count === 0) {
v8Util.deleteHiddenValue(pointer.object, 'atomId')
delete this.storage[id]
}
}
// Private: Clear the storage when webContents is reloaded/navigated.
registerDeleteListener (webContents, contextId) {
const processId = webContents.getProcessId()
const listener = (event, deletedProcessId) => {
if (deletedProcessId === processId) {
webContents.removeListener('render-view-deleted', listener)
this.clear(contextId)
}
}
webContents.on('render-view-deleted', listener)
}
}
module.exports = new ObjectsRegistry()