Remove workaround for monospace font resources.
[chromium-blink-merge.git] / tools / playback_benchmark / common.js
blob801d602c3a4d9d41b691999660b74d4ed84ca533
1 // Copyright 2010 Google Inc. All Rights Reserved.
3 /**
4  * @fileoverview Classes and functions used during recording and playback.
5  */
7 var Benchmark = Benchmark || {};
9 Benchmark.functionList = [
10   ['setTimeout', 'setTimeout'],
11   ['clearTimeout', 'clearTimeout'],
12   ['setInterval', 'setInterval'],
13   ['clearInterval', 'clearInterval'],
14   ['XMLHttpRequest', 'XMLHttpRequest'],
15   ['addEventListenerToWindow', 'addEventListener'],
16   ['addEventListenerToNode', 'addEventListener', ['Node', 'prototype']],
17   ['removeEventListenerFromNode', 'removeEventListener', ['Node', 'prototype']],
18   ['addEventListenerToXHR', 'addEventListener',
19    ['XMLHttpRequest', 'prototype']],
20   ['random', 'random', ['Math']],
21   ['Date', 'Date'],
22   ['documentWriteln', 'writeln', ['document']],
23   ['documentWrite', 'write', ['document']]
26 Benchmark.timeoutMapping = [];
28 Benchmark.ignoredListeners = ['mousemove', 'mouseover', 'mouseout'];
30 Benchmark.originals = {};
32 Benchmark.overrides = {
33   setTimeout: function(callback, timeout) {
34     var event = {type: 'timeout', timeout: timeout};
35     var eventId = Benchmark.agent.createAsyncEvent(event);
36     var timerId = Benchmark.originals.setTimeout.call(this, function() {
37       Benchmark.agent.fireAsyncEvent(eventId, callback);
38     }, Benchmark.playback ? 0 : timeout);
39     Benchmark.timeoutMapping[timerId] = eventId;
40     return timerId;
41   },
43   clearTimeout: function(timerId) {
44     var eventId = Benchmark.timeoutMapping[timerId];
45     if (eventId == undefined) return;
46     Benchmark.agent.cancelAsyncEvent(eventId);
47     Benchmark.originals.clearTimeout.call(this, timerId);
48   },
50   setInterval: function(callback, timeout) {
51     console.warn('setInterval');
52   },
54   clearInterval: function(timerId) {
55     console.warn('clearInterval');
56   },
58   XMLHttpRequest: function() {
59     return new Benchmark.XMLHttpRequestWrapper();
60   },
62   addEventListener: function(type, listener, useCapture, target, targetType,
63                              originalFunction) {
64     var event = {type: 'addEventListener', target: targetType, eventType: type};
65     var eventId = Benchmark.agent.createAsyncEvent(event);
66     listener.eventId = eventId;
67     listener.wrapper = function(e) {
68       Benchmark.agent.fireAsyncEvent(eventId, function() {
69         listener.call(target, e);
70       });
71     };
72     originalFunction.call(target, type, listener.wrapper, useCapture);
73   },
75   addEventListenerToWindow: function(type, listener, useCapture) {
76     if (Benchmark.ignoredListeners.indexOf(type) != -1) return;
77     Benchmark.overrides.addEventListener(
78         type, listener, useCapture, this, 'window',
79         Benchmark.originals.addEventListenerToWindow);
80   },
82   addEventListenerToNode: function(type, listener, useCapture) {
83     if (Benchmark.ignoredListeners.indexOf(type) != -1) return;
84     Benchmark.overrides.addEventListener(
85         type, listener, useCapture, this, 'node',
86         Benchmark.originals.addEventListenerToNode);
87   },
89   addEventListenerToXHR: function(type, listener, useCapture) {
90     Benchmark.overrides.addEventListener(
91         type, listener, useCapture, this, 'xhr',
92         Benchmark.originals.addEventListenerToXHR);
93   },
95   removeEventListener: function(type, listener, useCapture, target,
96                                 originalFunction) {
97     Benchmark.agent.cancelAsyncEvent(listener.eventId);
98     originalFunction.call(target, listener.wrapper, useCapture);
99   },
101   removeEventListenerFromWindow: function(type, listener, useCapture) {
102     removeEventListener(type, listener, useCapture, this,
103                         Benchmark.originals.removeEventListenerFromWindow);
104   },
106   removeEventListenerFromNode: function(type, listener, useCapture) {
107     removeEventListener(type, listener, useCapture, this,
108         Benchmark.originals.removeEventListenerFromNode);
109   },
111   removeEventListenerFromXHR: function(type, listener, useCapture) {
112     removeEventListener(type, listener, useCapture, this,
113         Benchmark.originals.removeEventListenerFromXHR);
114   },
116   random: function() {
117     return Benchmark.agent.random();
118   },
120   Date: function() {
121     var a = arguments;
122     var D = Benchmark.originals.Date, d;
123     switch(a.length) {
124       case 0: d = new D(Benchmark.agent.dateNow()); break;
125       case 1: d = new D(a[0]); break;
126       case 2: d = new D(a[0], a[1]); break;
127       case 3: d = new D(a[0], a[1], a[2]); break;
128       default: Benchmark.die('window.Date', arguments);
129     }
130     d.getTimezoneOffset = function() { return -240; };
131     return d;
132   },
134   dateNow: function() {
135     return Benchmark.agent.dateNow();
136   },
138   documentWriteln: function() {
139     console.warn('writeln');
140   },
142   documentWrite: function() {
143     console.warn('write');
144   }
148  * Replaces window functions specified by Benchmark.functionList with overrides
149  * and optionally saves original functions to Benchmark.originals.
150  * @param {Object} wnd Window object.
151  * @param {boolean} storeOriginals When true, original functions are saved to
152  * Benchmark.originals.
153  */
154 Benchmark.installOverrides = function(wnd, storeOriginals) {
155   // Substitute window functions with overrides.
156   for (var i = 0; i < Benchmark.functionList.length; ++i) {
157     var info = Benchmark.functionList[i], object = wnd;
158     var propertyName = info[1], pathToProperty = info[2];
159     if (pathToProperty)
160       for (var j = 0; j < pathToProperty.length; ++j)
161         object = object[pathToProperty[j]];
162     if (storeOriginals)
163       Benchmark.originals[info[0]] = object[propertyName];
164     object[propertyName] = Benchmark.overrides[info[0]];
165   }
166   wnd.__defineSetter__('onload', function() {
167     console.warn('window.onload setter')}
168   );
170   // Substitute window functions of static frames when DOM content is loaded.
171   Benchmark.originals.addEventListenerToWindow.call(wnd, 'DOMContentLoaded',
172                                                     function() {
173     var frames = document.getElementsByTagName('iframe');
174     for (var i = 0, frame; frame = frames[i]; ++i) {
175       Benchmark.installOverrides(frame.contentWindow);
176     }
177   }, true);
179   // Substitute window functions of dynamically added frames.
180   Benchmark.originals.addEventListenerToWindow.call(
181       wnd, 'DOMNodeInsertedIntoDocument', function(e) {
182         if (e.target.tagName && e.target.tagName.toLowerCase() != 'iframe')
183           return;
184         if (e.target.contentWindow)
185           Benchmark.installOverrides(e.target.contentWindow);
186       }, true);
189 // Install overrides on top window.
190 Benchmark.installOverrides(window, true);
193  * window.XMLHttpRequest wrapper. Notifies Benchmark.agent when request is
194  * opened, aborted, and when it's ready state changes to DONE.
195  * @constructor
196  */
197 Benchmark.XMLHttpRequestWrapper = function() {
198   this.request = new Benchmark.originals.XMLHttpRequest();
199   this.wrapperReadyState = 0;
202 // Create XMLHttpRequestWrapper functions and property accessors using original
203 // ones.
204 (function() {
205   var request = new Benchmark.originals.XMLHttpRequest();
206   for (var property in request) {
207     if (property === 'channel') continue; // Quick fix for FF.
208     if (typeof(request[property]) == 'function') {
209       (function(property) {
210         var f = Benchmark.originals.XMLHttpRequest.prototype[property];
211         Benchmark.XMLHttpRequestWrapper.prototype[property] = function() {
212           f.apply(this.request, arguments);
213         };
214       })(property);
215     } else {
216       (function(property) {
217         Benchmark.XMLHttpRequestWrapper.prototype.__defineGetter__(property,
218             function() { return this.request[property]; });
219         Benchmark.XMLHttpRequestWrapper.prototype.__defineSetter__(property,
220             function(value) {
221               this.request[property] = value;
222             });
224       })(property);
225     }
226   }
227 })();
229 // Define onreadystatechange getter.
230 Benchmark.XMLHttpRequestWrapper.prototype.__defineGetter__('onreadystatechange',
231     function() { return this.clientOnReadyStateChange; });
233 // Define onreadystatechange setter.
234 Benchmark.XMLHttpRequestWrapper.prototype.__defineSetter__('onreadystatechange',
235     function(value) { this.clientOnReadyStateChange = value; });
237 Benchmark.XMLHttpRequestWrapper.prototype.__defineGetter__('readyState',
238     function() { return this.wrapperReadyState; });
240 Benchmark.XMLHttpRequestWrapper.prototype.__defineSetter__('readyState',
241     function() {});
245  * Wrapper for XMLHttpRequest.open.
246  */
247 Benchmark.XMLHttpRequestWrapper.prototype.open = function() {
248   var url = Benchmark.extractURL(arguments[1]);
249   var event = {type: 'request', method: arguments[0], url: url};
250   this.eventId = Benchmark.agent.createAsyncEvent(event);
252   var request = this.request;
253   var requestWrapper = this;
254   Benchmark.originals.XMLHttpRequest.prototype.open.apply(request, arguments);
255   request.onreadystatechange = function() {
256     if (this.readyState != 4 || requestWrapper.cancelled) return;
257     var callback = requestWrapper.clientOnReadyStateChange || function() {};
258     Benchmark.agent.fireAsyncEvent(requestWrapper.eventId, function() {
259       requestWrapper.wrapperReadyState = 4;
260       callback.call(request);
261     });
262   }
266  * Wrapper for XMLHttpRequest.abort.
267  */
268 Benchmark.XMLHttpRequestWrapper.prototype.abort = function() {
269   this.cancelled = true;
270   Benchmark.originals.XMLHttpRequest.prototype.abort.apply(
271       this.request, arguments);
272   Benchmark.agent.cancelAsyncEvent(this.eventId);
276  * Driver url for reporting results.
277  * @const {string}
278  */
279 Benchmark.DRIVER_URL = '/benchmark/';
282  * Posts request as json to Benchmark.DRIVER_URL.
283  * @param {Object} request Request to post.
284  */
285 Benchmark.post = function(request, async) {
286   if (async === undefined) async = true;
287   var xmlHttpRequest = new Benchmark.originals.XMLHttpRequest();
288   xmlHttpRequest.open("POST", Benchmark.DRIVER_URL, async);
289   xmlHttpRequest.setRequestHeader("Content-type", "application/json");
290   xmlHttpRequest.send(JSON.stringify(request));
294  * Extracts url string.
295  * @param {(string|Object)} url Object or string representing url.
296  * @return {string} Extracted url.
297  */
298 Benchmark.extractURL = function(url) {
299   if (typeof(url) == 'string') return url;
300   return url.nI || url.G || '';
305  * Logs error message to console and throws an exception.
306  * @param {string} message Error message
307  */
308 Benchmark.die = function(message) {
309   // Debugging stuff.
310   var position = top.Benchmark.playback ? top.Benchmark.agent.timelinePosition :
311                  top.Benchmark.agent.timeline.length;
312   message = message + ' at position ' + position;
313   console.error(message);
314   Benchmark.post({error: message});
315   console.log(Benchmark.originals.setTimeout.call(window, function() {}, 9999));
316   try { (0)() } catch(ex) { console.error(ex.stack); }
317   throw message;