cache scope tree, fix issue with cache invalidation

test-unit-sauce
Brian Ford 11 years ago
parent b2c7ac52a4
commit 6cfcaa8545

@ -1,29 +1,61 @@
// notify of page refreshes
// scopes need to be cached here so that if the devtools connects,
// the list of scopes can be immediately populated
// TODO: clear this on refresh ?
var scopeCache = {};
var scopeCacheEmpty = function () {
return Object.keys(scopeCache).length;
};
// messages to be forwarded from content script to the devtools
var toForward = [
'modelChange',
'scopeChange',
'watcherChange',
'watchPerfChange',
'applyPerfChange'
];
chrome.extension.onConnect.addListener(function (port) {
port.onMessage.addListener(function (msg) {
// notify of page refreshes
if (msg.action === 'register') {
var respond = function (tabId, changeInfo, tab) {
if (tabId !== msg.inspectedTabId) {
return;
}
port.postMessage('refresh');
};
chrome.tabs.onUpdated.addListener(respond);
port.onDisconnect.addListener(function () {
chrome.tabs.onUpdated.removeListener(respond);
});
function respond (tabId, changeInfo, tab) {
if (tabId === msg.inspectedTabId) {
port.postMessage('refresh');
}
}
}
});
chrome.extension.onMessage.addListener(function (msg) {
if (msg.action === 'modelChange' ||
msg.action === 'scopeChange' ||
msg.action === 'watcherChange') {
if (toForward.indexOf(msg.action) !== -1) {
port.postMessage(msg);
}
});
// immediately populate the scopes tree from the cache
// TODO: how do we know that the cache refers to the
// tab that we're connected to?
Object.keys(scopeCache).forEach(function (scopeId) {
port.postMessage({
action: 'scopeChange',
scope: scopeCache[scopeId],
scopeId: scopeId
});
});
});
chrome.extension.onMessage.addListener(function (msg) {
if (msg.action === 'scopeChange') {
scopeCache[msg.id] = msg.scope;
}
});

@ -145,6 +145,9 @@ var instument = function instument (window) {
// map of scope.$ids --> $scope objects
scopes: {},
// whether or not to emit profile data
profiling: false,
// map of $ids --> [] array of things being watched
modelWatchers: {},
// map of $id + watcher --> value
@ -257,6 +260,26 @@ var instument = function instument (window) {
}
}, 50),
watchPerfChange: throttle(function (str) {
if (debug.profiling) {
fireCustomEvent({
action: 'watchPerfChange',
watcher: str,
value: debug.watchPerf[str]
});
}
}, 50),
applyPerfChange: throttle(function (str) {
if (debug.profiling) {
fireCustomEvent({
action: 'applyPerfChange',
watcher: str,
value: debug.applyPerf[str]
});
}
}, 50),
// might be worth limiting
watchPerf: function () {
throw new Error('Implement me :c');
@ -313,6 +336,10 @@ var instument = function instument (window) {
var api = window.__ngDebug = {
profiling: function (setting) {
debug.profiling = setting;
},
getDeps: function () {
return debug.deps;
},
@ -340,18 +367,32 @@ var instument = function instument (window) {
].
forEach(function (attr) {
var val = $elt.attr(attr),
className = $elt[0].className;
className = $elt[0].className,
match,
lhs,
valueIdentifier,
keyIdentifier;
if (val) {
name[attr] = val;
if (attr === 'ng-repeat') {
var lhs = /(.+) in/.exec(val);
lhs = lhs[1];
name.lhs = lhs + summarizeObject(scope[lhs]);
match = /(.+) in/.exec(val);
lhs = match[1];
match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
valueIdentifier = match[3] || match[1];
keyIdentifier = match[2];
if (keyIdentifier) {
name.lhs = valueIdentifier + '["' + scope[keyIdentifier] + '"]' + summarizeObject(scope[valueIdentifier]);
} else {
name.lhs = valueIdentifier + summarizeObject(scope[valueIdentifier]);
}
}
} else if (className.indexOf(attr) !== -1) {
val = (new RegExp(attr + ': ([a-zA-Z0-9]+);')).exec(className);
val = val[1];
name[attr] = val;
match = (new RegExp(attr + ': ([a-zA-Z0-9]+);')).exec(className);
name[attr] = match[1];
}
});
@ -430,6 +471,9 @@ var instument = function instument (window) {
watchModel: function (id, path) {
debug.modelWatchers[id] = debug.modelWatchers[id] || {};
debug.modelWatchers[id][path || ''] = true;
if (!path || path === '') {
debug.modelWatchersState = {};
}
emit.modelChange(id);
emit.watcherChange(id);
},
@ -895,6 +939,7 @@ var instument = function instument (window) {
var end = performance.now();
debug.watchPerf[watchStr].time += (end - start);
debug.watchPerf[watchStr].calls += 1;
emit.watchPerfChange(watchStr);
return ret;
};
} else {
@ -904,6 +949,7 @@ var instument = function instument (window) {
var end = performance.now();
debug.watchPerf[watchStr].time += (end - start);
debug.watchPerf[watchStr].calls += 1;
emit.watchPerfChange(watchStr);
return ret;
};
}
@ -927,6 +973,7 @@ var instument = function instument (window) {
}
debug.applyPerf[applyStr].time += (end - start);
debug.applyPerf[applyStr].calls += 1;
emit.applyPerfChange(applyStr);
return ret;
};
}

@ -31,12 +31,6 @@ angular.module('panelApp').factory('appContext', function (chromeExtension, $roo
"}", args, cb);
},
refresh: function (cb) {
chromeExtension.eval(function (window) {
window.document.location.reload();
}, cb);
},
inspect: function (scopeId) {
this.executeOnScope(scopeId, function (scope, elt) {
inspect(elt);
@ -49,9 +43,12 @@ angular.module('panelApp').factory('appContext', function (chromeExtension, $roo
// takes a bool
setDebug: function (setting) {
if (setting) {
// prevent a refresh if debugging is already enabled
chromeExtension.eval(function (window) {
window.document.cookie = '__ngDebug=true;';
window.document.location.reload();
if (document.cookie.indexOf('__ngDebug=true') === -1) {
window.document.cookie = '__ngDebug=true;';
window.document.location.reload();
}
});
} else {
chromeExtension.eval(function (window) {

@ -5,9 +5,7 @@ angular.module('panelApp').factory('appModel', function (chromeExtension, appCon
_scopeCache = {},
_rootScopeCache = [];
// clear cache on page refresh
appContext.watchRefresh(function () {
appContext.watchRefresh(function clearCaches () {
_scopeCache = {};
_scopeTreeCache = {};
_rootScopeCache = [];