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

Unified Diff: chrome/browser/resources/google_now/utility.js

Issue 19967005: Simplifying using tasks (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: More comments. Created 7 years, 5 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/resources/google_now/utility.js
diff --git a/chrome/browser/resources/google_now/utility.js b/chrome/browser/resources/google_now/utility.js
index eb8f5cc0b741c3924fd80dac07c648a57c8f279e..f70f35c379457c9c012927b37092617ec658b7b1 100644
--- a/chrome/browser/resources/google_now/utility.js
+++ b/chrome/browser/resources/google_now/utility.js
@@ -61,27 +61,50 @@ function buildTaskManager(areConflicting) {
var queue = [];
/**
- * Name of the current step of the currently running task if present,
- * otherwise, null. For diagnostics only.
- * It's set when the task is started and before each asynchronous operation.
+ * Count of unfinished callbacks of the current task.
+ * @type {number}
*/
- var stepName = null;
+ var taskPendingCallbackCount = 0;
+
+ /**
+ * Required callbacks that are not yet called. Includes both task and non-task
+ * callbacks. This is a map from unique callback id to the stack at the moment
+ * when the callback was wrapped. This stack identifies the callback.
+ * Used only for diagnostics.
+ * @type {Object.<number, string>}
+ */
+ var pendingCallbacks = {};
+
+ /**
+ * True if currently executed code is a part of a task.
+ * @type {boolean}
+ */
+ var isInTask = false;
/**
* Starts the first queued task.
*/
function startFirst() {
verify(queue.length >= 1, 'startFirst: queue is empty');
+ verify(!isInTask, 'startFirst: already in task');
+ isInTask = true;
// Start the oldest queued task, but don't remove it from the queue.
verify(
- stepName == null,
- 'tasks.startFirst: stepName is not null: ' + stepName +
- ', queue = ' + JSON.stringify(queue));
+ taskPendingCallbackCount == 0,
+ 'tasks.startFirst: still have pending task callbacks: ' +
+ taskPendingCallbackCount +
+ ', queue = ' + JSON.stringify(queue) +
+ ', pendingCallbacks = ' + JSON.stringify(pendingCallbacks));
var entry = queue[0];
- stepName = entry.name + '-initial';
console.log('Starting task ' + entry.name);
- entry.task(finish);
+
+ entry.task(function() {}); // TODO(vadimt): Don't pass parameter.
+
+ verify(isInTask, 'startFirst: not in task at exit');
+ isInTask = false;
+ if (taskPendingCallbackCount == 0)
arv (Not doing code reviews) 2013/07/24 23:10:19 if (!taskPendingCallbackCount)
vadimt 2013/07/25 00:25:10 Respectfully disagree. It's shorter, but makes cod
+ finish();
}
/**
@@ -126,25 +149,14 @@ function buildTaskManager(areConflicting) {
*/
function finish() {
verify(queue.length >= 1,
- 'tasks.finish: The task queue is empty; step = ' + stepName);
+ 'tasks.finish: The task queue is empty');
console.log('Finishing task ' + queue[0].name);
queue.shift();
- stepName = null;
if (queue.length >= 1)
startFirst();
}
- /**
- * Associates a name with the current step of the task. Used for diagnostics
- * only. A task is a chain of asynchronous events; debugSetStepName should be
- * called before starting any asynchronous operation.
- * @param {string} step Name of new step.
- */
- function debugSetStepName(step) {
- stepName = step;
- }
-
// Limiting 1 error report per background page load.
var errorReported = false;
@@ -187,15 +199,46 @@ function buildTaskManager(areConflicting) {
}
/**
+ * Unique ID of the next callback.
+ * @type {number}
+ */
+ var nextCallbackId = 0;
+
+ /**
* Adds error processing to an API callback.
* @param {Function} callback Callback to instrument.
+ * @param {boolean=} opt_dontRequire True if the callback is not required to
+ * be invoked.
* @return {Function} Instrumented callback.
*/
- function wrapCallback(callback) {
+ function wrapCallback(callback, opt_dontRequire) {
+ verify(!(opt_dontRequire && isInTask), 'Unrequired callback in a task.');
+ var callbackId = nextCallbackId++;
+ var isTaskCallback = isInTask;
+ if (isTaskCallback)
+ ++taskPendingCallbackCount;
+ if (!opt_dontRequire)
+ pendingCallbacks[callbackId] = new Error().stack;
+
return function() {
// This is the wrapper for the callback.
try {
- return callback.apply(null, arguments);
+ if (isTaskCallback) {
+ verify(!isInTask, 'wrapCallback: already in task');
+ isInTask = true;
+ }
+ if (!opt_dontRequire)
+ delete pendingCallbacks[callbackId];
+
+ // Call the original callback.
+ callback.apply(null, arguments);
+
+ if (isTaskCallback) {
+ verify(isInTask, 'wrapCallback: not in task at exit');
+ isInTask = false;
+ if (--taskPendingCallbackCount == 0)
+ finish();
+ }
} catch (error) {
var message = 'Uncaught exception:\n' + error.stack;
console.error(message);
@@ -233,7 +276,8 @@ function buildTaskManager(areConflicting) {
alert('Argument ' + callbackParameter + ' of ' + functionName +
' is not a function');
}
- arguments[callbackParameter] = wrapCallback(callback);
+ arguments[callbackParameter] = wrapCallback(
+ callback, functionName == 'addListener');
return originalFunction.apply(namespace, arguments);
};
}
@@ -242,20 +286,17 @@ function buildTaskManager(areConflicting) {
instrumentApiFunction(chrome.runtime.onSuspend, 'addListener', 0);
chrome.runtime.onSuspend.addListener(function() {
+ var stringifiedPendingCallbacks = JSON.stringify(pendingCallbacks);
verify(
- queue.length == 0,
- 'Incomplete task when unloading event page, queue = ' +
- JSON.stringify(queue) + ', step = ' + stepName);
- verify(
- stepName == null,
- 'Step name not null when unloading event page, queue = ' +
- JSON.stringify(queue) + ', step = ' + stepName);
+ queue.length == 0 && stringifiedPendingCallbacks == '{}',
arv (Not doing code reviews) 2013/07/24 23:10:19 !queue.length
vadimt 2013/07/25 00:25:10 Same.
+ 'Incomplete task or pending callbacks when unloading event page,' +
+ ' queue = ' + JSON.stringify(queue) +
+ ', pendingCallbacks = ' + stringifiedPendingCallbacks);
});
return {
add: add,
- // TODO(vadimt): Replace with instrumenting callbacks.
- debugSetStepName: debugSetStepName,
+ debugSetStepName: function() {}, // TODO(vadimt): remove
instrumentApiFunction: instrumentApiFunction,
wrapCallback: wrapCallback
};
@@ -338,7 +379,6 @@ function buildAttemptManager(
* the planning is done.
*/
function planForNext(callback) {
- tasks.debugSetStepName('planForNext-get-storage');
storage.get(currentDelayStorageKey, function(items) {
console.log('planForNext-get-storage ' + JSON.stringify(items));
scheduleNextAttempt(items[currentDelayStorageKey]);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698