| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This file is part of Adblock Plus <http://adblockplus.org/>, | 2  * This file is part of Adblock Plus <http://adblockplus.org/>, | 
| 3  * Copyright (C) 2006-2014 Eyeo GmbH | 3  * Copyright (C) 2006-2014 Eyeo GmbH | 
| 4  * | 4  * | 
| 5  * Adblock Plus is free software: you can redistribute it and/or modify | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
| 6  * it under the terms of the GNU General Public License version 3 as | 6  * it under the terms of the GNU General Public License version 3 as | 
| 7  * published by the Free Software Foundation. | 7  * published by the Free Software Foundation. | 
| 8  * | 8  * | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 12  * GNU General Public License for more details. | 12  * GNU General Public License for more details. | 
| 13  * | 13  * | 
| 14  * You should have received a copy of the GNU General Public License | 14  * You should have received a copy of the GNU General Public License | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 16  */ | 16  */ | 
| 17 | 17 | 
| 18 "use strict"; | 18 "use strict"; | 
| 19 | 19 | 
| 20 let {fixedPropertyDescriptor, getViewsForType, defineProperties} = require("type
     dObjects/utils"); | 20 let {fixedPropertyDescriptor, getViewsForType, defineProperties} = require("type
     dObjects/utils"); | 
| 21 let {Reference, TypedReference} = require("typedObjects/references"); | 21 let {Reference, TypedReference} = require("typedObjects/references"); | 
|  | 22 let {uint8, uint32} = require("typedObjects/primitiveTypes"); | 
|  | 23 | 
|  | 24 const STATE_UNINITIALIZED = 0; | 
|  | 25 const STATE_CREATED = 1; | 
|  | 26 const STATE_RELEASING = 2; | 
| 22 | 27 | 
| 23 /** | 28 /** | 
| 24  * List of registered types (typeId is the index in that array). | 29  * List of registered types (typeId is the index in that array). | 
| 25  */ | 30  */ | 
| 26 let types = []; | 31 let types = []; | 
| 27 | 32 | 
| 28 function fromReference(reference) | 33 function fromReference(reference) | 
| 29 { | 34 { | 
| 30   let typeInfo = reference.typeInfo; | 35   let typeInfo = reference.typeInfo; | 
| 31   if (typeInfo) | 36   if (typeInfo) | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 76       this.firstFree.targetBufferIndex = bufferIndex; | 81       this.firstFree.targetBufferIndex = bufferIndex; | 
| 77       this.firstFree.targetByteOffset = nextByteOffset; | 82       this.firstFree.targetByteOffset = nextByteOffset; | 
| 78     } | 83     } | 
| 79   } | 84   } | 
| 80 | 85 | 
| 81   let result = Object.create(this.proto, { | 86   let result = Object.create(this.proto, { | 
| 82     typeId: fixedPropertyDescriptor(this.typeId), | 87     typeId: fixedPropertyDescriptor(this.typeId), | 
| 83     bufferIndex: fixedPropertyDescriptor(bufferIndex), | 88     bufferIndex: fixedPropertyDescriptor(bufferIndex), | 
| 84     byteOffset: fixedPropertyDescriptor(byteOffset) | 89     byteOffset: fixedPropertyDescriptor(byteOffset) | 
| 85   }); | 90   }); | 
|  | 91 | 
|  | 92   result._state = STATE_UNINITIALIZED; | 
|  | 93   for (let [prop, value] of this.cleanupValues) | 
|  | 94     result[prop] = value; | 
|  | 95   result._state = STATE_CREATED; | 
|  | 96   result._refCount = 1; | 
|  | 97 | 
| 86   if (this.constructor) | 98   if (this.constructor) | 
| 87     this.constructor.apply(result, arguments); | 99     this.constructor.apply(result, arguments); | 
| 88   return result; | 100   return result; | 
| 89 } | 101 } | 
| 90 | 102 | 
|  | 103 function free(obj) | 
|  | 104 { | 
|  | 105   try | 
|  | 106   { | 
|  | 107     if (this.destructor) | 
|  | 108     { | 
|  | 109       this.destructor.call(obj); | 
|  | 110       if (obj._refCount | 0) | 
|  | 111         throw new Error("Reference count is no longer zero after calling the des
     tructor"); | 
|  | 112     } | 
|  | 113   } | 
|  | 114   finally | 
|  | 115   { | 
|  | 116     for (let [prop, value] of this.cleanupValues) | 
|  | 117       obj[prop] = value; | 
|  | 118 | 
|  | 119     // Mark object as first free spot | 
|  | 120     let oldFreeBufferIndex = this.firstFree.bufferIndex; | 
|  | 121     let oldFreeByteOffset = this.firstFree.byteOffset; | 
|  | 122     this.firstFree.bufferIndex = obj.bufferIndex; | 
|  | 123     this.firstFree.byteOffset = obj.byteOffset; | 
|  | 124     this.firstFree.targetBufferIndex = oldFreeBufferIndex; | 
|  | 125     this.firstFree.targetByteOffset = oldFreeByteOffset; | 
|  | 126   } | 
|  | 127 } | 
|  | 128 | 
| 91 function createGetter(offset) | 129 function createGetter(offset) | 
| 92 { | 130 { | 
| 93   offset = offset | 0; | 131   offset = offset | 0; | 
| 94 | 132 | 
| 95   let views = Array.prototype.slice.call(arguments, 1); | 133   let views = Array.prototype.slice.call(arguments, 1); | 
| 96   let reference = new Reference(types, views); | 134   let reference = new Reference(types, views); | 
| 97   return function() | 135   return function() | 
| 98   { | 136   { | 
| 99     reference.bufferIndex = this.bufferIndex | 0; | 137     reference.bufferIndex = this.bufferIndex | 0; | 
| 100     reference.byteOffset = (this.byteOffset | 0) + offset; | 138     reference.byteOffset = (this.byteOffset | 0) + offset; | 
| 101     return fromReference(reference); | 139     return fromReference(reference); | 
| 102   }; | 140   }; | 
| 103 } | 141 } | 
| 104 | 142 | 
| 105 function createSetter(typeId, offset) | 143 function createSetter(typeId, offset) | 
| 106 { | 144 { | 
| 107   typeId = typeId | 0; | 145   typeId = typeId | 0; | 
| 108   offset = offset | 0; | 146   offset = offset | 0; | 
| 109 | 147 | 
| 110   let views = Array.prototype.slice.call(arguments, 2); | 148   let views = Array.prototype.slice.call(arguments, 2); | 
| 111   let reference = new Reference(types, views); | 149   let reference = new Reference(types, views); | 
| 112   return function(value) | 150   return function(value) | 
| 113   { | 151   { | 
| 114     if (value && !isinstance(typeId, value)) | 152     if (value && !isinstance(typeId, value)) | 
| 115       throw new Error("Incompatible type"); | 153       throw new Error("Incompatible type"); | 
| 116 | 154 | 
| 117     reference.bufferIndex = this.bufferIndex | 0; | 155     reference.bufferIndex = this.bufferIndex | 0; | 
| 118     reference.byteOffset = (this.byteOffset | 0) + offset; | 156     reference.byteOffset = (this.byteOffset | 0) + offset; | 
|  | 157 | 
|  | 158     if ((this._state | 0) > STATE_UNINITIALIZED) | 
|  | 159     { | 
|  | 160       let oldValue = fromReference(reference); | 
|  | 161       if (oldValue) | 
|  | 162         oldValue.release(); | 
|  | 163     } | 
|  | 164 | 
| 119     if (value) | 165     if (value) | 
| 120     { | 166     { | 
| 121       reference.typeId = value.typeId; | 167       reference.typeId = value.typeId; | 
| 122       reference.targetBufferIndex = value.bufferIndex; | 168       reference.targetBufferIndex = value.bufferIndex; | 
| 123       reference.targetByteOffset = value.byteOffset; | 169       reference.targetByteOffset = value.byteOffset; | 
|  | 170       value.retain(); | 
| 124     } | 171     } | 
| 125     else | 172     else | 
| 126       reference.typeId = -1; | 173       reference.typeId = -1; | 
| 127   }; | 174   }; | 
| 128 } | 175 } | 
| 129 | 176 | 
| 130 /** | 177 /** | 
| 131  * Overridden methods get the respective method of the superclass as the first | 178  * Overridden methods get the respective method of the superclass as the first | 
| 132  * parameter. This function will create a wrapper function for the method that | 179  * parameter. This function will create a wrapper function for the method that | 
| 133  * forwards all arguments to the actual methods but also injects super as first | 180  * forwards all arguments to the actual methods but also injects super as first | 
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 191       methods[name] = fixedPropertyDescriptor(type); | 238       methods[name] = fixedPropertyDescriptor(type); | 
| 192     } | 239     } | 
| 193     else | 240     else | 
| 194       throw new Error("Unrecognized type " + type + " given for property " + nam
     e); | 241       throw new Error("Unrecognized type " + type + " given for property " + nam
     e); | 
| 195   } | 242   } | 
| 196 | 243 | 
| 197   let proto = {}; | 244   let proto = {}; | 
| 198   let buffers = []; | 245   let buffers = []; | 
| 199   let viewTypes = []; | 246   let viewTypes = []; | 
| 200   let views = []; | 247   let views = []; | 
| 201   let byteLength = defineProperties(proto, properties, viewTypes, views, 0); | 248   let cleanupValues = []; | 
|  | 249   let byteLength = defineProperties(proto, properties, viewTypes, views, 0, clea
     nupValues); | 
| 202   Object.defineProperties(proto, methods); | 250   Object.defineProperties(proto, methods); | 
| 203 | 251 | 
| 204   // Round up to be a multiple of the maximal property size | 252   // Round up to be a multiple of the maximal property size | 
| 205   byteLength = ((byteLength - 1) | (maxReferenceLength - 1)) + 1; | 253   byteLength = ((byteLength - 1) | (maxReferenceLength - 1)) + 1; | 
| 206 | 254 | 
| 207   // We need to be able to store a typed reference in the object's buffer | 255   // We need to be able to store a typed reference in the object's buffer | 
| 208   byteLength = Math.max(byteLength, TypedReference.byteLength) | 0; | 256   byteLength = Math.max(byteLength, TypedReference.byteLength) | 0; | 
| 209   let typedReferenceViews = getViewsForType(TypedReference, viewTypes, views); | 257   let typedReferenceViews = getViewsForType(TypedReference, viewTypes, views); | 
| 210 | 258 | 
| 211   // Take constructor from meta parameter, allow calling superclass constructor. | 259   // Take constructor and destructor from meta parameters, allow calling | 
|  | 260   // superclass constructor/destructor. | 
| 212   let constructor = parentTypeInfo && parentTypeInfo.constructor; | 261   let constructor = parentTypeInfo && parentTypeInfo.constructor; | 
| 213   if (meta.hasOwnProperty("constructor") && typeof meta.constructor == "function
     ") | 262   if (meta.hasOwnProperty("constructor") && typeof meta.constructor == "function
     ") | 
| 214   { | 263   { | 
| 215     if (constructor) | 264     if (constructor) | 
| 216       constructor = createSubclassMethod(meta.constructor, constructor); | 265       constructor = createSubclassMethod(meta.constructor, constructor); | 
| 217     else | 266     else | 
| 218       constructor = meta.constructor; | 267       constructor = meta.constructor; | 
| 219   } | 268   } | 
| 220 | 269 | 
|  | 270   let destructor = parentTypeInfo && parentTypeInfo.destructor; | 
|  | 271   if (meta.hasOwnProperty("destructor") && typeof meta.destructor == "function") | 
|  | 272   { | 
|  | 273     if (destructor) | 
|  | 274       destructor = createSubclassMethod(meta.destructor, destructor); | 
|  | 275     else | 
|  | 276       destructor = meta.destructor; | 
|  | 277   } | 
|  | 278 | 
| 221   let typeId = types.length | 0; | 279   let typeId = types.length | 0; | 
| 222   let typeInfo = { | 280   let typeInfo = { | 
| 223     byteLength: byteLength, | 281     byteLength: byteLength, | 
| 224     bufferSize: "bufferSize" in meta ? Math.max(meta.bufferSize | 0, 2) : 128, | 282     bufferSize: "bufferSize" in meta ? Math.max(meta.bufferSize | 0, 2) : 128, | 
| 225     firstFree: new TypedReference(typeId, typedReferenceViews), | 283     firstFree: new TypedReference(typeId, typedReferenceViews), | 
| 226     proto: proto, | 284     proto: proto, | 
| 227     properties: properties, | 285     properties: properties, | 
| 228     methods: methods, | 286     methods: methods, | 
| 229     buffers: buffers, | 287     buffers: buffers, | 
| 230     viewTypes: viewTypes, | 288     viewTypes: viewTypes, | 
| 231     views: views, | 289     views: views, | 
|  | 290     cleanupValues: cleanupValues, | 
| 232     typeId: typeId, | 291     typeId: typeId, | 
| 233     parentTypeInfo: parentTypeInfo, | 292     parentTypeInfo: parentTypeInfo, | 
| 234     constructor: constructor | 293     constructor: constructor, | 
|  | 294     destructor: destructor | 
| 235   }; | 295   }; | 
| 236 | 296 | 
| 237   let result = create.bind(typeInfo); | 297   let result = create.bind(typeInfo); | 
| 238   Object.defineProperties(result, { | 298   Object.defineProperties(result, { | 
| 239     byteLength: fixedPropertyDescriptor(byteLength), | 299     byteLength: fixedPropertyDescriptor(byteLength), | 
| 240 | 300 | 
| 241     referenceLength: fixedPropertyDescriptor(Reference.byteLength), | 301     referenceLength: fixedPropertyDescriptor(Reference.byteLength), | 
| 242     viewTypes: fixedPropertyDescriptor(Reference.viewTypes), | 302     viewTypes: fixedPropertyDescriptor(Reference.viewTypes), | 
|  | 303     cleanupValue: fixedPropertyDescriptor(null), | 
| 243 | 304 | 
| 244     typeId: fixedPropertyDescriptor(typeId), | 305     typeId: fixedPropertyDescriptor(typeId), | 
| 245     extend: fixedPropertyDescriptor(extend.bind(null, typeInfo)), | 306     extend: fixedPropertyDescriptor(extend.bind(null, typeInfo)), | 
| 246     isinstance: fixedPropertyDescriptor(isinstance.bind(null, typeId)), | 307     isinstance: fixedPropertyDescriptor(isinstance.bind(null, typeId)), | 
| 247 | 308 | 
| 248     createGetter: fixedPropertyDescriptor(createGetter), | 309     createGetter: fixedPropertyDescriptor(createGetter), | 
| 249     createSetter: fixedPropertyDescriptor(createSetter.bind(null, typeId)) | 310     createSetter: fixedPropertyDescriptor(createSetter.bind(null, typeId)) | 
| 250   }); | 311   }); | 
| 251   types.push(typeInfo); | 312   types.push(typeInfo); | 
| 252   return result; | 313   return result; | 
| 253 } | 314 } | 
| 254 | 315 | 
| 255 function isinstance(typeId, obj) | 316 function isinstance(typeId, obj) | 
| 256 { | 317 { | 
| 257   typeId = typeId | 0; | 318   typeId = typeId | 0; | 
| 258 | 319 | 
| 259   // TODO: This could be optimized by compiling the list of all subclasses for | 320   // TODO: This could be optimized by compiling the list of all subclasses for | 
| 260   // each type up front. Question is whether this is worth it. | 321   // each type up front. Question is whether this is worth it. | 
| 261   let typeInfo = types[obj.typeId | 0]; | 322   let typeInfo = types[obj.typeId | 0]; | 
| 262   while (typeInfo) | 323   while (typeInfo) | 
| 263   { | 324   { | 
| 264     if ((typeInfo.typeId | 0) == typeId) | 325     if ((typeInfo.typeId | 0) == typeId) | 
| 265       return true; | 326       return true; | 
| 266     typeInfo = typeInfo.parentTypeInfo; | 327     typeInfo = typeInfo.parentTypeInfo; | 
| 267   } | 328   } | 
| 268   return false; | 329   return false; | 
| 269 } | 330 } | 
| 270 | 331 | 
| 271 let ObjectBase = exports.ObjectBase = extend(null, { | 332 let ObjectBase = exports.ObjectBase = extend(null, { | 
|  | 333   _state: uint8, | 
|  | 334   _refCount: uint32, | 
|  | 335 | 
| 272   equals: function(obj) | 336   equals: function(obj) | 
| 273   { | 337   { | 
| 274     if (!obj) | 338     if (!obj) | 
| 275       return false; | 339       return false; | 
| 276     return this.typeId == obj.typeId && this.bufferIndex == obj.bufferIndex && t
     his.byteOffset == obj.byteOffset; | 340     return this.typeId == obj.typeId && this.bufferIndex == obj.bufferIndex && t
     his.byteOffset == obj.byteOffset; | 
|  | 341   }, | 
|  | 342 | 
|  | 343   retain: function() | 
|  | 344   { | 
|  | 345     this._refCount++; | 
|  | 346   }, | 
|  | 347 | 
|  | 348   release: function() | 
|  | 349   { | 
|  | 350     this._refCount--; | 
|  | 351     if (this._refCount == 0 && this._state < STATE_RELEASING) | 
|  | 352     { | 
|  | 353       this._state = STATE_RELEASING; | 
|  | 354       free.call(types[this.typeId | 0], this); | 
|  | 355     } | 
| 277   } | 356   } | 
| 278 }, null); | 357 }, null); | 
| 279 | 358 | 
| 280 exports.ObjectType = ObjectBase.extend; | 359 exports.ObjectType = ObjectBase.extend; | 
| OLD | NEW | 
|---|