Skip to content

Commit 67e5f4f

Browse files
committed
Merge branch 'master' of github.com:bahmutov/code-snippets
2 parents 101387a + 1406bb7 commit 67e5f4f

9 files changed

+185
-64
lines changed

.npmrc

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
registry=http://registry.npmjs.org/

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
language: node_js
2+
sudo: false
23
node_js:
34
- "0.12"
45
branches:

README.md

+22-12
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,26 @@ Read [Code Snippets tutorial][1],
2626
[Performance profiling using DevTools code snippets][2] and
2727
[How to improve Angular application performance using code snippets][3].
2828

29-
Note: code snippets do NOT have access to the full console API, for example no access to
29+
Note: code snippets do NOT have access to the full console API, for example no access to
3030
`console.monitor`.
3131

3232
## Snippets
3333

34+
### Security
35+
36+
* [test-script-injection.js](test-script-injection.js) - tries to create a new
37+
inline script tag to test if page allows it.
38+
3439
### DOM and CPU generic performance
3540

36-
* [boilerplate.js](boilerplate.js) - boilerplate for loading and running a remote code script
41+
* [boilerplate.js](boilerplate.js) - boilerplate for loading and running a remote code script
3742
(see [remote download](#remote-download)).
3843
* [first-paint.js](first-paint.js) - time from page reload to first visible contents.
39-
* [timing.js](timing.js) - Detailed page timing information,
44+
* [timing.js](timing.js) - Detailed page timing information,
4045
from [addyosmani/timing.js](https://github.com/addyosmani/timing.js).
4146
* [time-method-call.js](time-method-call.js) - measures single method call time.
4247
* [profile-method-call.js](profile-method-call.js) - profiles a single method call.
43-
* [profile-prototype-method.js](profile-prototype-method.js) - profiles a single method call
48+
* [profile-prototype-method.js](profile-prototype-method.js) - profiles a single method call
4449
that is on a prototype object, not on an instance.
4550
* [profile-separate-calls.js](profile-separate-calls.js) can profile actions where separate
4651
method calls start and stop the operation.
@@ -54,9 +59,9 @@ take up in a collection of objects, read [Measuring Space Allocation][measure].
5459

5560
### Angular performance
5661

57-
* [ng-count-watchers.js](ng-count-watchers.js) - counts total watchers in the page.
62+
* [ng-count-watchers.js](ng-count-watchers.js) - counts total watchers in the page.
5863
More watchers - slower digest cycle.
59-
* [ng-idle-apply-timing.js](ng-idle-apply-timing.js) - measures how long a digest cycle takes without
64+
* [ng-idle-apply-timing.js](ng-idle-apply-timing.js) - measures how long a digest cycle takes without
6065
any data changes. This measures purely how long all watched expressions take to compute and compare
6166
to previous values (dirty checking).
6267
* [ng-profile-scope-method.js](ng-profile-scope-method.js) - installs profile calls around a given
@@ -82,23 +87,28 @@ the digest cycle runs.
8287
* [ng-throw-error.js](ng-throw-error.js) throws an error from the digest cycle; useful for checking
8388
if your [exception handler](http://glebbahmutov.com/blog/catch-all-errors-in-angular-app/) is working.
8489

90+
## Misc snippets
91+
92+
* [github-pull-request-template.js](github-pull-request-template.js) - better GitHub pull request
93+
text, based on the blog post [Enforce standards while submitting a pull request](http://krasimirtsonev.com/blog/article/enforce-standards-while-submitting-a-pull-request) by [Krasimir Tsonev](https://github.com/krasimir).
94+
8595
All snippets, including mine are distributed under MIT license.
8696

8797
## Updating local code snippets
8898

8999
You can update local code snippets by downloading new versions from this github repository.
90-
Create a code snippets and copy source from [update-code-snippets.js](update-code-snippets.js).
100+
Create a new code snippet and copy the source from [update-code-snippets.js](update-code-snippets.js).
91101

92102
You will run this code snippet in an unusual way. First, open any web page, even an empty tab.
93-
Open the DevTools in **undocked** mode (Command+Option+I on Mac). Then open the DevTools **again**,
103+
Open the DevTools in **undocked** mode (Command+Option+I on Mac). Then open the DevTools **again**,
94104
*while focused* on the first DevTools. This will open the second DevTools instance with the source for the
95105
first DevTools panels. If you inspect the `localStorage` variable in the second DevTools window, you will
96106
find lots of interesting stuff, including all the code snippets in the `localStorage.scriptSnippets` property.
97107

98108
Whenever you want to update the your local code snippets in the Chrome DevTools, execute the `update-code-snippets.js`
99-
snippet in the second DevTools instance. The update script looks at the your current code snippets and
100-
tries to download a file with same name from the code snippets github repository (via [RawGit][RawGit]).
101-
If the remote file has been downloaded successfully, it will replace the snippet.
109+
snippet in the second DevTools instance. The update script looks at the your current code snippets and
110+
tries to download a file with same name from the code snippets github repository (via [RawGit][RawGit]).
111+
If the remote file has been downloaded successfully, it will replace the snippet.
102112
After all snippets are checked, reopen the DevTools to load the updated source code.
103113

104114
![update code snippets](images/update-code-snippets.png)
@@ -109,7 +119,7 @@ want to override a code snippet - just rename it, for example, remove the `.js`
109119

110120
## Remote download a single script
111121

112-
You can download and run a single snippet by using the following boilerplate
122+
You can download and run a single snippet by using the following boilerplate
113123
(scripts are via downloaded via [RawGit][RawGit])
114124

115125
```js

bower.json

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "code-snippets",
33
"main": "first-paint.js",
4-
"version": "0.5.0",
4+
"version": "0.6.0",
55
"homepage": "https://github.com/bahmutov/code-snippets",
66
"license": "MIT",
77
"ignore": [
@@ -16,14 +16,14 @@
1616
"index.html"
1717
],
1818
"keywords": [
19-
"testing",
20-
"test",
21-
"exploratory",
22-
"mock",
2319
"chrome",
24-
"devtools",
2520
"code",
26-
"snippets"
21+
"devtools",
22+
"exploratory",
23+
"mock",
24+
"snippets",
25+
"test",
26+
"testing"
2727
],
2828
"description": "Chrome DevTools code snippets ",
2929
"authors": [

github-pull-request-template.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Read the following blog post
3+
http://krasimirtsonev.com/blog/article/enforce-standards-while-submitting-a-pull-request
4+
*/
5+
(function () {
6+
var textareaId = '#pull_request_body';
7+
var textarea = document.querySelector(textareaId);
8+
var template = '';
9+
var firstLine;
10+
11+
template += firstLine = 'ID (ticket/card/issue): ';
12+
template += '\n\n';
13+
template += '## Task/Problem\n\n';
14+
template += '## Solution\n\n';
15+
template += '## Steps to reproduce\n\n';
16+
template += '## UAT\n\n';
17+
template += '## Code review\n\n\n';
18+
template += '- [ ] Unit tests passed\n';
19+
template += '- [ ] System tests passed\n';
20+
21+
if (textarea) {
22+
textarea.value = template;
23+
textarea.focus();
24+
textarea.scrollTop = 0;
25+
textarea.selectionStart = textarea.selectionEnd = firstLine.length;
26+
} else {
27+
/* global alert */
28+
/* eslint no-alert:0 */
29+
alert('You are either not on the PR page or there is no ' + textareaId + ' element.');
30+
}
31+
})();

ng-count-watchers.js

+51-13
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,73 @@
11
// taken from http://ng.malsup.com/#!/counting-watchers
2-
(function countAngularWatchers(angular) {
2+
/*
3+
Usage
4+
- just run the script and it will compute number of watchers on the page
5+
- select an element on the page using "Elements" tab
6+
and run `countAngularWatchers(angular, $0)` to count total watchers
7+
in the tree rooted at the selected element. Useful to find where the
8+
large numbers of watchers are "hiding"
9+
*/
10+
(function countAngularWatchers(angular, start) {
11+
window.countAngularWatchers = countAngularWatchers;
12+
13+
function allDescendents(list, node) {
14+
list.push(node);
15+
Array.prototype.forEach.call(node.childNodes, function (child) {
16+
allDescendents(list, child);
17+
});
18+
}
19+
320
var i, data, scope,
4-
count = 0,
5-
all = document.all,
6-
len = all.length,
7-
test = {};
21+
count = 0,
22+
all = document.all,
23+
test = {},
24+
watchers = [];
25+
26+
if (start) {
27+
all = [];
28+
allDescendents(all, start);
29+
}
30+
console.log('counting watchers in', all.length, 'elements');
31+
var len = all.length;
832

933
var mostWatchers = 0;
34+
var maxWatchersToPrint = 20;
1035

1136
function countScopeWatchers(scope, element) {
1237
test[scope.$id] = true;
1338
var n = scope.$$watchers.length;
1439
count += n;
40+
if (n > 0){
41+
watchers.push.apply(watchers, scope.$$watchers);
42+
}
1543
if (n > mostWatchers) {
1644
console.log('most watchers', n);
1745
console.log(element);
1846
mostWatchers = n;
47+
1948
}
2049
}
2150

22-
// go through each element. Count watchers if it has scope or isolate scope
23-
for (i = 0; i < len; i += 1) {
24-
var el = angular.element(all[i]);
51+
function countWatchersInData(el) {
2552
data = el.data();
26-
scope = data.$scope || data.$isolateScope;
27-
if (scope && scope.$$watchers) {
28-
if ( !test[ scope.$id ] ) {
29-
countScopeWatchers(scope, el);
53+
if (data) {
54+
scope = data.$scope || data.$isolateScope;
55+
if (scope && scope.$$watchers) {
56+
if (!test[scope.$id]) {
57+
countScopeWatchers(scope, el);
58+
}
3059
}
3160
}
3261
}
33-
console.log('this page has', count, 'angular watchers');
62+
63+
// go through each element. Count watchers if it has scope or isolate scope
64+
for (i = 0; i < len; i += 1) {
65+
var el = angular.element(all[i]);
66+
countWatchersInData(el);
67+
}
68+
console.log('this page has ' + watchers.length + ' angular watchers');
69+
if (watchers.length < maxWatchersToPrint) {
70+
console.log('the watchers are:', watchers);
71+
}
3472
return count;
3573
}(window.angular));

ng-idle-apply-timing.js

+16-10
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@
55

66
// assumes the angular application is at least around the document's body
77

8-
/* global angular, performance */
9-
angular.element(document.body).injector().invoke(function timeApply($rootScope) {
10-
console.profile('$apply');
11-
var started = performance.now();
12-
$rootScope.$apply();
13-
var takes = performance.now() - started;
14-
console.log('idle $apply takes', takes, 'ms');
15-
console.profileEnd();
16-
return takes;
17-
});
8+
/* global performance */
9+
(function profileIdleTiming(angular) {
10+
11+
function timeApply($rootScope) {
12+
console.profile('$apply');
13+
var started = performance.now();
14+
$rootScope.$apply();
15+
var takes = performance.now() - started;
16+
console.log('idle $apply takes', takes, 'ms');
17+
console.profileEnd();
18+
return takes;
19+
}
20+
timeApply.$inject = ['$rootScope'];
21+
22+
angular.element(document.body).injector().invoke(timeApply);
23+
}(window.angular));

package.json

+40-22
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,72 @@
11
{
22
"name": "code-snippets",
33
"description": "Chrome DevTools code snippets ",
4-
"version": "0.5.0",
4+
"version": "0.6.0",
55
"author": "Gleb Bahmutov <[email protected]>",
66
"bugs": {
77
"url": "https://github.com/bahmutov/code-snippets/issues"
88
},
9+
"config": {
10+
"pre-git": {
11+
"commit-msg": "simple",
12+
"pre-commit": [
13+
"npm test"
14+
],
15+
"pre-push": [
16+
"npm run size"
17+
],
18+
"post-commit": [],
19+
"post-merge": []
20+
}
21+
},
922
"contributors": [],
1023
"dependencies": {},
1124
"devDependencies": {
12-
"eslint-rules": "0.3.0",
25+
"eslint-rules": "0.4.3",
26+
"git-issues": "1.2.0",
1327
"grunt": "0.4.5",
1428
"grunt-cli": "0.1.13",
15-
"grunt-contrib-jshint": "0.11.0",
16-
"grunt-deps-ok": "0.5.2",
29+
"grunt-contrib-jshint": "0.11.3",
30+
"grunt-deps-ok": "0.8.0",
1731
"grunt-eslint": "2.1.0",
18-
"grunt-gh-pages": "0.9.1",
32+
"grunt-gh-pages": "1.0.0",
1933
"grunt-jscs": "1.2.0",
20-
"grunt-nice-package": "0.9.2",
21-
"grunt-npm2bower-sync": "0.8.1",
34+
"grunt-nice-package": "0.9.6",
35+
"grunt-npm2bower-sync": "0.9.1",
2236
"jshint-summary": "0.4.0",
23-
"matchdep": "0.3.0",
24-
"pre-git": "0.1.1"
37+
"matchdep": "1.0.0",
38+
"pre-git": "3.1.2"
2539
},
2640
"engines": {
2741
"node": "> 0.10.*"
2842
},
43+
"files": [
44+
"*.js",
45+
"!Gruntfile.js"
46+
],
2947
"homepage": "https://github.com/bahmutov/code-snippets",
3048
"keywords": [
31-
"testing",
32-
"test",
33-
"exploratory",
34-
"mock",
3549
"chrome",
36-
"devtools",
3750
"code",
38-
"snippets"
51+
"devtools",
52+
"exploratory",
53+
"mock",
54+
"snippets",
55+
"test",
56+
"testing"
3957
],
4058
"license": "MIT",
4159
"main": "first-paint.js",
42-
"pre-commit": [
43-
"npm test",
44-
"npm version"
45-
],
4660
"repository": {
4761
"type": "git",
4862
"url": "[email protected]:bahmutov/code-snippets.git"
4963
},
5064
"scripts": {
51-
"test": "grunt",
52-
"grunt": "grunt"
65+
"build": "grunt",
66+
"commit": "git-issues && commit-wizard",
67+
"grunt": "grunt",
68+
"issues": "git-issues",
69+
"size": "t=\"$(npm pack .)\"; wc -c \"${t}\"; tar tvf \"${t}\"; rm \"${t}\";",
70+
"test": "grunt"
5371
}
54-
}
72+
}

test-script-injection.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
This code snippet checks if the page allows creating
3+
and executing new inline scripts (script-injection attacks)
4+
See https://github.com/bahmutov/disable-inline-javascript-tutorial
5+
*/
6+
(function testInlineScriptInjection() {
7+
var el = document.createElement('script');
8+
el.innerText = 'alert("hi there")';
9+
document.body.appendChild(el); // runs the code by default
10+
}());
11+
12+
(function testExternalScriptInjection() {
13+
var el = document.createElement('script');
14+
el.src = 'https://rawgit.com/hakimel/reveal.js/tree/master/js';
15+
document.body.appendChild(el);
16+
}());

0 commit comments

Comments
 (0)