Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / src / tvcm / raf.js
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 tvcm.require('tvcm.utils');
8
9 tvcm.exportTo('tvcm', function() {
10   // Setting this to true will cause stack traces to get dumped into the
11   // tasks. When an exception happens the original stack will be printed.
12   //
13   // NOTE: This should never be set committed as true.
14   var recordRAFStacks = false;
15
16   var pendingPreAFs = [];
17   var pendingRAFs = [];
18   var pendingIdleCallbacks = [];
19   var currentRAFDispatchList = undefined;
20
21   var rafScheduled = false;
22
23   function scheduleRAF() {
24     if (rafScheduled)
25       return;
26     rafScheduled = true;
27     if (window.requestAnimationFrame) {
28       window.requestAnimationFrame(processRequests);
29     } else {
30       var delta = Date.now() - window.performance.now();
31       window.webkitRequestAnimationFrame(function(domTimeStamp) {
32         processRequests(domTimeStamp - delta);
33       });
34     }
35   }
36
37   function onAnimationFrameError(e, opt_stack) {
38     if (opt_stack)
39       console.log(opt_stack);
40
41     if (e.message)
42       console.error(e.message, e.stack);
43     else
44       console.error(e);
45   }
46
47   function runTask(task, frameBeginTime) {
48     try {
49       task.callback.call(task.context, frameBeginTime);
50     } catch (e) {
51       tvcm.onAnimationFrameError(e, task.stack);
52     }
53   }
54
55   function processRequests(frameBeginTime) {
56     // We assume that we want to do a maximum of 10ms optional work per frame.
57     // Hopefully rAF will eventually pass this in for us.
58     var rafCompletionDeadline = frameBeginTime + 10;
59
60     rafScheduled = false;
61
62     var currentPreAFs = pendingPreAFs;
63     currentRAFDispatchList = pendingRAFs;
64     pendingPreAFs = [];
65     pendingRAFs = [];
66     var hasRAFTasks = currentPreAFs.length || currentRAFDispatchList.length;
67
68     for (var i = 0; i < currentPreAFs.length; i++)
69       runTask(currentPreAFs[i], frameBeginTime);
70
71     while (currentRAFDispatchList.length > 0)
72       runTask(currentRAFDispatchList.shift(), frameBeginTime);
73     currentRAFDispatchList = undefined;
74
75     if (!hasRAFTasks) {
76       while (pendingIdleCallbacks.length > 0) {
77         runTask(pendingIdleCallbacks.shift());
78         // Check timer after running at least one idle task to avoid buggy
79         // window.performance.now() on some platforms from blocking the idle
80         // task queue.
81         if (window.performance.now() >= rafCompletionDeadline)
82           break;
83       }
84     }
85
86     if (pendingIdleCallbacks.length > 0)
87       scheduleRAF();
88   }
89
90   function getStack_() {
91     if (!recordRAFStacks)
92       return '';
93
94     var stackLines = tvcm.stackTrace();
95     // Strip off getStack_.
96     stackLines.shift();
97     return stackLines.join('\n');
98   }
99
100   function requestPreAnimationFrame(callback, opt_this) {
101     pendingPreAFs.push({
102       callback: callback,
103       context: opt_this || window,
104       stack: getStack_()});
105     scheduleRAF();
106   }
107
108   function requestAnimationFrameInThisFrameIfPossible(callback, opt_this) {
109     if (!currentRAFDispatchList) {
110       requestAnimationFrame(callback, opt_this);
111       return;
112     }
113     currentRAFDispatchList.push({
114       callback: callback,
115       context: opt_this || window,
116       stack: getStack_()});
117     return;
118   }
119
120   function requestAnimationFrame(callback, opt_this) {
121     pendingRAFs.push({
122       callback: callback,
123       context: opt_this || window,
124       stack: getStack_()});
125     scheduleRAF();
126   }
127
128   function requestIdleCallback(callback, opt_this) {
129     pendingIdleCallbacks.push({
130       callback: callback,
131       context: opt_this || window,
132       stack: getStack_()});
133     scheduleRAF();
134   }
135
136   function forcePendingRAFTasksToRun(frameBeginTime) {
137     if (!rafScheduled)
138       return;
139     processRequests(frameBeginTime);
140   }
141
142   return {
143     onAnimationFrameError: onAnimationFrameError,
144     requestPreAnimationFrame: requestPreAnimationFrame,
145     requestAnimationFrame: requestAnimationFrame,
146     requestAnimationFrameInThisFrameIfPossible:
147         requestAnimationFrameInThisFrameIfPossible,
148     requestIdleCallback: requestIdleCallback,
149     forcePendingRAFTasksToRun: forcePendingRAFTasksToRun
150   };
151 });