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 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 if (index < 0) | 80 if (index < 0) |
81 { | 81 { |
82 index = (viewTypes.push(viewType) | 0) - 1; | 82 index = (viewTypes.push(viewType) | 0) - 1; |
83 views.push([]); | 83 views.push([]); |
84 } | 84 } |
85 result.push(views[index]); | 85 result.push(views[index]); |
86 } | 86 } |
87 return result; | 87 return result; |
88 }; | 88 }; |
89 | 89 |
| 90 /** |
| 91 * Creates a wrapper function for a setter that will call the watcher function |
| 92 * with the new value of the property before executing the actual setter. |
| 93 */ |
| 94 function watchSetter(/**Function*/ setter, /**Function*/ watcher) /**Function*/ |
| 95 { |
| 96 return function(value) |
| 97 { |
| 98 setter.call(this, watcher.call(this, value)); |
| 99 } |
| 100 } |
| 101 |
| 102 /** |
| 103 * Creates a parameter-less wrapper function around a getter that will get |
| 104 * bufferIndex and byteOffset parameters from object properties. |
| 105 */ |
| 106 function wrapGetter(/**Function*/ getter) /**Function*/ |
| 107 { |
| 108 return function() |
| 109 { |
| 110 return getter.call(this, this.bufferIndex, this.byteOffset); |
| 111 } |
| 112 } |
| 113 |
| 114 /** |
| 115 * Creates a wrapper function around a setter with value as the only parameter, |
| 116 * the bufferIndex and byteOffset parameters will be retrieved from object |
| 117 * properties. |
| 118 */ |
| 119 function wrapSetter(/**Function*/ setter) /**Function*/ |
| 120 { |
| 121 return function(value) |
| 122 { |
| 123 return setter.call(this, this.bufferIndex, this.byteOffset, value); |
| 124 } |
| 125 } |
| 126 |
90 /** | 127 /** |
91 * Defines properties with given name and type on an object. | 128 * Defines properties with given name and type on an object. |
92 * | 129 * |
93 * @param obj object to define properties on | 130 * @param obj object to define properties on |
94 * @param properties object mapping property names to their respective types | 131 * @param properties object mapping property names to their respective types |
95 * @param viewTypes see getViewsForType() | 132 * @param viewTypes see getViewsForType() |
96 * @param views see getViewsForType() | 133 * @param views see getViewsForType() |
97 * @param [offset] byte array offset at which the properties should start | 134 * @param [offset] byte array offset at which the properties should start |
98 * @param [cleanupValues] array of property/value combinations to be set when th
e object is created or destroyed | 135 * @param [watchers] map of watcher functions to be called when a particular pro
perty is being set |
| 136 * @param [initialValues] array of property/value combinations to be set when th
e object is created or destroyed |
99 * @return new start offset for additional properties | 137 * @return new start offset for additional properties |
100 */ | 138 */ |
101 exports.defineProperties = function defineProperties(obj, properties, viewTypes,
views, offset, cleanupValues) | 139 exports.defineProperties = function defineProperties(obj, properties, viewTypes,
views, offset, watchers, initialValues) |
102 { | 140 { |
103 offset = offset | 0; | 141 offset = offset | 0; |
104 | 142 |
105 let propList = []; | 143 let propList = []; |
106 for (let name in properties) | 144 for (let name in properties) |
107 propList.push([name, properties[name]]); | 145 propList.push([name, properties[name]]); |
108 | 146 |
109 // Put larger properties first to make sure alignment requirements are met. | 147 // Put larger properties first to make sure alignment requirements are met. |
110 propList.sort(function(a, b) | 148 propList.sort(function(a, b) |
111 { | 149 { |
112 return b[1].referenceLength - a[1].referenceLength; | 150 return b[1].referenceLength - a[1].referenceLength; |
113 }); | 151 }); |
114 | 152 |
115 // Generates getters and setters for each property. | 153 // Generates getters and setters for each property. |
116 let descriptors = {}; | 154 let descriptors = {}; |
117 for (let i = 0, l = propList.length | 0; i < l; i++) | 155 for (let i = 0, l = propList.length | 0; i < l; i++) |
118 { | 156 { |
119 let [name, type] = propList[i]; | 157 let [name, type] = propList[i]; |
120 | 158 |
121 let viewParams = getViewsForType(type, viewTypes, views); | 159 let viewParams = getViewsForType(type, viewTypes, views); |
122 descriptors[name] = { | 160 descriptors[name] = { |
123 get: type.createGetter.apply(type, [offset].concat(viewParams)), | 161 get: wrapGetter(type.createGetter.apply(type, [offset].concat(viewParams))
), |
124 set: type.createSetter.apply(type, [offset].concat(viewParams)), | 162 set: wrapSetter(type.createSetter.apply(type, [offset].concat(viewParams))
), |
125 configurable: false, | 163 configurable: false, |
126 enumerable: true | 164 enumerable: true |
127 }; | 165 }; |
| 166 |
| 167 if (watchers && typeof watchers[name] == "function") |
| 168 descriptors[name].set = watchSetter(descriptors[name].set, watchers[name])
; |
| 169 |
128 offset += type.referenceLength; | 170 offset += type.referenceLength; |
129 if (cleanupValues && typeof type.cleanupValue != "undefined") | 171 if (initialValues && typeof type.initialValue != "undefined") |
130 cleanupValues.push([name, type.cleanupValue]); | 172 initialValues.push([name, type.initialValue]); |
131 } | 173 } |
132 | 174 |
133 // Define properties | 175 // Define properties |
134 Object.defineProperties(obj, descriptors); | 176 Object.defineProperties(obj, descriptors); |
135 | 177 |
136 return offset; | 178 return offset; |
137 }; | 179 }; |
| 180 |
| 181 /** |
| 182 * Creates a new array buffer and adds the necessary views. |
| 183 * |
| 184 * @param {Integer} byteSize bytes to allocate for the buffer |
| 185 * @param {Array} buffers existing buffers (will be modified) |
| 186 * @param {Array} viewTypes view types for the buffers |
| 187 * @param {Array} views existing buffer views (will be modified) |
| 188 * @result {Integer} index of the buffer created |
| 189 */ |
| 190 let addBuffer = exports.addBuffer = function(byteSize, buffers, viewTypes, views
) |
| 191 { |
| 192 let buffer = new ArrayBuffer(byteSize | 0); |
| 193 buffers.push(buffer); |
| 194 for (let i = 0, l = viewTypes.length | 0; i < l; i++) |
| 195 views[i].push(new viewTypes[i](buffer)); |
| 196 return (buffers.length | 0) - 1; |
| 197 } |
| 198 |
| 199 /** |
| 200 * Releases an array buffer. |
| 201 * |
| 202 * @param {Integer} bufferIndex index of the buffer to be released. |
| 203 * @param {Array} buffers existing buffers (will be modified) |
| 204 * @param {Array} views existing buffer views (will be modified) |
| 205 */ |
| 206 exports.removeBuffer = function(bufferIndex, buffers, views) |
| 207 { |
| 208 delete buffers[bufferIndex]; |
| 209 for (let i = 0, l = views.length | 0; i < l; i++) |
| 210 delete views[i][bufferIndex]; |
| 211 } |
| 212 |
| 213 /** |
| 214 * Allocates a new fixed-size element. It will return the first available free |
| 215 * block or create a new buffer if the existing ones have no space left. |
| 216 * |
| 217 * @param {TypedReference} firstFree head of the linked list pointing to unallo
cated elements |
| 218 * @param {Integer} byteLength size of an element |
| 219 * @param {Integer} bufferSize number of elements in a buffer |
| 220 * @param {Array} buffers existing buffers (might be modified in necessary) |
| 221 * @param {Array} viewTypes view types for the buffers |
| 222 * @param {Array} views existing buffer views (might be modified if necessary) |
| 223 * @result {Array} [bufferIndex, byteOffset] parameters of the newly allocated b
lock |
| 224 */ |
| 225 exports.alloc = function(firstFree, byteLength, bufferSize, buffers, viewTypes,
views) |
| 226 { |
| 227 let bufferIndex = firstFree.bufferIndex | 0; |
| 228 let byteOffset = firstFree.byteOffset | 0; |
| 229 if (bufferIndex >= 0) |
| 230 { |
| 231 // There is still a free spot, simply move on firstFree reference |
| 232 [firstFree.bufferIndex, firstFree.byteOffset] = |
| 233 [firstFree.targetBufferIndex, firstFree.targetByteOffset]; |
| 234 } |
| 235 else |
| 236 { |
| 237 byteLength = byteLength | 0; |
| 238 bufferSize = bufferSize | 0; |
| 239 |
| 240 // Create new buffer and use the first element of it |
| 241 bufferIndex = addBuffer(byteLength * bufferSize, buffers, viewTypes, views); |
| 242 byteOffset = 0; |
| 243 |
| 244 // Mark last element of the new buffer as the last free spot |
| 245 firstFree.bufferIndex = bufferIndex; |
| 246 firstFree.byteOffset = (bufferSize - 1) * byteLength; |
| 247 firstFree.targetBufferIndex = -1; |
| 248 |
| 249 // Make each remaining element of the new buffer point to the next one |
| 250 for (let i = bufferSize - 2; i >= 1; i--) |
| 251 { |
| 252 let nextByteOffset = firstFree.byteOffset; |
| 253 firstFree.byteOffset = nextByteOffset - byteLength; |
| 254 firstFree.targetBufferIndex = bufferIndex; |
| 255 firstFree.targetByteOffset = nextByteOffset; |
| 256 } |
| 257 } |
| 258 return [bufferIndex, byteOffset]; |
| 259 }; |
| 260 |
| 261 /** |
| 262 * Releases the block at given offset so that it can be allocated again. |
| 263 * |
| 264 * @param {TypedReference} firstFree head of the linked list pointing to unallo
cated elements |
| 265 * @param {Integer} bufferIndex buffer index of the block to be released |
| 266 * @param {Integer} byteOffset byte offset o fthe block to be released |
| 267 */ |
| 268 exports.dealloc = function(firstFree, bufferIndex, byteOffset) |
| 269 { |
| 270 let oldFreeBufferIndex = firstFree.bufferIndex | 0; |
| 271 let oldFreeByteOffset = firstFree.byteOffset | 0; |
| 272 |
| 273 firstFree.bufferIndex = bufferIndex | 0; |
| 274 firstFree.byteOffset = byteOffset | 0; |
| 275 firstFree.targetBufferIndex = oldFreeBufferIndex; |
| 276 firstFree.targetByteOffset = oldFreeByteOffset; |
| 277 } |
OLD | NEW |