1<!DOCTYPE html> 2<!-- 3Copyright (c) 2014 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="import" href="/tracing/base/base.html"> 9 10<script> 11'use strict'; 12 13tr.exportTo('tr.b', function() { 14 function asArray(arrayish) { 15 var values = []; 16 for (var i = 0; i < arrayish.length; i++) 17 values.push(arrayish[i]); 18 return values; 19 } 20 21 function compareArrays(x, y, elementCmp) { 22 var minLength = Math.min(x.length, y.length); 23 for (var i = 0; i < minLength; i++) { 24 var tmp = elementCmp(x[i], y[i]); 25 if (tmp) 26 return tmp; 27 } 28 if (x.length == y.length) 29 return 0; 30 31 if (x[i] === undefined) 32 return -1; 33 34 return 1; 35 } 36 37 /** 38 * Compares two values when one or both might be undefined. Undefined 39 * values are sorted after defined. 40 */ 41 function comparePossiblyUndefinedValues(x, y, cmp, opt_this) { 42 if (x !== undefined && y !== undefined) 43 return cmp.call(opt_this, x, y); 44 if (x !== undefined) 45 return -1; 46 if (y !== undefined) 47 return 1; 48 return 0; 49 } 50 51 /** 52 * Compares two numeric values when one or both might be undefined or NaNs. 53 * Undefined / NaN values are sorted after others. 54 */ 55 function compareNumericWithNaNs(x, y) { 56 if (!isNaN(x) && !isNaN(y)) 57 return x - y; 58 if (isNaN(x)) 59 return 1; 60 if (isNaN(y)) 61 return -1; 62 return 0; 63 } 64 65 function concatenateArrays(/*arguments*/) { 66 var values = []; 67 for (var i = 0; i < arguments.length; i++) { 68 if (!(arguments[i] instanceof Array)) 69 throw new Error('Arguments ' + i + 'is not an array'); 70 values.push.apply(values, arguments[i]); 71 } 72 return values; 73 } 74 75 function concatenateObjects(/*arguments*/) { 76 var result = {}; 77 for (var i = 0; i < arguments.length; i++) { 78 var object = arguments[i]; 79 for (var j in object) { 80 result[j] = object[j]; 81 } 82 } 83 return result; 84 } 85 86 function dictionaryKeys(dict) { 87 var keys = []; 88 for (var key in dict) 89 keys.push(key); 90 return keys; 91 } 92 93 function dictionaryValues(dict) { 94 var values = []; 95 for (var key in dict) 96 values.push(dict[key]); 97 return values; 98 } 99 100 function dictionaryLength(dict) { 101 var n = 0; 102 for (var key in dict) 103 n++; 104 return n; 105 } 106 107 function dictionaryContainsValue(dict, value) { 108 for (var key in dict) 109 if (dict[key] === value) 110 return true; 111 return false; 112 } 113 114 /** 115 * Returns a new dictionary with items grouped by the return value of the 116 * specified function being called on each item. 117 * @param {!Array.<Object>} ary The array being iterated through 118 * @param {!Function} fn The mapping function between the array value and the 119 * map key. 120 */ 121 function group(ary, fn) { 122 return ary.reduce(function(accumulator, curr) { 123 var key = fn(curr); 124 125 if (key in accumulator) 126 accumulator[key].push(curr); 127 else 128 accumulator[key] = [curr]; 129 130 return accumulator; 131 }, {}); 132 } 133 134 function iterItems(dict, fn, opt_this) { 135 opt_this = opt_this || this; 136 var keys = Object.keys(dict); 137 for (var i = 0; i < keys.length; i++) { 138 var key = keys[i]; 139 fn.call(opt_this, key, dict[key]); 140 } 141 } 142 143 /** 144 * Create a new dictionary with the same keys as the original dictionary 145 * mapped to the results of the provided function called on the corresponding 146 * entries in the original dictionary, i.e. result[key] = fn(key, dict[key]) 147 * for all keys in dict (own enumerable properties only). 148 * 149 * Example: 150 * var srcDict = {a: 10, b: 15}; 151 * var dstDict = mapItems(srcDict, function(k, v) { return 2 * v; }); 152 * // srcDict is unmodified and dstDict is now equal to {a: 20, b: 30}. 153 */ 154 function mapItems(dict, fn, opt_this) { 155 opt_this = opt_this || this; 156 var result = {}; 157 var keys = Object.keys(dict); 158 for (var i = 0; i < keys.length; i++) { 159 var key = keys[i]; 160 result[key] = fn.call(opt_this, key, dict[key]); 161 } 162 return result; 163 } 164 165 function filterItems(dict, predicate, opt_this) { 166 opt_this = opt_this || this; 167 var result = {}; 168 var keys = Object.keys(dict); 169 for (var i = 0; i < keys.length; i++) { 170 var key = keys[i]; 171 var value = dict[key]; 172 if (predicate.call(opt_this, key, value)) 173 result[key] = value; 174 } 175 return result; 176 } 177 178 function iterObjectFieldsRecursively(object, func) { 179 if (!(object instanceof Object)) 180 return; 181 182 if (object instanceof Array) { 183 for (var i = 0; i < object.length; i++) { 184 func(object, i, object[i]); 185 iterObjectFieldsRecursively(object[i], func); 186 } 187 return; 188 } 189 190 for (var key in object) { 191 var value = object[key]; 192 func(object, key, value); 193 iterObjectFieldsRecursively(value, func); 194 } 195 } 196 197 /** 198 * Convert an array of dictionaries to a dictionary of arrays. 199 * 200 * The keys of the resulting dictionary are a union of the keys of all 201 * dictionaries in the provided array. Each array in the resulting dictionary 202 * has the same length as the provided array and contains the values of its 203 * key in the dictionaries in the provided array. Example: 204 * 205 * INPUT: 206 * 207 * [ 208 * {a: 6, b: 5 }, 209 * undefined, 210 * {a: 4, b: 3, c: 2}, 211 * { b: 1, c: 0} 212 * ] 213 * 214 * OUTPUT: 215 * 216 * { 217 * a: [6, undefined, 4, undefined], 218 * b: [5, undefined, 3, 1 ], 219 * c: [undefined, undefined, 2, 0 ] 220 * } 221 * 222 * @param {!Array} array Array of items to be inverted. If opt_dictGetter 223 * is not provided, all elements of the array must be either undefined, 224 * or dictionaries. 225 * @param {?(function(*): (!Object|undefined))=} opt_dictGetter Optional 226 * function mapping defined elements of array to dictionaries. 227 * @param {*=} opt_this Optional 'this' context for opt_dictGetter. 228 */ 229 function invertArrayOfDicts(array, opt_dictGetter, opt_this) { 230 opt_this = opt_this || this; 231 var result = {}; 232 for (var i = 0; i < array.length; i++) { 233 var item = array[i]; 234 if (item === undefined) 235 continue; 236 var dict = opt_dictGetter ? opt_dictGetter.call(opt_this, item) : item; 237 if (dict === undefined) 238 continue; 239 for (var key in dict) { 240 var valueList = result[key]; 241 if (valueList === undefined) 242 result[key] = valueList = new Array(array.length); 243 valueList[i] = dict[key]; 244 } 245 } 246 return result; 247 } 248 249 /** 250 * Convert an array to a dictionary. 251 * 252 * Every element in the array is mapped in the dictionary to the key returned 253 * by the provided function: 254 * 255 * dictionary[valueToKeyFn(element)] = element; 256 * 257 * @param {!Array} array Arbitrary array. 258 * @param {function(*): string} valueToKeyFn Function mapping array elements 259 * to dictionary keys. 260 * @param {*=} opt_this Optional 'this' context for valueToKeyFn. 261 */ 262 function arrayToDict(array, valueToKeyFn, opt_this) { 263 opt_this = opt_this || this; 264 var result = {}; 265 var length = array.length; 266 for (var i = 0; i < length; i++) { 267 var value = array[i]; 268 var key = valueToKeyFn.call(opt_this, value); 269 result[key] = value; 270 } 271 return result; 272 } 273 274 function identity(d) { 275 return d; 276 } 277 278 function findFirstIndexInArray(ary, opt_func, opt_this) { 279 var func = opt_func || identity; 280 for (var i = 0; i < ary.length; i++) { 281 if (func.call(opt_this, ary[i], i)) 282 return i; 283 } 284 return -1; 285 } 286 287 function findFirstInArray(ary, opt_func, opt_this) { 288 var i = findFirstIndexInArray(ary, opt_func, opt_func); 289 if (i === -1) 290 return undefined; 291 return ary[i]; 292 } 293 294 function findFirstKeyInDictMatching(dict, opt_func, opt_this) { 295 var func = opt_func || identity; 296 for (var key in dict) { 297 if (func.call(opt_this, key, dict[key])) 298 return key; 299 } 300 return undefined; 301 } 302 303 function mapValues(map) { 304 var values = []; 305 for (var value of map.values()) 306 values.push(value); 307 return values; 308 } 309 310 function iterMapItems(map, fn, opt_this) { 311 opt_this = opt_this || this; 312 for (var key of map.keys()) 313 fn.call(opt_this, key, map.get(key)); 314 } 315 316 return { 317 asArray: asArray, 318 concatenateArrays: concatenateArrays, 319 concatenateObjects: concatenateObjects, 320 compareArrays: compareArrays, 321 comparePossiblyUndefinedValues: comparePossiblyUndefinedValues, 322 compareNumericWithNaNs: compareNumericWithNaNs, 323 dictionaryLength: dictionaryLength, 324 dictionaryKeys: dictionaryKeys, 325 dictionaryValues: dictionaryValues, 326 dictionaryContainsValue: dictionaryContainsValue, 327 group: group, 328 iterItems: iterItems, 329 mapItems: mapItems, 330 filterItems: filterItems, 331 iterObjectFieldsRecursively: iterObjectFieldsRecursively, 332 invertArrayOfDicts: invertArrayOfDicts, 333 arrayToDict: arrayToDict, 334 identity: identity, 335 findFirstIndexInArray: findFirstIndexInArray, 336 findFirstInArray: findFirstInArray, 337 findFirstKeyInDictMatching: findFirstKeyInDictMatching, 338 mapValues: mapValues, 339 iterMapItems: iterMapItems 340 }; 341}); 342</script> 343