mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-01-12 22:45:52 +08:00
feat: add WTF tracing
- $digest - $digest#asyncQueue - $digest#postDigestQueue - $eval - $watcher - $compile#compile - $compile#link - $timeout Show events (ng-click, etc.) expressions. Show watched expressions. Show $timeout callbacks. Show reslving/rejecting promises details.
This commit is contained in:
@@ -103,6 +103,8 @@
|
||||
* <div doc-module-components="ng"></div>
|
||||
*/
|
||||
|
||||
var WTF_ENABLED = WTF && WTF.PRESENT;
|
||||
|
||||
var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
|
||||
|
||||
// The name of a form control's ValidityState property.
|
||||
|
||||
@@ -1024,12 +1024,23 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
*/
|
||||
function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
|
||||
previousCompileContext) {
|
||||
var wtfScope, wtfHtml;
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfScope = WTF.trace.enterScope('$compile#compile');
|
||||
wtfHtml = '';
|
||||
}
|
||||
|
||||
var linkFns = [],
|
||||
attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound, nodeLinkFnFound;
|
||||
|
||||
for (var i = 0; i < nodeList.length; i++) {
|
||||
attrs = new Attributes();
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfHtml += (nodeList[i].outerHTML || '');
|
||||
}
|
||||
|
||||
// we must always refer to nodeList[i] since the nodes can be replaced underneath us.
|
||||
directives = collectDirectives(nodeList[i], [], attrs, i === 0 ? maxPriority : undefined,
|
||||
ignoreDirective);
|
||||
@@ -1062,12 +1073,18 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
previousCompileContext = null;
|
||||
}
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.appendScopeData('html', wtfHtml);
|
||||
WTF.trace.leaveScope(wtfScope);
|
||||
}
|
||||
|
||||
// return a linking function if we have found anything, null otherwise
|
||||
return linkFnFound ? compositeLinkFn : null;
|
||||
|
||||
function compositeLinkFn(scope, nodeList, $rootElement, parentBoundTranscludeFn) {
|
||||
var nodeLinkFn, childLinkFn, node, childScope, i, ii, idx, childBoundTranscludeFn;
|
||||
var stableNodeList;
|
||||
var wtfLinkScope;
|
||||
|
||||
|
||||
if (nodeLinkFnFound) {
|
||||
@@ -1090,6 +1107,11 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
nodeLinkFn = linkFns[i++];
|
||||
childLinkFn = linkFns[i++];
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfLinkScope = WTF.trace.enterScope('$compile#link');
|
||||
WTF.trace.appendScopeData('html', node.outerHTML || node.textContent);
|
||||
}
|
||||
|
||||
if (nodeLinkFn) {
|
||||
if (nodeLinkFn.scope) {
|
||||
childScope = scope.$new();
|
||||
@@ -1118,6 +1140,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
|
||||
} else if (childLinkFn) {
|
||||
childLinkFn(scope, node.childNodes, undefined, parentBoundTranscludeFn);
|
||||
}
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.leaveScope(wtfLinkScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,13 @@ forEach(
|
||||
var callback = function() {
|
||||
fn(scope, {$event:event});
|
||||
};
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
callback.toString = function() {
|
||||
return 'ng-' + name + '="' + attr[directiveName] + '"';
|
||||
};
|
||||
}
|
||||
|
||||
if (forceAsyncEvents[eventName] && scope.$$phase) {
|
||||
scope.$evalAsync(callback);
|
||||
} else {
|
||||
|
||||
@@ -1117,6 +1117,11 @@ function $ParseProvider() {
|
||||
// initial value is defined (for bind-once)
|
||||
return isDefined(value) ? result : value;
|
||||
};
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
fn.exp = parsedExpression;
|
||||
}
|
||||
|
||||
fn.$$watchDelegate = parsedExpression.$$watchDelegate;
|
||||
return fn;
|
||||
}
|
||||
|
||||
23
src/ng/q.js
23
src/ng/q.js
@@ -325,7 +325,28 @@ function qFactory(nextTick, exceptionHandler) {
|
||||
function scheduleProcessQueue(state) {
|
||||
if (state.processScheduled || !state.pending) return;
|
||||
state.processScheduled = true;
|
||||
nextTick(function() { processQueue(state); });
|
||||
|
||||
var fn = function() { processQueue(state); };
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
var pending = state.pending;
|
||||
|
||||
fn.toString = function() {
|
||||
var callbacks = state.pending.map(function(p) {
|
||||
return p[state.status];
|
||||
}).filter(function(callback) {
|
||||
return !!callback;
|
||||
}).map(function(callback) {
|
||||
return callback.name || callback.toString();
|
||||
});
|
||||
|
||||
return (state.status === 1 ? 'resolving' : 'rejecting') + ' promise\n' +
|
||||
'callbacks (' + callbacks.length + '):\n' + callbacks.join('\n\n') + '\n\n' +
|
||||
'value: ' + toJson(state.value, true);
|
||||
};
|
||||
}
|
||||
|
||||
nextTick(fn);
|
||||
}
|
||||
|
||||
function Deferred() {
|
||||
|
||||
@@ -622,6 +622,11 @@ function $RootScopeProvider(){
|
||||
}
|
||||
}
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
$watchCollectionAction.exp = listener;
|
||||
changeDetector.exp = obj;
|
||||
}
|
||||
|
||||
return this.$watch(changeDetector, $watchCollectionAction);
|
||||
},
|
||||
|
||||
@@ -687,6 +692,15 @@ function $RootScopeProvider(){
|
||||
watchLog = [],
|
||||
logIdx, logMsg, asyncTask;
|
||||
|
||||
var wtfDigestScope, wtfDigestCycleScope, wtfDigestCycleCount, wtfAsyncQueueScope,
|
||||
wtfAsyncQueueCount, wtfWatcherScope;
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfDigestScope = WTF.trace.enterScope('$digest');
|
||||
wtfDigestCycleCount = 0;
|
||||
wtfAsyncQueueCount = 0;
|
||||
}
|
||||
|
||||
beginPhase('$digest');
|
||||
// Check for changes to browser url that happened in sync before the call to $digest
|
||||
$browser.$$checkUrlChange();
|
||||
@@ -704,8 +718,17 @@ function $RootScopeProvider(){
|
||||
dirty = false;
|
||||
current = target;
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfDigestCycleCount++;
|
||||
wtfDigestCycleScope = WTF.trace.enterScope('$digest#' + wtfDigestCycleCount);
|
||||
wtfAsyncQueueScope = WTF.trace.enterScope('$digest#asyncQueue');
|
||||
}
|
||||
|
||||
while(asyncQueue.length) {
|
||||
try {
|
||||
if (WTF_ENABLED) {
|
||||
wtfAsyncQueueCount++
|
||||
}
|
||||
asyncTask = asyncQueue.shift();
|
||||
asyncTask.scope.$eval(asyncTask.expression);
|
||||
} catch (e) {
|
||||
@@ -714,6 +737,11 @@ function $RootScopeProvider(){
|
||||
lastDirtyWatch = null;
|
||||
}
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.appendScopeData('length', wtfAsyncQueueCount);
|
||||
WTF.trace.leaveScope(wtfAsyncQueueScope);
|
||||
}
|
||||
|
||||
traverseScopesLoop:
|
||||
do { // "traverse the scopes" loop
|
||||
if ((watchers = current.$$watchers)) {
|
||||
@@ -733,7 +761,33 @@ function $RootScopeProvider(){
|
||||
dirty = true;
|
||||
lastDirtyWatch = watch;
|
||||
watch.last = watch.eq ? copy(value, null) : value;
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfWatcherScope = WTF.trace.enterScope('watcher');
|
||||
if (watch.exp) {
|
||||
// interpolation watch.exp.exp
|
||||
// parse watch.exp
|
||||
if (watch.exp.exp) {
|
||||
WTF.trace.appendScopeData('exp', watch.exp.exp.toString());
|
||||
} else if (Object.hasOwnProperty.call(watch.exp, 'toString')) {
|
||||
WTF.trace.appendScopeData('exp', watch.exp.toString());
|
||||
} else {
|
||||
WTF.trace.appendScopeData('exp', watch.exp.name || watch.exp.toString());
|
||||
}
|
||||
}
|
||||
|
||||
WTF.trace.appendScopeData('get', (watch.get.name || watch.get.toString()));
|
||||
WTF.trace.appendScopeData('fn', (watch.fn.name || watch.fn.toString()));
|
||||
WTF.trace.appendScopeData('previous', toJson(last));
|
||||
WTF.trace.appendScopeData('current', toJson(value));
|
||||
}
|
||||
|
||||
watch.fn(value, ((last === initWatchVal) ? value : last), current);
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.leaveScope(wtfWatcherScope);
|
||||
}
|
||||
|
||||
if (ttl < 5) {
|
||||
logIdx = 4 - ttl;
|
||||
if (!watchLog[logIdx]) watchLog[logIdx] = [];
|
||||
@@ -777,17 +831,41 @@ function $RootScopeProvider(){
|
||||
TTL, toJson(watchLog));
|
||||
}
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.leaveScope(wtfDigestCycleScope);
|
||||
}
|
||||
|
||||
} while (dirty || asyncQueue.length);
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.appendScopeData('cycles', wtfDigestCycleCount);
|
||||
WTF.trace.leaveScope(wtfDigestScope);
|
||||
}
|
||||
|
||||
clearPhase();
|
||||
|
||||
var wtfPostDigestQueueScope, wtfPostDigestQueueCount;
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfPostDigestQueueScope = WTF.trace.enterScope('$digest#postDigestQueue');
|
||||
wtfPostDigestQueueCount = 0;
|
||||
}
|
||||
|
||||
while(postDigestQueue.length) {
|
||||
try {
|
||||
if (WTF_ENABLED) {
|
||||
wtfPostDigestQueueCount++;
|
||||
}
|
||||
postDigestQueue.shift()();
|
||||
} catch (e) {
|
||||
$exceptionHandler(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.appendScopeData('length', wtfPostDigestQueueCount);
|
||||
WTF.trace.leaveScope(wtfPostDigestQueueScope);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -895,6 +973,20 @@ function $RootScopeProvider(){
|
||||
* @returns {*} The result of evaluating the expression.
|
||||
*/
|
||||
$eval: function(expr, locals) {
|
||||
if (WTF_ENABLED) {
|
||||
var wtfScope = WTF.trace.enterScope('$eval');
|
||||
|
||||
if (expr) {
|
||||
WTF.trace.appendScopeData('expression', Object.hasOwnProperty.call(expr, 'toString') ? expr.toString() : (expr.name || expr.toString()));
|
||||
}
|
||||
|
||||
var result = $parse(expr)(this, locals);
|
||||
|
||||
WTF.trace.leaveScope(wtfScope);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
return $parse(expr)(this, locals);
|
||||
},
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ function $TimeoutProvider() {
|
||||
timeoutId;
|
||||
|
||||
timeoutId = $browser.defer(function() {
|
||||
var wtfScope;
|
||||
|
||||
if (WTF_ENABLED) {
|
||||
wtfScope = WTF.trace.enterScope('$timeout');
|
||||
WTF.trace.appendScopeData('fn', fn.name || fn.toString());
|
||||
}
|
||||
|
||||
try {
|
||||
deferred.resolve(fn());
|
||||
} catch(e) {
|
||||
@@ -50,6 +57,9 @@ function $TimeoutProvider() {
|
||||
}
|
||||
|
||||
if (!skipApply) $rootScope.$apply();
|
||||
if (WTF_ENABLED) {
|
||||
WTF.trace.leaveScope(wtfScope);
|
||||
}
|
||||
}, delay);
|
||||
|
||||
promise.$$timeoutId = timeoutId;
|
||||
|
||||
Reference in New Issue
Block a user