Skip to content

Commit 9cce3a4

Browse files
committed
feat(visualizer): wrap it into a chrome extension
Update the visualizer app to consume new serialization format (now anything can be a token and so we use serialized ids). Clicking an injector or provider will inspect given object in console. Handle multiple root injectors.
1 parent 5df586e commit 9cce3a4

12 files changed

+179
-23
lines changed

chrome-extension/background.html

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<html>
2+
<body>
3+
<script src="background.js"></script>
4+
</body>
5+
</html>

chrome-extension/background.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// TODO(vojta): Make refresh work
2+
// notify of page refreshes
3+
chrome.extension.onConnect.addListener(function(port) {
4+
port.onMessage.addListener(function (msg) {
5+
if (msg.action === 'register') {
6+
var respond = function (tabId, changeInfo, tab) {
7+
if (tabId !== msg.inspectedTabId) {
8+
return;
9+
}
10+
port.postMessage('refresh');
11+
};
12+
13+
chrome.tabs.onUpdated.addListener(respond);
14+
port.onDisconnect.addListener(function () {
15+
chrome.tabs.onUpdated.removeListener(respond);
16+
});
17+
}
18+
});
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<html>
2+
<body>
3+
<script src="devtools_background.js"></script>
4+
</body>
5+
</html>
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Create DI panel.
2+
chrome.devtools.panels.create(
3+
'DI',
4+
'icon.png',
5+
'panel.html'
6+
);

chrome-extension/icon.png

7.23 KB
Loading

chrome-extension/manifest.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "DI visualizer",
3+
"version": "0.0.1",
4+
"description": "",
5+
"background": {
6+
"page": "background.html"
7+
},
8+
"devtools_page": "devtools_background.html",
9+
"manifest_version": 2,
10+
"permissions": [
11+
"tabs",
12+
"<all_urls>"
13+
]
14+
}

chrome-extension/panel.html

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<!doctype html>
2+
<meta charset="utf-8">
3+
<link rel="stylesheet" href="visualize/injectors/style.css">
4+
<title>Visualization of injectors</title>
5+
6+
<body ng-app="di-visualiser" ng-controller="Main" ng-cloak>
7+
8+
<span ng-show="message">{{message}}</span>
9+
10+
<div class="control-panel">
11+
<ul class="providers" ng-show="providers.length">
12+
<li ng-repeat="provider in providers" ng-class="{highlighted: provider.highlighted}" on-toggle="highlight(provider, toggled)">
13+
{{provider.name}}
14+
</li>
15+
</ul>
16+
<label><input type="checkbox" ng-model="showAllDependencies"> show all deps</label>
17+
</div>
18+
19+
20+
<graph width="800" height="800"></graph>
21+
22+
<!-- CDN
23+
<script src="http://d3js.org/d3.v3.min.js"></script>
24+
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
25+
-->
26+
27+
<script src="visualize/lib/d3.v3.js"></script>
28+
<script src="visualize/lib/angular.js"></script>
29+
30+
<script src="visualize/injectors/app.js"></script>
31+
<script src="panel.js"></script>
32+
33+
</body>
34+
35+
36+
</body>
37+
</html>

chrome-extension/panel.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
function evalInInspectedWindow(fn, args, cb) {
2+
var code = '(' + fn.toString() + ')(window, ' + JSON.stringify(args) + ')';
3+
chrome.devtools.inspectedWindow.eval(code, cb);
4+
}
5+
6+
app.factory('data', function($q) {
7+
var d = $q.defer();
8+
9+
evalInInspectedWindow(function(window) {
10+
var injectors = window.__di_dump__.injectors;
11+
var tokens = Object.create(null);
12+
13+
// Serialize the map so that we can pass it back to the console panel.
14+
window.__di_dump__.tokens.forEach(function(id, token) {
15+
tokens[id] = token.name;
16+
});
17+
18+
return {
19+
injectors: injectors,
20+
tokens: tokens
21+
};
22+
}, [], function(dump) {
23+
d.resolve(dump);
24+
});
25+
26+
d.promise.success = d.promise.then;
27+
return d.promise;
28+
});

chrome-extension/visualize

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../visualize

visualize/injectors/app.js

+57-23
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,11 @@ app.controller('Main', function($scope, data) {
330330
var links = [];
331331

332332
data.success(function(data) {
333+
if (!data) {
334+
$scope.message = 'Enable DI profiling by appending ?di_debug into the url.';
335+
return;
336+
}
337+
333338
var injectors = data.injectors;
334339
var injectorsMap = {};
335340
var rootInjectors = [];
@@ -354,26 +359,26 @@ app.controller('Main', function($scope, data) {
354359
}
355360

356361
// Process all providers defined in this injector.
357-
Object.keys(injector.providers).forEach(function(name) {
358-
var provider = injector.providers[name];
362+
Object.keys(injector.providers).forEach(function(id) {
363+
var provider = injector.providers[id];
359364

360-
providersMap[name] = providersMap[name] || [];
361-
providersMap[name].push(provider);
365+
providersMap[id] = providersMap[id] || [];
366+
providersMap[id].push(provider);
362367

363368
// Compute override links.
364-
if (parent && parent.providers[name]) {
365-
links.push({source: parent.providers[name], target: provider, type: 'override'});
369+
if (parent && parent.providers[id]) {
370+
links.push({source: parent.providers[id], target: provider, type: 'override'});
366371
}
367372

368373
// Compute dependency links.
369374
provider.dependencies.forEach(function(dep) {
370-
if (injector.providers[dep]) {
371-
links.push({source: provider, target: injector.providers[dep], type: 'dependency'});
375+
if (injector.providers[dep.token]) {
376+
links.push({source: provider, target: injector.providers[dep.token], type: 'dependency', isPromise: dep.isPromise, isLazy: dep.isLazy});
372377
} else {
373378
var pivot = parent;
374379
while (pivot) {
375-
if (pivot.providers[dep]) {
376-
links.push({source: provider, target: pivot.providers[dep], type: 'dependency'});
380+
if (pivot.providers[dep.token]) {
381+
links.push({source: provider, target: pivot.providers[dep.token], type: 'dependency', isPromise: dep.isPromise, isLazy: dep.isLazy});
377382
break;
378383
} else {
379384
pivot = pivot.parent_id && injectorsMap[pivot.parent_id] || null;
@@ -388,48 +393,54 @@ app.controller('Main', function($scope, data) {
388393
});
389394
});
390395

391-
$scope.providers = Object.keys(providersMap).map(function(name) {
396+
$scope.providers = Object.keys(providersMap).map(function(id) {
392397
return {
393-
name: name,
398+
id: id,
399+
name: providersMap[id][0].name,
394400
highlighted: false
395401
};
396402
});
397403

398-
$scope.$broadcast('graph_data_changed', rootInjectors[0], links);
404+
var fakeRoot = rootInjectors.length > 1 ? {
405+
type: 'fake-root',
406+
children: rootInjectors
407+
} : rootInjectors;
408+
409+
$scope.$broadcast('graph_data_changed', fakeRoot, links);
399410
});
400411

401-
var highlightProviders = function(name, highlighted) {
412+
var highlightProviders = function(id, highlighted) {
402413
// Highlight the provider name in the list.
403414
$scope.providers.forEach(function(provider) {
404-
if (provider.name === name) {
415+
if (provider.id === id) {
405416
provider.highlighted = highlighted;
406417
}
407418
});
408419

409420
// Highlight all the circles in the graph.
410-
providersMap[name].forEach(function(p) {
421+
providersMap[id].forEach(function(p) {
411422
p.highlighted = highlighted;
412423
});
413424

414425
// Highlight all the "override" links in the graph.
415426
links.forEach(function(link) {
416-
if (link.type === 'override' && link.source.name === name) {
427+
if (link.type === 'override' && link.source.id === id) {
417428
link.highlighted = highlighted;
418429
}
419430
});
420431

421432
$scope.$broadcast('graph_data_changed');
422433
};
423434

424-
var highlightAllProvidersByName = function(name, highlighted) {
425-
providersMap[name].forEach(function(p) {
435+
var highlightAllProvidersById = function(id, highlighted) {
436+
providersMap[id].forEach(function(p) {
426437
p.highlighted = highlighted;
427438
});
428439
};
429440

430-
var highlightOverrideLinksForProviderByName = function(name, highlighted) {
441+
var highlightOverrideLinksForProviderById = function(id, highlighted) {
431442
links.forEach(function(link) {
432-
if (link.type === 'override' && link.source.name === name) {
443+
if (link.type === 'override' && link.source.id === id) {
433444
link.highlighted = highlighted;
434445
}
435446
});
@@ -454,8 +465,8 @@ app.controller('Main', function($scope, data) {
454465
$scope.highlight = function(provider, highlighted) {
455466
provider.highlighted = highlighted;
456467

457-
highlightAllProvidersByName(provider.name, highlighted);
458-
highlightOverrideLinksForProviderByName(provider.name, highlighted);
468+
highlightAllProvidersById(provider.id, highlighted);
469+
highlightOverrideLinksForProviderById(provider.id, highlighted);
459470

460471
$scope.$broadcast('graph_data_changed');
461472
};
@@ -491,6 +502,29 @@ app.controller('Main', function($scope, data) {
491502

492503
$scope.$on('graph_click', function(_, d) {
493504
console.log(d)
505+
if (d.type === 'provider') {
506+
evalInInspectedWindow(function(window, args) {
507+
var tokenId = args[0];
508+
var injectorId = args[1];
509+
var injector;
510+
var token;
511+
512+
window.__di_dump__.tokens.forEach(function(id, instance) {
513+
if (id === tokenId) token = instance;
514+
if (id === injectorId) injector = instance;
515+
})
516+
window.console.log(injector.get(token));
517+
}, [d.id, d.parent.id], function() {});
518+
} else if (d.type === 'injector') {
519+
evalInInspectedWindow(function(window, args) {
520+
var injectorId = args[0];
521+
var injector;
522+
window.__di_dump__.tokens.forEach(function(id, instance) {
523+
if (id === injectorId) injector = instance;
524+
})
525+
window.console.log(injector);
526+
}, [d.id], function() {});
527+
}
494528
});
495529
});
496530

visualize/injectors/index.html

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
<body ng-app="di-visualiser" ng-controller="Main" ng-cloak>
77

8+
<span class="message">{{message}}</span>
9+
810
<div class="control-panel">
911
<ul class="providers" ng-show="providers.length">
1012
<li ng-repeat="provider in providers" ng-class="{highlighted: provider.highlighted}" on-toggle="highlight(provider, toggled)">

visualize/injectors/style.css

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ label {
1717
cursor: pointer;
1818
}
1919

20+
.fake-root {
21+
stroke: 0;
22+
fill: none;
23+
}
24+
2025
.injector circle {
2126
fill: #0a629f;
2227
fill-opacity: .2;

0 commit comments

Comments
 (0)