Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(170)

Side by Side Diff: Source/devtools/front_end/platform/utilities.js

Issue 692343002: Revert of [DevTools] Extract platform module. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 // FIXME: This performance optimization should be moved to blink so that all dev elopers could enjoy it.
31 // console is retrieved with V8Window.getAttribute method which is slow. Here we copy it to a js variable for faster access.
32 console = console;
33 console.__originalAssert = console.assert;
34 console.assert = function(value, message)
35 {
36 if (value)
37 return;
38 console.__originalAssert(value, message);
39 }
40
41 /** @typedef {Array|NodeList|Arguments|{length: number}} */
42 var ArrayLike;
43
44 /**
45 * @param {!Object} obj
46 * @return {boolean}
47 */
48 Object.isEmpty = function(obj)
49 {
50 for (var i in obj)
51 return false;
52 return true;
53 }
54
55 /**
56 * @param {!Object.<string,!T>} obj
57 * @return {!Array.<!T>}
58 * @template T
59 */
60 Object.values = function(obj)
61 {
62 var result = Object.keys(obj);
63 var length = result.length;
64 for (var i = 0; i < length; ++i)
65 result[i] = obj[result[i]];
66 return result;
67 }
68
69 /**
70 * @param {number} m
71 * @param {number} n
72 * @return {number}
73 */
74 function mod(m, n)
75 {
76 return ((m % n) + n) % n;
77 }
78
79 /**
80 * @param {string} string
81 * @return {!Array.<number>}
82 */
83 String.prototype.findAll = function(string)
84 {
85 var matches = [];
86 var i = this.indexOf(string);
87 while (i !== -1) {
88 matches.push(i);
89 i = this.indexOf(string, i + string.length);
90 }
91 return matches;
92 }
93
94 /**
95 * @return {!Array.<number>}
96 */
97 String.prototype.lineEndings = function()
98 {
99 if (!this._lineEndings) {
100 this._lineEndings = this.findAll("\n");
101 this._lineEndings.push(this.length);
102 }
103 return this._lineEndings;
104 }
105
106 /**
107 * @return {number}
108 */
109 String.prototype.lineCount = function()
110 {
111 var lineEndings = this.lineEndings();
112 return lineEndings.length;
113 }
114
115 /**
116 * @return {string}
117 */
118 String.prototype.lineAt = function(lineNumber)
119 {
120 var lineEndings = this.lineEndings();
121 var lineStart = lineNumber > 0 ? lineEndings[lineNumber - 1] + 1 : 0;
122 var lineEnd = lineEndings[lineNumber];
123 var lineContent = this.substring(lineStart, lineEnd);
124 if (lineContent.length > 0 && lineContent.charAt(lineContent.length - 1) === "\r")
125 lineContent = lineContent.substring(0, lineContent.length - 1);
126 return lineContent;
127 }
128
129 /**
130 * @param {string} chars
131 * @return {string}
132 */
133 String.prototype.escapeCharacters = function(chars)
134 {
135 var foundChar = false;
136 for (var i = 0; i < chars.length; ++i) {
137 if (this.indexOf(chars.charAt(i)) !== -1) {
138 foundChar = true;
139 break;
140 }
141 }
142
143 if (!foundChar)
144 return String(this);
145
146 var result = "";
147 for (var i = 0; i < this.length; ++i) {
148 if (chars.indexOf(this.charAt(i)) !== -1)
149 result += "\\";
150 result += this.charAt(i);
151 }
152
153 return result;
154 }
155
156 /**
157 * @return {string}
158 */
159 String.regexSpecialCharacters = function()
160 {
161 return "^[]{}()\\.^$*+?|-,";
162 }
163
164 /**
165 * @return {string}
166 */
167 String.prototype.escapeForRegExp = function()
168 {
169 return this.escapeCharacters(String.regexSpecialCharacters());
170 }
171
172 /**
173 * @return {string}
174 */
175 String.prototype.escapeHTML = function()
176 {
177 return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt; ").replace(/"/g, "&quot;"); //" doublequotes just for editor
178 }
179
180 /**
181 * @return {string}
182 */
183 String.prototype.unescapeHTML = function()
184 {
185 return this.replace(/&lt;/g, "<")
186 .replace(/&gt;/g, ">")
187 .replace(/&#58;/g, ":")
188 .replace(/&quot;/g, "\"")
189 .replace(/&#60;/g, "<")
190 .replace(/&#62;/g, ">")
191 .replace(/&amp;/g, "&");
192 }
193
194 /**
195 * @return {string}
196 */
197 String.prototype.collapseWhitespace = function()
198 {
199 return this.replace(/[\s\xA0]+/g, " ");
200 }
201
202 /**
203 * @param {number} maxLength
204 * @return {string}
205 */
206 String.prototype.trimMiddle = function(maxLength)
207 {
208 if (this.length <= maxLength)
209 return String(this);
210 var leftHalf = maxLength >> 1;
211 var rightHalf = maxLength - leftHalf - 1;
212 return this.substr(0, leftHalf) + "\u2026" + this.substr(this.length - right Half, rightHalf);
213 }
214
215 /**
216 * @param {number} maxLength
217 * @return {string}
218 */
219 String.prototype.trimEnd = function(maxLength)
220 {
221 if (this.length <= maxLength)
222 return String(this);
223 return this.substr(0, maxLength - 1) + "\u2026";
224 }
225
226 /**
227 * @param {?string=} baseURLDomain
228 * @return {string}
229 */
230 String.prototype.trimURL = function(baseURLDomain)
231 {
232 var result = this.replace(/^(https|http|file):\/\//i, "");
233 if (baseURLDomain)
234 result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp() , "i"), "");
235 return result;
236 }
237
238 /**
239 * @return {string}
240 */
241 String.prototype.toTitleCase = function()
242 {
243 return this.substring(0, 1).toUpperCase() + this.substring(1);
244 }
245
246 /**
247 * @param {string} other
248 * @return {number}
249 */
250 String.prototype.compareTo = function(other)
251 {
252 if (this > other)
253 return 1;
254 if (this < other)
255 return -1;
256 return 0;
257 }
258
259 /**
260 * @param {string} href
261 * @return {?string}
262 */
263 function sanitizeHref(href)
264 {
265 return href && href.trim().toLowerCase().startsWith("javascript:") ? null : href;
266 }
267
268 /**
269 * @return {string}
270 */
271 String.prototype.removeURLFragment = function()
272 {
273 var fragmentIndex = this.indexOf("#");
274 if (fragmentIndex == -1)
275 fragmentIndex = this.length;
276 return this.substring(0, fragmentIndex);
277 }
278
279 /**
280 * @return {boolean}
281 */
282 String.prototype.startsWith = function(substring)
283 {
284 return !this.lastIndexOf(substring, 0);
285 }
286
287 /**
288 * @return {boolean}
289 */
290 String.prototype.endsWith = function(substring)
291 {
292 return this.indexOf(substring, this.length - substring.length) !== -1;
293 }
294
295 /**
296 * @return {number}
297 */
298 String.prototype.hashCode = function()
299 {
300 var result = 0;
301 for (var i = 0; i < this.length; ++i)
302 result = (result * 3 + this.charCodeAt(i)) | 0;
303 return result;
304 }
305
306 /**
307 * @param {number} index
308 * @return {boolean}
309 */
310 String.prototype.isDigitAt = function(index)
311 {
312 var c = this.charCodeAt(index);
313 return 48 <= c && c <= 57;
314 }
315
316 /**
317 * @param {string} a
318 * @param {string} b
319 * @return {number}
320 */
321 String.naturalOrderComparator = function(a, b)
322 {
323 var chunk = /^\d+|^\D+/;
324 var chunka, chunkb, anum, bnum;
325 while (1) {
326 if (a) {
327 if (!b)
328 return 1;
329 } else {
330 if (b)
331 return -1;
332 else
333 return 0;
334 }
335 chunka = a.match(chunk)[0];
336 chunkb = b.match(chunk)[0];
337 anum = !isNaN(chunka);
338 bnum = !isNaN(chunkb);
339 if (anum && !bnum)
340 return -1;
341 if (bnum && !anum)
342 return 1;
343 if (anum && bnum) {
344 var diff = chunka - chunkb;
345 if (diff)
346 return diff;
347 if (chunka.length !== chunkb.length) {
348 if (!+chunka && !+chunkb) // chunks are strings of all 0s (speci al case)
349 return chunka.length - chunkb.length;
350 else
351 return chunkb.length - chunka.length;
352 }
353 } else if (chunka !== chunkb)
354 return (chunka < chunkb) ? -1 : 1;
355 a = a.substring(chunka.length);
356 b = b.substring(chunkb.length);
357 }
358 }
359
360 /**
361 * @param {number} num
362 * @param {number} min
363 * @param {number} max
364 * @return {number}
365 */
366 Number.constrain = function(num, min, max)
367 {
368 if (num < min)
369 num = min;
370 else if (num > max)
371 num = max;
372 return num;
373 }
374
375 /**
376 * @param {number} a
377 * @param {number} b
378 * @return {number}
379 */
380 Number.gcd = function(a, b)
381 {
382 if (b === 0)
383 return a;
384 else
385 return Number.gcd(b, a % b);
386 }
387
388 /**
389 * @param {string} value
390 * @return {string}
391 */
392 Number.toFixedIfFloating = function(value)
393 {
394 if (!value || isNaN(value))
395 return value;
396 var number = Number(value);
397 return number % 1 ? number.toFixed(3) : String(number);
398 }
399
400 /**
401 * @return {string}
402 */
403 Date.prototype.toISO8601Compact = function()
404 {
405 /**
406 * @param {number} x
407 * @return {string}
408 */
409 function leadZero(x)
410 {
411 return (x > 9 ? "" : "0") + x;
412 }
413 return this.getFullYear() +
414 leadZero(this.getMonth() + 1) +
415 leadZero(this.getDate()) + "T" +
416 leadZero(this.getHours()) +
417 leadZero(this.getMinutes()) +
418 leadZero(this.getSeconds());
419 }
420
421 /**
422 * @return {string}
423 */
424 Date.prototype.toConsoleTime = function()
425 {
426 /**
427 * @param {number} x
428 * @return {string}
429 */
430 function leadZero2(x)
431 {
432 return (x > 9 ? "" : "0") + x;
433 }
434
435 /**
436 * @param {number} x
437 * @return {string}
438 */
439 function leadZero3(x)
440 {
441 return (Array(4 - x.toString().length)).join('0') + x;
442 }
443
444 return this.getFullYear() + "-" +
445 leadZero2(this.getMonth() + 1) + "-" +
446 leadZero2(this.getDate()) + " " +
447 leadZero2(this.getHours()) + ":" +
448 leadZero2(this.getMinutes()) + ":" +
449 leadZero2(this.getSeconds()) + "." +
450 leadZero3(this.getMilliseconds());
451 }
452
453 Object.defineProperty(Array.prototype, "remove",
454 {
455 /**
456 * @param {!T} value
457 * @param {boolean=} firstOnly
458 * @this {Array.<!T>}
459 * @template T
460 */
461 value: function(value, firstOnly)
462 {
463 var index = this.indexOf(value);
464 if (index === -1)
465 return;
466 if (firstOnly) {
467 this.splice(index, 1);
468 return;
469 }
470 for (var i = index + 1, n = this.length; i < n; ++i) {
471 if (this[i] !== value)
472 this[index++] = this[i];
473 }
474 this.length = index;
475 }
476 });
477
478 Object.defineProperty(Array.prototype, "keySet",
479 {
480 /**
481 * @return {!Object.<string, boolean>}
482 * @this {Array.<*>}
483 */
484 value: function()
485 {
486 var keys = {};
487 for (var i = 0; i < this.length; ++i)
488 keys[this[i]] = true;
489 return keys;
490 }
491 });
492
493 Object.defineProperty(Array.prototype, "pushAll",
494 {
495 /**
496 * @param {!Array.<!T>} array
497 * @this {Array.<!T>}
498 * @template T
499 */
500 value: function(array)
501 {
502 Array.prototype.push.apply(this, array);
503 }
504 });
505
506 Object.defineProperty(Array.prototype, "rotate",
507 {
508 /**
509 * @param {number} index
510 * @return {!Array.<!T>}
511 * @this {Array.<!T>}
512 * @template T
513 */
514 value: function(index)
515 {
516 var result = [];
517 for (var i = index; i < index + this.length; ++i)
518 result.push(this[i % this.length]);
519 return result;
520 }
521 });
522
523 Object.defineProperty(Array.prototype, "sortNumbers",
524 {
525 /**
526 * @this {Array.<number>}
527 */
528 value: function()
529 {
530 /**
531 * @param {number} a
532 * @param {number} b
533 * @return {number}
534 */
535 function numericComparator(a, b)
536 {
537 return a - b;
538 }
539
540 this.sort(numericComparator);
541 }
542 });
543
544 Object.defineProperty(Uint32Array.prototype, "sort", {
545 value: Array.prototype.sort
546 });
547
548 (function() {
549 var partition = {
550 /**
551 * @this {Array.<number>}
552 * @param {function(number, number): number} comparator
553 * @param {number} left
554 * @param {number} right
555 * @param {number} pivotIndex
556 */
557 value: function(comparator, left, right, pivotIndex)
558 {
559 function swap(array, i1, i2)
560 {
561 var temp = array[i1];
562 array[i1] = array[i2];
563 array[i2] = temp;
564 }
565
566 var pivotValue = this[pivotIndex];
567 swap(this, right, pivotIndex);
568 var storeIndex = left;
569 for (var i = left; i < right; ++i) {
570 if (comparator(this[i], pivotValue) < 0) {
571 swap(this, storeIndex, i);
572 ++storeIndex;
573 }
574 }
575 swap(this, right, storeIndex);
576 return storeIndex;
577 }
578 };
579 Object.defineProperty(Array.prototype, "partition", partition);
580 Object.defineProperty(Uint32Array.prototype, "partition", partition);
581
582 var sortRange = {
583 /**
584 * @param {function(number, number): number} comparator
585 * @param {number} leftBound
586 * @param {number} rightBound
587 * @param {number} sortWindowLeft
588 * @param {number} sortWindowRight
589 * @return {!Array.<number>}
590 * @this {Array.<number>}
591 */
592 value: function(comparator, leftBound, rightBound, sortWindowLeft, sortWindo wRight)
593 {
594 function quickSortRange(array, comparator, left, right, sortWindowLeft, sortWindowRight)
595 {
596 if (right <= left)
597 return;
598 var pivotIndex = Math.floor(Math.random() * (right - left)) + left;
599 var pivotNewIndex = array.partition(comparator, left, right, pivotIn dex);
600 if (sortWindowLeft < pivotNewIndex)
601 quickSortRange(array, comparator, left, pivotNewIndex - 1, sortW indowLeft, sortWindowRight);
602 if (pivotNewIndex < sortWindowRight)
603 quickSortRange(array, comparator, pivotNewIndex + 1, right, sort WindowLeft, sortWindowRight);
604 }
605 if (leftBound === 0 && rightBound === (this.length - 1) && sortWindowLef t === 0 && sortWindowRight >= rightBound)
606 this.sort(comparator);
607 else
608 quickSortRange(this, comparator, leftBound, rightBound, sortWindowLe ft, sortWindowRight);
609 return this;
610 }
611 }
612 Object.defineProperty(Array.prototype, "sortRange", sortRange);
613 Object.defineProperty(Uint32Array.prototype, "sortRange", sortRange);
614 })();
615
616 Object.defineProperty(Array.prototype, "stableSort",
617 {
618 /**
619 * @param {function(?T, ?T): number=} comparator
620 * @return {!Array.<?T>}
621 * @this {Array.<?T>}
622 * @template T
623 */
624 value: function(comparator)
625 {
626 function defaultComparator(a, b)
627 {
628 return a < b ? -1 : (a > b ? 1 : 0);
629 }
630 comparator = comparator || defaultComparator;
631
632 var indices = new Array(this.length);
633 for (var i = 0; i < this.length; ++i)
634 indices[i] = i;
635 var self = this;
636 /**
637 * @param {number} a
638 * @param {number} b
639 * @return {number}
640 */
641 function indexComparator(a, b)
642 {
643 var result = comparator(self[a], self[b]);
644 return result ? result : a - b;
645 }
646 indices.sort(indexComparator);
647
648 for (var i = 0; i < this.length; ++i) {
649 if (indices[i] < 0 || i === indices[i])
650 continue;
651 var cyclical = i;
652 var saved = this[i];
653 while (true) {
654 var next = indices[cyclical];
655 indices[cyclical] = -1;
656 if (next === i) {
657 this[cyclical] = saved;
658 break;
659 } else {
660 this[cyclical] = this[next];
661 cyclical = next;
662 }
663 }
664 }
665 return this;
666 }
667 });
668
669 Object.defineProperty(Array.prototype, "qselect",
670 {
671 /**
672 * @param {number} k
673 * @param {function(number, number): number=} comparator
674 * @return {number|undefined}
675 * @this {Array.<number>}
676 */
677 value: function(k, comparator)
678 {
679 if (k < 0 || k >= this.length)
680 return;
681 if (!comparator)
682 comparator = function(a, b) { return a - b; }
683
684 var low = 0;
685 var high = this.length - 1;
686 for (;;) {
687 var pivotPosition = this.partition(comparator, low, high, Math.floor ((high + low) / 2));
688 if (pivotPosition === k)
689 return this[k];
690 else if (pivotPosition > k)
691 high = pivotPosition - 1;
692 else
693 low = pivotPosition + 1;
694 }
695 }
696 });
697
698 Object.defineProperty(Array.prototype, "lowerBound",
699 {
700 /**
701 * Return index of the leftmost element that is equal or greater
702 * than the specimen object. If there's no such element (i.e. all
703 * elements are smaller than the specimen) returns right bound.
704 * The function works for sorted array.
705 * When specified, |left| (inclusive) and |right| (exclusive) indices
706 * define the search window.
707 *
708 * @param {!T} object
709 * @param {function(!T,!S):number=} comparator
710 * @param {number=} left
711 * @param {number=} right
712 * @return {number}
713 * @this {Array.<!S>}
714 * @template T,S
715 */
716 value: function(object, comparator, left, right)
717 {
718 function defaultComparator(a, b)
719 {
720 return a < b ? -1 : (a > b ? 1 : 0);
721 }
722 comparator = comparator || defaultComparator;
723 var l = left || 0;
724 var r = right !== undefined ? right : this.length;
725 while (l < r) {
726 var m = (l + r) >> 1;
727 if (comparator(object, this[m]) > 0)
728 l = m + 1;
729 else
730 r = m;
731 }
732 return r;
733 }
734 });
735
736 Object.defineProperty(Array.prototype, "upperBound",
737 {
738 /**
739 * Return index of the leftmost element that is greater
740 * than the specimen object. If there's no such element (i.e. all
741 * elements are smaller or equal to the specimen) returns right bound.
742 * The function works for sorted array.
743 * When specified, |left| (inclusive) and |right| (exclusive) indices
744 * define the search window.
745 *
746 * @param {!T} object
747 * @param {function(!T,!S):number=} comparator
748 * @param {number=} left
749 * @param {number=} right
750 * @return {number}
751 * @this {Array.<!S>}
752 * @template T,S
753 */
754 value: function(object, comparator, left, right)
755 {
756 function defaultComparator(a, b)
757 {
758 return a < b ? -1 : (a > b ? 1 : 0);
759 }
760 comparator = comparator || defaultComparator;
761 var l = left || 0;
762 var r = right !== undefined ? right : this.length;
763 while (l < r) {
764 var m = (l + r) >> 1;
765 if (comparator(object, this[m]) >= 0)
766 l = m + 1;
767 else
768 r = m;
769 }
770 return r;
771 }
772 });
773
774 Object.defineProperty(Uint32Array.prototype, "lowerBound", {
775 value: Array.prototype.lowerBound
776 });
777
778 Object.defineProperty(Uint32Array.prototype, "upperBound", {
779 value: Array.prototype.upperBound
780 });
781
782 Object.defineProperty(Float64Array.prototype, "lowerBound", {
783 value: Array.prototype.lowerBound
784 });
785
786 Object.defineProperty(Array.prototype, "binaryIndexOf",
787 {
788 /**
789 * @param {!T} value
790 * @param {function(!T,!S):number} comparator
791 * @return {number}
792 * @this {Array.<!S>}
793 * @template T,S
794 */
795 value: function(value, comparator)
796 {
797 var index = this.lowerBound(value, comparator);
798 return index < this.length && comparator(value, this[index]) === 0 ? ind ex : -1;
799 }
800 });
801
802 Object.defineProperty(Array.prototype, "select",
803 {
804 /**
805 * @param {string} field
806 * @return {!Array.<!T>}
807 * @this {Array.<!Object.<string,!T>>}
808 * @template T
809 */
810 value: function(field)
811 {
812 var result = new Array(this.length);
813 for (var i = 0; i < this.length; ++i)
814 result[i] = this[i][field];
815 return result;
816 }
817 });
818
819 Object.defineProperty(Array.prototype, "peekLast",
820 {
821 /**
822 * @return {!T|undefined}
823 * @this {Array.<!T>}
824 * @template T
825 */
826 value: function()
827 {
828 return this[this.length - 1];
829 }
830 });
831
832 (function(){
833
834 /**
835 * @param {!Array.<T>} array1
836 * @param {!Array.<T>} array2
837 * @param {function(T,T):number} comparator
838 * @param {boolean} mergeNotIntersect
839 * @return {!Array.<T>}
840 * @template T
841 */
842 function mergeOrIntersect(array1, array2, comparator, mergeNotIntersect)
843 {
844 var result = [];
845 var i = 0;
846 var j = 0;
847 while (i < array1.length && j < array2.length) {
848 var compareValue = comparator(array1[i], array2[j]);
849 if (mergeNotIntersect || !compareValue)
850 result.push(compareValue <= 0 ? array1[i] : array2[j]);
851 if (compareValue <= 0)
852 i++;
853 if (compareValue >= 0)
854 j++;
855 }
856 if (mergeNotIntersect) {
857 while (i < array1.length)
858 result.push(array1[i++]);
859 while (j < array2.length)
860 result.push(array2[j++]);
861 }
862 return result;
863 }
864
865 Object.defineProperty(Array.prototype, "intersectOrdered",
866 {
867 /**
868 * @param {!Array.<T>} array
869 * @param {function(T,T):number} comparator
870 * @return {!Array.<T>}
871 * @this {!Array.<T>}
872 * @template T
873 */
874 value: function(array, comparator)
875 {
876 return mergeOrIntersect(this, array, comparator, false);
877 }
878 });
879
880 Object.defineProperty(Array.prototype, "mergeOrdered",
881 {
882 /**
883 * @param {!Array.<T>} array
884 * @param {function(T,T):number} comparator
885 * @return {!Array.<T>}
886 * @this {!Array.<T>}
887 * @template T
888 */
889 value: function(array, comparator)
890 {
891 return mergeOrIntersect(this, array, comparator, true);
892 }
893 });
894
895 }());
896
897
898 /**
899 * @param {!T} object
900 * @param {!Array.<!S>} list
901 * @param {function(!T,!S):number=} comparator
902 * @param {boolean=} insertionIndexAfter
903 * @return {number}
904 * @template T,S
905 */
906 function insertionIndexForObjectInListSortedByFunction(object, list, comparator, insertionIndexAfter)
907 {
908 if (insertionIndexAfter)
909 return list.upperBound(object, comparator);
910 else
911 return list.lowerBound(object, comparator);
912 }
913
914 /**
915 * @param {string} format
916 * @param {...*} var_arg
917 * @return {string}
918 */
919 String.sprintf = function(format, var_arg)
920 {
921 return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
922 }
923
924 /**
925 * @param {string} format
926 * @param {!Object.<string, function(string, ...):*>} formatters
927 * @return {!Array.<!Object>}
928 */
929 String.tokenizeFormatString = function(format, formatters)
930 {
931 var tokens = [];
932 var substitutionIndex = 0;
933
934 function addStringToken(str)
935 {
936 tokens.push({ type: "string", value: str });
937 }
938
939 function addSpecifierToken(specifier, precision, substitutionIndex)
940 {
941 tokens.push({ type: "specifier", specifier: specifier, precision: precis ion, substitutionIndex: substitutionIndex });
942 }
943
944 var index = 0;
945 for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; pre centIndex = format.indexOf("%", index)) {
946 addStringToken(format.substring(index, precentIndex));
947 index = precentIndex + 1;
948
949 if (format[index] === "%") {
950 // %% escape sequence.
951 addStringToken("%");
952 ++index;
953 continue;
954 }
955
956 if (format.isDigitAt(index)) {
957 // The first character is a number, it might be a substitution index .
958 var number = parseInt(format.substring(index), 10);
959 while (format.isDigitAt(index))
960 ++index;
961
962 // If the number is greater than zero and ends with a "$",
963 // then this is a substitution index.
964 if (number > 0 && format[index] === "$") {
965 substitutionIndex = (number - 1);
966 ++index;
967 }
968 }
969
970 var precision = -1;
971 if (format[index] === ".") {
972 // This is a precision specifier. If no digit follows the ".",
973 // then the precision should be zero.
974 ++index;
975 precision = parseInt(format.substring(index), 10);
976 if (isNaN(precision))
977 precision = 0;
978
979 while (format.isDigitAt(index))
980 ++index;
981 }
982
983 if (!(format[index] in formatters)) {
984 addStringToken(format.substring(precentIndex, index + 1));
985 ++index;
986 continue;
987 }
988
989 addSpecifierToken(format[index], precision, substitutionIndex);
990
991 ++substitutionIndex;
992 ++index;
993 }
994
995 addStringToken(format.substring(index));
996
997 return tokens;
998 }
999
1000 String.standardFormatters = {
1001 /**
1002 * @return {number}
1003 */
1004 d: function(substitution)
1005 {
1006 return !isNaN(substitution) ? substitution : 0;
1007 },
1008
1009 /**
1010 * @return {number}
1011 */
1012 f: function(substitution, token)
1013 {
1014 if (substitution && token.precision > -1)
1015 substitution = substitution.toFixed(token.precision);
1016 return !isNaN(substitution) ? substitution : (token.precision > -1 ? Num ber(0).toFixed(token.precision) : 0);
1017 },
1018
1019 /**
1020 * @return {string}
1021 */
1022 s: function(substitution)
1023 {
1024 return substitution;
1025 }
1026 }
1027
1028 /**
1029 * @param {string} format
1030 * @param {!Array.<*>} substitutions
1031 * @return {string}
1032 */
1033 String.vsprintf = function(format, substitutions)
1034 {
1035 return String.format(format, substitutions, String.standardFormatters, "", f unction(a, b) { return a + b; }).formattedResult;
1036 }
1037
1038 /**
1039 * @param {string} format
1040 * @param {?ArrayLike} substitutions
1041 * @param {!Object.<string, function(string, ...):string>} formatters
1042 * @param {!T} initialValue
1043 * @param {function(T, string): T|undefined} append
1044 * @param {!Array.<!Object>=} tokenizedFormat
1045 * @return {!{formattedResult: T, unusedSubstitutions: ?ArrayLike}};
1046 * @template T
1047 */
1048 String.format = function(format, substitutions, formatters, initialValue, append , tokenizedFormat)
1049 {
1050 if (!format || !substitutions || !substitutions.length)
1051 return { formattedResult: append(initialValue, format), unusedSubstituti ons: substitutions };
1052
1053 function prettyFunctionName()
1054 {
1055 return "String.format(\"" + format + "\", \"" + Array.prototype.join.cal l(substitutions, "\", \"") + "\")";
1056 }
1057
1058 function warn(msg)
1059 {
1060 console.warn(prettyFunctionName() + ": " + msg);
1061 }
1062
1063 function error(msg)
1064 {
1065 console.error(prettyFunctionName() + ": " + msg);
1066 }
1067
1068 var result = initialValue;
1069 var tokens = tokenizedFormat || String.tokenizeFormatString(format, formatte rs);
1070 var usedSubstitutionIndexes = {};
1071
1072 for (var i = 0; i < tokens.length; ++i) {
1073 var token = tokens[i];
1074
1075 if (token.type === "string") {
1076 result = append(result, token.value);
1077 continue;
1078 }
1079
1080 if (token.type !== "specifier") {
1081 error("Unknown token type \"" + token.type + "\" found.");
1082 continue;
1083 }
1084
1085 if (token.substitutionIndex >= substitutions.length) {
1086 // If there are not enough substitutions for the current substitutio nIndex
1087 // just output the format specifier literally and move on.
1088 error("not enough substitution arguments. Had " + substitutions.leng th + " but needed " + (token.substitutionIndex + 1) + ", so substitution was ski pped.");
1089 result = append(result, "%" + (token.precision > -1 ? token.precisio n : "") + token.specifier);
1090 continue;
1091 }
1092
1093 usedSubstitutionIndexes[token.substitutionIndex] = true;
1094
1095 if (!(token.specifier in formatters)) {
1096 // Encountered an unsupported format character, treat as a string.
1097 warn("unsupported format character \u201C" + token.specifier + "\u20 1D. Treating as a string.");
1098 result = append(result, substitutions[token.substitutionIndex]);
1099 continue;
1100 }
1101
1102 result = append(result, formatters[token.specifier](substitutions[token. substitutionIndex], token));
1103 }
1104
1105 var unusedSubstitutions = [];
1106 for (var i = 0; i < substitutions.length; ++i) {
1107 if (i in usedSubstitutionIndexes)
1108 continue;
1109 unusedSubstitutions.push(substitutions[i]);
1110 }
1111
1112 return { formattedResult: result, unusedSubstitutions: unusedSubstitutions } ;
1113 }
1114
1115 /**
1116 * @param {string} query
1117 * @param {boolean} caseSensitive
1118 * @param {boolean} isRegex
1119 * @return {!RegExp}
1120 */
1121 function createSearchRegex(query, caseSensitive, isRegex)
1122 {
1123 var regexFlags = caseSensitive ? "g" : "gi";
1124 var regexObject;
1125
1126 if (isRegex) {
1127 try {
1128 regexObject = new RegExp(query, regexFlags);
1129 } catch (e) {
1130 // Silent catch.
1131 }
1132 }
1133
1134 if (!regexObject)
1135 regexObject = createPlainTextSearchRegex(query, regexFlags);
1136
1137 return regexObject;
1138 }
1139
1140 /**
1141 * @param {string} query
1142 * @param {string=} flags
1143 * @return {!RegExp}
1144 */
1145 function createPlainTextSearchRegex(query, flags)
1146 {
1147 // This should be kept the same as the one in ContentSearchUtils.cpp.
1148 var regexSpecialCharacters = String.regexSpecialCharacters();
1149 var regex = "";
1150 for (var i = 0; i < query.length; ++i) {
1151 var c = query.charAt(i);
1152 if (regexSpecialCharacters.indexOf(c) != -1)
1153 regex += "\\";
1154 regex += c;
1155 }
1156 return new RegExp(regex, flags || "");
1157 }
1158
1159 /**
1160 * @param {!RegExp} regex
1161 * @param {string} content
1162 * @return {number}
1163 */
1164 function countRegexMatches(regex, content)
1165 {
1166 var text = content;
1167 var result = 0;
1168 var match;
1169 while (text && (match = regex.exec(text))) {
1170 if (match[0].length > 0)
1171 ++result;
1172 text = text.substring(match.index + 1);
1173 }
1174 return result;
1175 }
1176
1177 /**
1178 * @param {number} spacesCount
1179 * @return {string}
1180 */
1181 function spacesPadding(spacesCount)
1182 {
1183 return Array(spacesCount).join("\u00a0");
1184 }
1185
1186 /**
1187 * @param {number} value
1188 * @param {number} symbolsCount
1189 * @return {string}
1190 */
1191 function numberToStringWithSpacesPadding(value, symbolsCount)
1192 {
1193 var numberString = value.toString();
1194 var paddingLength = Math.max(0, symbolsCount - numberString.length);
1195 return spacesPadding(paddingLength) + numberString;
1196 }
1197
1198 /**
1199 * @param {!Iterator.<T>} iterator
1200 * @return {!Array.<T>}
1201 * @template T
1202 */
1203 Array.from = function(iterator)
1204 {
1205 var values = [];
1206 for (var iteratorValue = iterator.next(); !iteratorValue.done; iteratorValue = iterator.next())
1207 values.push(iteratorValue.value);
1208 return values;
1209 }
1210
1211 /**
1212 * @param {!Array.<!T>} array
1213 * @return {!Set.<T>}
1214 * @template T
1215 */
1216 Set.fromArray = function(array)
1217 {
1218 return new Set(array);
1219 }
1220
1221 /**
1222 * @return {!Array.<T>}
1223 * @template T
1224 */
1225 Set.prototype.valuesArray = function()
1226 {
1227 return Array.from(this.values());
1228 }
1229
1230 Set.prototype.remove = Set.prototype.delete;
1231
1232 /**
1233 * @return {T}
1234 * @template T
1235 */
1236 Map.prototype.remove = function(key)
1237 {
1238 var value = this.get(key);
1239 this.delete(key);
1240 return value;
1241 }
1242
1243 /**
1244 * @return {!Array.<V>}
1245 * @template K, V
1246 * @this {Map.<K, V>}
1247 */
1248 Map.prototype.valuesArray = function()
1249 {
1250 return Array.from(this.values());
1251 }
1252
1253 /**
1254 * @return {!Array.<K>}
1255 * @template K, V
1256 * @this {Map.<K, V>}
1257 */
1258 Map.prototype.keysArray = function()
1259 {
1260 return Array.from(this.keys());
1261 }
1262
1263 /**
1264 * @constructor
1265 * @template T
1266 */
1267 var StringMultimap = function()
1268 {
1269 /** @type {!Map.<string, !Set.<!T>>} */
1270 this._map = new Map();
1271 }
1272
1273 StringMultimap.prototype = {
1274 /**
1275 * @param {string} key
1276 * @param {T} value
1277 */
1278 set: function(key, value)
1279 {
1280 var set = this._map.get(key);
1281 if (!set) {
1282 set = new Set();
1283 this._map.set(key, set);
1284 }
1285 set.add(value);
1286 },
1287
1288 /**
1289 * @param {string} key
1290 * @return {!Set.<!T>}
1291 */
1292 get: function(key)
1293 {
1294 var result = this._map.get(key);
1295 if (!result)
1296 result = new Set();
1297 return result;
1298 },
1299
1300 /**
1301 * @param {string} key
1302 * @param {T} value
1303 */
1304 remove: function(key, value)
1305 {
1306 var values = this.get(key);
1307 values.remove(value);
1308 if (!values.size)
1309 this._map.remove(key)
1310 },
1311
1312 /**
1313 * @param {string} key
1314 */
1315 removeAll: function(key)
1316 {
1317 this._map.remove(key)
1318 },
1319
1320 /**
1321 * @return {!Array.<string>}
1322 */
1323 keysArray: function()
1324 {
1325 return this._map.keysArray();
1326 },
1327
1328 /**
1329 * @return {!Array.<!T>}
1330 */
1331 valuesArray: function()
1332 {
1333 var result = [];
1334 var keys = this.keysArray();
1335 for (var i = 0; i < keys.length; ++i)
1336 result.pushAll(this.get(keys[i]).valuesArray());
1337 return result;
1338 },
1339
1340 clear: function()
1341 {
1342 this._map.clear();
1343 }
1344 }
1345
1346 /**
1347 * @param {string} url
1348 * @return {!Promise.<string>}
1349 */
1350 function loadXHR(url)
1351 {
1352 return new Promise(load);
1353
1354 function load(successCallback, failureCallback)
1355 {
1356 function onReadyStateChanged()
1357 {
1358 if (xhr.readyState !== XMLHttpRequest.DONE)
1359 return;
1360 if (xhr.status !== 200) {
1361 xhr.onreadystatechange = null;
1362 failureCallback(new Error(xhr.status));
1363 return;
1364 }
1365 xhr.onreadystatechange = null;
1366 successCallback(xhr.responseText);
1367 }
1368
1369 var xhr = new XMLHttpRequest();
1370 xhr.open("GET", url, true);
1371 xhr.onreadystatechange = onReadyStateChanged;
1372 xhr.send(null);
1373 }
1374 }
1375
1376 /**
1377 * @constructor
1378 */
1379 function CallbackBarrier()
1380 {
1381 this._pendingIncomingCallbacksCount = 0;
1382 }
1383
1384 CallbackBarrier.prototype = {
1385 /**
1386 * @param {function(...)=} userCallback
1387 * @return {function(...)}
1388 */
1389 createCallback: function(userCallback)
1390 {
1391 console.assert(!this._outgoingCallback, "CallbackBarrier.createCallback( ) is called after CallbackBarrier.callWhenDone()");
1392 ++this._pendingIncomingCallbacksCount;
1393 return this._incomingCallback.bind(this, userCallback);
1394 },
1395
1396 /**
1397 * @param {function()} callback
1398 */
1399 callWhenDone: function(callback)
1400 {
1401 console.assert(!this._outgoingCallback, "CallbackBarrier.callWhenDone() is called multiple times");
1402 this._outgoingCallback = callback;
1403 if (!this._pendingIncomingCallbacksCount)
1404 this._outgoingCallback();
1405 },
1406
1407 /**
1408 * @param {function(...)=} userCallback
1409 */
1410 _incomingCallback: function(userCallback)
1411 {
1412 console.assert(this._pendingIncomingCallbacksCount > 0);
1413 if (userCallback) {
1414 var args = Array.prototype.slice.call(arguments, 1);
1415 userCallback.apply(null, args);
1416 }
1417 if (!--this._pendingIncomingCallbacksCount && this._outgoingCallback)
1418 this._outgoingCallback();
1419 }
1420 }
1421
1422 /**
1423 * @param {*} value
1424 */
1425 function suppressUnused(value)
1426 {
1427 }
1428
1429 /**
1430 * @param {function()} callback
1431 * @return {number}
1432 */
1433 self.setImmediate = function(callback)
1434 {
1435 Promise.resolve().then(callback).done();
1436 return 0;
1437 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/platform/module.json ('k') | Source/devtools/front_end/promises/module.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698