| 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 |