Skip to content

Commit ecfefd3

Browse files
committed
Keep track of which frames are used to execute tasks.
This allows us to produce more accurate snapshot of a control flow's internal state for debugging.
1 parent 120c8ab commit ecfefd3

File tree

1 file changed

+55
-10
lines changed

1 file changed

+55
-10
lines changed

javascript/webdriver/promise.js

Lines changed: 55 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,37 +1411,54 @@ promise.ControlFlow.prototype.annotateError = function(e) {
14111411
*/
14121412
promise.ControlFlow.prototype.getSchedule = function(opt_includeStackTraces) {
14131413
var ret = 'ControlFlow::' + goog.getUid(this);
1414-
if (!this.activeFrame_) {
1414+
var activeFrame = this.activeFrame_;
1415+
if (!activeFrame) {
14151416
return ret;
14161417
}
14171418
var childIndent = '| ';
1418-
return ret + '\n' + toStringHelper(this.activeFrame_.getRoot(), childIndent);
1419+
return ret + '\n' + toStringHelper(activeFrame.getRoot(), childIndent);
14191420

14201421
/**
14211422
* @param {!(promise.Frame_|promise.Task_)} node .
14221423
* @param {string} indent .
1424+
* @param {boolean=} opt_isPending .
14231425
* @return {string} .
14241426
*/
1425-
function toStringHelper(node, indent) {
1427+
function toStringHelper(node, indent, opt_isPending) {
14261428
var ret = node.toString();
1429+
if (opt_isPending) {
1430+
ret = '(pending) ' + ret;
1431+
}
1432+
if (node === activeFrame) {
1433+
ret = '(active) ' + ret;
1434+
}
14271435
if (node instanceof promise.Frame_) {
14281436
if (node.getPendingTask()) {
14291437
ret += '\n' + toStringHelper(
14301438
/** @type {!promise.Task_} */(node.getPendingTask()),
1431-
childIndent);
1439+
childIndent,
1440+
true);
14321441
}
14331442
if (node.children_) {
14341443
goog.array.forEach(node.children_, function(child) {
1435-
ret += '\n' + toStringHelper(child, childIndent);
1444+
if (!node.getPendingTask() ||
1445+
node.getPendingTask().getFrame() !== child) {
1446+
ret += '\n' + toStringHelper(child, childIndent);
1447+
}
14361448
});
14371449
}
1438-
} else if (opt_includeStackTraces) {
1450+
} else {
14391451
var task = /** @type {!promise.Task_} */(node);
1440-
if (task.promise.stack_) {
1452+
if (opt_includeStackTraces && task.promise.stack_) {
14411453
ret += '\n' + childIndent +
14421454
(task.promise.stack_.stack || task.promise.stack_).
14431455
replace(/\n/g, '\n' + childIndent);
14441456
}
1457+
if (task.getFrame()) {
1458+
ret += '\n' + toStringHelper(
1459+
/** @type {!promise.Frame_} */(task.getFrame()),
1460+
childIndent);
1461+
}
14451462
}
14461463
return indent + ret.replace(/\n/g, '\n' + indent);
14471464
}
@@ -1725,18 +1742,21 @@ promise.ControlFlow.prototype.runEventLoop_ = function() {
17251742

17261743
var onSuccess = function(value) {
17271744
activeFrame.setPendingTask(null);
1745+
task.setFrame(null);
17281746
task.fulfill(value);
17291747
scheduleEventLoop();
17301748
};
17311749

17321750
var onFailure = function(reason) {
17331751
activeFrame.setPendingTask(null);
1752+
task.setFrame(null);
17341753
task.reject(reason);
17351754
scheduleEventLoop();
17361755
};
17371756

17381757
activeFrame.setPendingTask(task);
17391758
var frame = new promise.Frame_(this);
1759+
task.setFrame(frame);
17401760
this.runInFrame_(frame, task.execute, function(result) {
17411761
promise.asap(result, onSuccess, onFailure);
17421762
}, onFailure, true);
@@ -1846,9 +1866,7 @@ promise.ControlFlow.prototype.runInFrame_ = function(
18461866
oldFrame = this.activeFrame_;
18471867

18481868
try {
1849-
if (!this.activeFrame_) {
1850-
this.activeFrame_ = newFrame;
1851-
} else if (this.activeFrame_ !== newFrame && !newFrame.getParent()) {
1869+
if (this.activeFrame_ !== newFrame && !newFrame.getParent()) {
18521870
this.activeFrame_.addChild(newFrame);
18531871
}
18541872

@@ -2229,6 +2247,14 @@ promise.Frame_ = goog.defineClass(webdriver.EventEmitter, {
22292247
this.pendingTask_ = task;
22302248
},
22312249

2250+
/**
2251+
* @return {boolean} Whether this frame is empty (has no scheduled tasks or
2252+
* pending callback frames).
2253+
*/
2254+
isEmpty: function() {
2255+
return !this.children_ || !this.children_.length;
2256+
},
2257+
22322258
/**
22332259
* Adds a new node to this frame.
22342260
* @param {!(promise.Frame_|promise.Task_)} node The node to insert.
@@ -2330,6 +2356,25 @@ promise.Task_ = goog.defineClass(promise.Deferred, {
23302356

23312357
/** @private {promise.Frame_} */
23322358
this.parent_ = null;
2359+
2360+
/** @private {promise.Frame_} */
2361+
this.frame_ = null;
2362+
},
2363+
2364+
/**
2365+
* @return {promise.Frame_} frame The frame used to run this task's
2366+
* {@link #execute} method.
2367+
*/
2368+
getFrame: function() {
2369+
return this.frame_;
2370+
},
2371+
2372+
/**
2373+
* @param {promise.Frame_} frame The frame used to run this task's
2374+
* {@link #execute} method.
2375+
*/
2376+
setFrame: function(frame) {
2377+
this.frame_ = frame;
23332378
},
23342379

23352380
/**

0 commit comments

Comments
 (0)