electron/atom/browser/lib/objects-registry.js
Cheng Zhao 2b04af4349 No longer need to count the references in webContents
All remote objects are now cached in renderer process, so there is
always only one reference to one remote object for each webContents.
2016-02-22 15:24:18 +08:00

94 lines
2.3 KiB
JavaScript

'use strict';
const EventEmitter = require('events').EventEmitter;
const v8Util = process.atomBinding('v8_util');
class ObjectsRegistry extends EventEmitter {
constructor() {
super();
this.setMaxListeners(Number.MAX_VALUE);
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(webContentsId, obj) {
// Get or assign an ID to the object.
let id = this.saveToStorage(obj);
// Add object to the set of referenced objects.
let owner = this.owners[webContentsId];
if (!owner)
owner = this.owners[webContentsId] = new Set();
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) {
return this.storage[id].object;
}
// Dereference an object according to its ID.
remove(webContentsId, id) {
// Dereference from the storage.
this.dereference(id);
// Also remove the reference in owner.
this.owners[webContentsId].delete(id);
}
// Clear all references to objects refrenced by the WebContents.
clear(webContentsId) {
this.emit(`clear-${webContentsId}`);
let owner = this.owners[webContentsId];
if (!owner)
return;
for (let id of owner)
this.dereference(id);
delete this.owners[webContentsId];
}
// 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');
return delete this.storage[id];
}
}
}
module.exports = new ObjectsRegistry;