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 |