134 lines
		
	
	
	
		
			3.2 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			134 lines
		
	
	
	
		
			3.2 KiB
			
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|   | var EventEmitter, ObjectsRegistry, v8Util, | ||
|  |   extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, | ||
|  |   hasProp = {}.hasOwnProperty; | ||
|  | 
 | ||
|  | EventEmitter = require('events').EventEmitter; | ||
|  | 
 | ||
|  | v8Util = process.atomBinding('v8_util'); | ||
|  | 
 | ||
|  | ObjectsRegistry = (function(superClass) { | ||
|  |   extend(ObjectsRegistry, superClass); | ||
|  | 
 | ||
|  |   function ObjectsRegistry() { | ||
|  |     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) => (count)} | ||
|  |      */ | ||
|  |     this.owners = {}; | ||
|  |   } | ||
|  | 
 | ||
|  | 
 | ||
|  |   /* | ||
|  |     Register a new object, the object would be kept referenced until you release | ||
|  |     it explicitly. | ||
|  |    */ | ||
|  | 
 | ||
|  |   ObjectsRegistry.prototype.add = function(webContentsId, obj) { | ||
|  |     var base, base1, id; | ||
|  |     id = this.saveToStorage(obj); | ||
|  | 
 | ||
|  |     /* Remember the owner. */ | ||
|  |     if ((base = this.owners)[webContentsId] == null) { | ||
|  |       base[webContentsId] = {}; | ||
|  |     } | ||
|  |     if ((base1 = this.owners[webContentsId])[id] == null) { | ||
|  |       base1[id] = 0; | ||
|  |     } | ||
|  |     this.owners[webContentsId][id]++; | ||
|  | 
 | ||
|  |     /* Returns object's id */ | ||
|  |     return id; | ||
|  |   }; | ||
|  | 
 | ||
|  | 
 | ||
|  |   /* Get an object according to its ID. */ | ||
|  | 
 | ||
|  |   ObjectsRegistry.prototype.get = function(id) { | ||
|  |     var ref; | ||
|  |     return (ref = this.storage[id]) != null ? ref.object : void 0; | ||
|  |   }; | ||
|  | 
 | ||
|  | 
 | ||
|  |   /* Dereference an object according to its ID. */ | ||
|  | 
 | ||
|  |   ObjectsRegistry.prototype.remove = function(webContentsId, id) { | ||
|  |     var pointer; | ||
|  |     this.dereference(id, 1); | ||
|  | 
 | ||
|  |     /* Also reduce the count in owner. */ | ||
|  |     pointer = this.owners[webContentsId]; | ||
|  |     if (pointer == null) { | ||
|  |       return; | ||
|  |     } | ||
|  |     --pointer[id]; | ||
|  |     if (pointer[id] === 0) { | ||
|  |       return delete pointer[id]; | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  | 
 | ||
|  |   /* Clear all references to objects refrenced by the WebContents. */ | ||
|  | 
 | ||
|  |   ObjectsRegistry.prototype.clear = function(webContentsId) { | ||
|  |     var count, id, ref; | ||
|  |     this.emit("clear-" + webContentsId); | ||
|  |     if (this.owners[webContentsId] == null) { | ||
|  |       return; | ||
|  |     } | ||
|  |     ref = this.owners[webContentsId]; | ||
|  |     for (id in ref) { | ||
|  |       count = ref[id]; | ||
|  |       this.dereference(id, count); | ||
|  |     } | ||
|  |     return delete this.owners[webContentsId]; | ||
|  |   }; | ||
|  | 
 | ||
|  | 
 | ||
|  |   /* Private: Saves the object into storage and assigns an ID for it. */ | ||
|  | 
 | ||
|  |   ObjectsRegistry.prototype.saveToStorage = function(object) { | ||
|  |     var id; | ||
|  |     id = v8Util.getHiddenValue(object, 'atomId'); | ||
|  |     if (!id) { | ||
|  |       id = ++this.nextId; | ||
|  |       this.storage[id] = { | ||
|  |         count: 0, | ||
|  |         object: object | ||
|  |       }; | ||
|  |       v8Util.setHiddenValue(object, 'atomId', id); | ||
|  |     } | ||
|  |     ++this.storage[id].count; | ||
|  |     return id; | ||
|  |   }; | ||
|  | 
 | ||
|  | 
 | ||
|  |   /* Private: Dereference the object from store. */ | ||
|  | 
 | ||
|  |   ObjectsRegistry.prototype.dereference = function(id, count) { | ||
|  |     var pointer; | ||
|  |     pointer = this.storage[id]; | ||
|  |     if (pointer == null) { | ||
|  |       return; | ||
|  |     } | ||
|  |     pointer.count -= count; | ||
|  |     if (pointer.count === 0) { | ||
|  |       v8Util.deleteHiddenValue(pointer.object, 'atomId'); | ||
|  |       return delete this.storage[id]; | ||
|  |     } | ||
|  |   }; | ||
|  | 
 | ||
|  |   return ObjectsRegistry; | ||
|  | 
 | ||
|  | })(EventEmitter); | ||
|  | 
 | ||
|  | module.exports = new ObjectsRegistry; |