| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 return string.lastIndexOf(suffix) == expectedIndex; | 35 return string.lastIndexOf(suffix) == expectedIndex; |
| 36 }; | 36 }; |
| 37 | 37 |
| 38 base.joinPath = function(parent, child) | 38 base.joinPath = function(parent, child) |
| 39 { | 39 { |
| 40 if (parent.length == 0) | 40 if (parent.length == 0) |
| 41 return child; | 41 return child; |
| 42 return parent + '/' + child; | 42 return parent + '/' + child; |
| 43 }; | 43 }; |
| 44 | 44 |
| 45 base.dirName = function(path) | |
| 46 { | |
| 47 var directoryIndex = path.lastIndexOf('/'); | |
| 48 if (directoryIndex == -1) | |
| 49 return path; | |
| 50 return path.substr(0, directoryIndex); | |
| 51 }; | |
| 52 | |
| 53 base.trimExtension = function(url) | 45 base.trimExtension = function(url) |
| 54 { | 46 { |
| 55 var index = url.lastIndexOf('.'); | 47 var index = url.lastIndexOf('.'); |
| 56 if (index == -1) | 48 if (index == -1) |
| 57 return url; | 49 return url; |
| 58 return url.substr(0, index); | 50 return url.substr(0, index); |
| 59 } | 51 } |
| 60 | 52 |
| 61 base.uniquifyArray = function(array) | 53 base.uniquifyArray = function(array) |
| 62 { | 54 { |
| 63 var seen = {}; | 55 var seen = {}; |
| 64 var result = []; | 56 var result = []; |
| 65 array.forEach(function(value) { | 57 array.forEach(function(value) { |
| 66 if (seen[value]) | 58 if (seen[value]) |
| 67 return; | 59 return; |
| 68 seen[value] = true; | 60 seen[value] = true; |
| 69 result.push(value); | 61 result.push(value); |
| 70 }); | 62 }); |
| 71 return result; | 63 return result; |
| 72 }; | 64 }; |
| 73 | 65 |
| 74 base.flattenArray = function(arrayOfArrays) | |
| 75 { | |
| 76 if (!arrayOfArrays.length) | |
| 77 return []; | |
| 78 return arrayOfArrays.reduce(function(left, right) { | |
| 79 return left.concat(right); | |
| 80 }); | |
| 81 }; | |
| 82 | |
| 83 base.filterDictionary = function(dictionary, predicate) | |
| 84 { | |
| 85 var result = {}; | |
| 86 | |
| 87 for (var key in dictionary) { | |
| 88 if (predicate(key)) | |
| 89 result[key] = dictionary[key]; | |
| 90 } | |
| 91 | |
| 92 return result; | |
| 93 }; | |
| 94 | |
| 95 base.filterTree = function(tree, isLeaf, predicate) | 66 base.filterTree = function(tree, isLeaf, predicate) |
| 96 { | 67 { |
| 97 var filteredTree = {}; | 68 var filteredTree = {}; |
| 98 | 69 |
| 99 function walkSubtree(subtree, directory) | 70 function walkSubtree(subtree, directory) |
| 100 { | 71 { |
| 101 for (var childName in subtree) { | 72 for (var childName in subtree) { |
| 102 var child = subtree[childName]; | 73 var child = subtree[childName]; |
| 103 var childPath = base.joinPath(directory, childName); | 74 var childPath = base.joinPath(directory, childName); |
| 104 if (isLeaf(child)) { | 75 if (isLeaf(child)) { |
| 105 if (predicate(child)) | 76 if (predicate(child)) |
| 106 filteredTree[childPath] = child; | 77 filteredTree[childPath] = child; |
| 107 continue; | 78 continue; |
| 108 } | 79 } |
| 109 walkSubtree(child, childPath); | 80 walkSubtree(child, childPath); |
| 110 } | 81 } |
| 111 } | 82 } |
| 112 | 83 |
| 113 walkSubtree(tree, ''); | 84 walkSubtree(tree, ''); |
| 114 return filteredTree; | 85 return filteredTree; |
| 115 }; | 86 }; |
| 116 | 87 |
| 117 base.forEachDirectory = function(pathList, callback) | |
| 118 { | |
| 119 var pathsByDirectory = {}; | |
| 120 pathList.forEach(function(path) { | |
| 121 var directory = base.dirName(path); | |
| 122 pathsByDirectory[directory] = pathsByDirectory[directory] || []; | |
| 123 pathsByDirectory[directory].push(path); | |
| 124 }); | |
| 125 Object.keys(pathsByDirectory).sort().forEach(function(directory) { | |
| 126 var paths = pathsByDirectory[directory]; | |
| 127 callback(directory + ' (' + paths.length + ' tests)', paths); | |
| 128 }); | |
| 129 }; | |
| 130 | |
| 131 base.parseJSONP = function(jsonp) | 88 base.parseJSONP = function(jsonp) |
| 132 { | 89 { |
| 133 if (!jsonp) | 90 if (!jsonp) |
| 134 return {}; | 91 return {}; |
| 135 | 92 |
| 136 if (!jsonp.match(/^[^{[]*\(/)) | 93 if (!jsonp.match(/^[^{[]*\(/)) |
| 137 return JSON.parse(jsonp); | 94 return JSON.parse(jsonp); |
| 138 | 95 |
| 139 var startIndex = jsonp.indexOf('(') + 1; | 96 var startIndex = jsonp.indexOf('(') + 1; |
| 140 var endIndex = jsonp.lastIndexOf(')'); | 97 var endIndex = jsonp.lastIndexOf(')'); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 161 return Promise.reject(Error("Reentrant request for ", key)); | 118 return Promise.reject(Error("Reentrant request for ", key)); |
| 162 | 119 |
| 163 return this._promiseCache[key]; | 120 return this._promiseCache[key]; |
| 164 }; | 121 }; |
| 165 | 122 |
| 166 base.AsynchronousCache.prototype.clear = function() | 123 base.AsynchronousCache.prototype.clear = function() |
| 167 { | 124 { |
| 168 this._promiseCache = {}; | 125 this._promiseCache = {}; |
| 169 }; | 126 }; |
| 170 | 127 |
| 171 /* | |
| 172 Maintains a dictionary of items, tracking their updates and removing items t
hat haven't been updated. | |
| 173 An "update" is a call to the "update" method. | |
| 174 To remove stale items, call the "remove" method. It will remove all | |
| 175 items that have not been been updated since the last call of "remove". | |
| 176 */ | |
| 177 base.UpdateTracker = function() | |
| 178 { | |
| 179 this._items = {}; | |
| 180 this._updated = {}; | |
| 181 } | |
| 182 | |
| 183 base.UpdateTracker.prototype = { | |
| 184 /* | |
| 185 Update an {key}/{item} pair. You can make the dictionary act as a set an
d | |
| 186 skip the {item}, in which case the {key} is also the {item}. | |
| 187 */ | |
| 188 update: function(key, object) | |
| 189 { | |
| 190 object = object || key; | |
| 191 this._items[key] = object; | |
| 192 this._updated[key] = 1; | |
| 193 }, | |
| 194 exists: function(key) | |
| 195 { | |
| 196 return !!this.get(key); | |
| 197 }, | |
| 198 get: function(key) | |
| 199 { | |
| 200 return this._items[key]; | |
| 201 }, | |
| 202 length: function() | |
| 203 { | |
| 204 return Object.keys(this._items).length; | |
| 205 }, | |
| 206 /* | |
| 207 Callback parameters are: | |
| 208 - item | |
| 209 - key | |
| 210 - updated, which is true if the item was updated after last purge() call
. | |
| 211 */ | |
| 212 forEach: function(callback, thisObject) | |
| 213 { | |
| 214 if (!callback) | |
| 215 return; | |
| 216 | |
| 217 Object.keys(this._items).sort().forEach(function(key) { | |
| 218 var item = this._items[key]; | |
| 219 callback.call(thisObject || item, item, key, !!this._updated[key]); | |
| 220 }, this); | |
| 221 }, | |
| 222 purge: function(removeCallback, thisObject) { | |
| 223 removeCallback = removeCallback || function() {}; | |
| 224 this.forEach(function(item, key, updated) { | |
| 225 if (updated) | |
| 226 return; | |
| 227 removeCallback.call(thisObject || item, item); | |
| 228 delete this._items[key]; | |
| 229 }, this); | |
| 230 this._updated = {}; | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 // Based on http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/resou
rces/shared/js/cr/ui.js | 128 // Based on http://src.chromium.org/viewvc/chrome/trunk/src/chrome/browser/resou
rces/shared/js/cr/ui.js |
| 235 base.extends = function(base, prototype) | 129 base.extends = function(base, prototype) |
| 236 { | 130 { |
| 237 var extended = function() { | 131 var extended = function() { |
| 238 var element = typeof base == 'string' ? document.createElement(base) : b
ase.call(this); | 132 var element = typeof base == 'string' ? document.createElement(base) : b
ase.call(this); |
| 239 extended.prototype.__proto__ = element.__proto__; | 133 extended.prototype.__proto__ = element.__proto__; |
| 240 element.__proto__ = extended.prototype; | 134 element.__proto__ = extended.prototype; |
| 241 var singleton = element.init && element.init.apply(element, arguments); | 135 var singleton = element.init && element.init.apply(element, arguments); |
| 242 if (singleton) | 136 if (singleton) |
| 243 return singleton; | 137 return singleton; |
| 244 return element; | 138 return element; |
| 245 } | 139 } |
| 246 | 140 |
| 247 extended.prototype = prototype; | 141 extended.prototype = prototype; |
| 248 return extended; | 142 return extended; |
| 249 } | 143 } |
| 250 | 144 |
| 251 base.getURLParameter = function(name) | |
| 252 { | |
| 253 var match = RegExp(name + '=' + '(.+?)(&|$)').exec(location.search); | |
| 254 if (!match) | |
| 255 return null; | |
| 256 return decodeURI(match[1]) | |
| 257 } | |
| 258 | |
| 259 base.underscoredBuilderName = function(builderName) | 145 base.underscoredBuilderName = function(builderName) |
| 260 { | 146 { |
| 261 return builderName.replace(/[ .()]/g, '_'); | 147 return builderName.replace(/[ .()]/g, '_'); |
| 262 } | 148 } |
| 263 | 149 |
| 264 base.queryParam = function(params) | 150 base.queryParam = function(params) |
| 265 { | 151 { |
| 266 var result = [] | 152 var result = [] |
| 267 Object.keys(params, function(key, value) { | 153 Object.keys(params, function(key, value) { |
| 268 result.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); | 154 result.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); |
| 269 }); | 155 }); |
| 270 // FIXME: Remove the conversion of space to plus. This is just here | 156 // FIXME: Remove the conversion of space to plus. This is just here |
| 271 // to remain compatible with jQuery.param, but there's no reason to | 157 // to remain compatible with jQuery.param, but there's no reason to |
| 272 // deviate from the built-in encodeURIComponent behavior. | 158 // deviate from the built-in encodeURIComponent behavior. |
| 273 return result.join('&').replace(/%20/g, '+'); | 159 return result.join('&').replace(/%20/g, '+'); |
| 274 } | 160 } |
| 275 | 161 |
| 276 })(); | 162 })(); |
| OLD | NEW |