Compare commits
5605 Commits
starting
...
4.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
992647dc43 | |||
bbc4e8ab5f | |||
0a724208b9 | |||
1200cf25f4 | |||
635bf02b02 | |||
2d7b3a86cc | |||
523fd84d22 | |||
e8ea741039 | |||
1a92e3d406 | |||
be6c95ad03 | |||
f816319e41 | |||
5047d9780d | |||
b1e3dda5cb | |||
d169c2434e | |||
6d1f1a43bb | |||
e19bf70b47 | |||
a6f8e9fc90 | |||
d6382bfa0b | |||
4dea347101 | |||
5237b1c98c | |||
f364557629 | |||
c2aa981dd6 | |||
dc63cef10a | |||
2c294d5dff | |||
e1af25d93e | |||
123943a6e0 | |||
3a4b54daa4 | |||
95cbca20a5 | |||
aeed7373af | |||
2e3ac70e0a | |||
9aeb8c5357 | |||
424e6c4cb9 | |||
5cb2008e6c | |||
78f42c7aa1 | |||
d4d3782d45 | |||
46cb04d575 | |||
8c7e93bebe | |||
5d9cbd7d6f | |||
d061adc02d | |||
6d29faefea | |||
99aa49ab6c | |||
e5c6bb4286 | |||
d9a22dae4f | |||
fb6c4582a1 | |||
8578682dcf | |||
c0178de0e2 | |||
31322e73b7 | |||
9211a22039 | |||
3f67ab074a | |||
4bae4b3bb5 | |||
02dd90faed | |||
1c85e99588 | |||
ccb65893bf | |||
3e90ffd293 | |||
8063b0d9a2 | |||
21030e9a1c | |||
889b48d85f | |||
1bd04e95de | |||
f88cd2f22e | |||
f822f9599c | |||
9898d8f6d9 | |||
2dd6280ab8 | |||
35f9a1c2cb | |||
465516b905 | |||
db49d422f2 | |||
8ed92d75b0 | |||
50e5cb15dd | |||
c5c53f3666 | |||
bb0d23f82b | |||
1e6440e81b | |||
6b02b80a03 | |||
2c0c86e3ce | |||
5b4bea24de | |||
7690d02133 | |||
b2ae7b607e | |||
7c210645a3 | |||
07e0fce8fc | |||
0ac8e102de | |||
e74d8aaf92 | |||
881eb894bc | |||
0eca960494 | |||
eed83443b8 | |||
e5c4e5801f | |||
69fa3bbc03 | |||
445ed43b9a | |||
174334dec3 | |||
9c697030e6 | |||
697690349f | |||
0448e80704 | |||
e85232afd2 | |||
e7ece6c8ce | |||
67380d4b28 | |||
f114e40212 | |||
952471e25d | |||
c65e428778 | |||
842f52e841 | |||
eb2ceff4ba | |||
f49ab56160 | |||
c0f750af4e | |||
bcd37f52fb | |||
e69c1fb36c | |||
9da4c259a5 | |||
fcd116fdc0 | |||
383adc9ad9 | |||
9b8488f007 | |||
1817ddb57b | |||
1ee574c51e | |||
171a9bdc85 | |||
896916af29 | |||
e49c7fae22 | |||
6b65fc1286 | |||
0e3981afc1 | |||
e78508507d | |||
a23fa94ca8 | |||
4568d5ddac | |||
c6e893953f | |||
55dfa1b69d | |||
0fe3cd9a4c | |||
0c19898694 | |||
5b6e8ea3ec | |||
732f446ad2 | |||
f0e092515c | |||
14e785f5b7 | |||
01d1624884 | |||
33910ddfc9 | |||
01ca2db6ae | |||
6cefccb314 | |||
fa9e21e83c | |||
b6078f5887 | |||
c65b4fa9dc | |||
169ed82900 | |||
fd8e15b15d | |||
aa40366a92 | |||
40d8d9c3e3 | |||
ee2ac025ef | |||
aa3769ba69 | |||
d4ddb6004e | |||
84400bcc86 | |||
42d9998cbb | |||
c18d2fe5e3 | |||
d91a86aac6 | |||
d6e5e9283c | |||
eab7e490c9 | |||
3e90605db9 | |||
79671a6f12 | |||
a659259962 | |||
b56474d067 | |||
8395f0e138 | |||
dd0519abad | |||
f238c8ac7a | |||
8c27c62fab | |||
5031adc7a3 | |||
821b8f09d6 | |||
2bf1bbc071 | |||
7b0a86718c | |||
3edca4d37e | |||
a0a05041ac | |||
7256d0ede5 | |||
d62d89319e | |||
f5f1d5f65c | |||
a8d237581d | |||
d036165a19 | |||
d17e690eb4 | |||
714f2af0dd | |||
2b90cd532f | |||
3a64ad895a | |||
9ec0a4e105 | |||
4b3d135193 | |||
1d0ed6f75f | |||
6f330a5fc9 | |||
e23076f767 | |||
7295a5e7f2 | |||
20bed46737 | |||
2a5012d515 | |||
fb38fba8f9 | |||
4c35be3e07 | |||
e9f307f948 | |||
2e500cc85b | |||
56dce0e26d | |||
8a8c53250e | |||
08ff2e5249 | |||
a006c1418a | |||
90c223591f | |||
aaf6e05f56 | |||
3bee521aa4 | |||
95f48292b1 | |||
04cfa1ebdf | |||
4022173d1e | |||
c8baf51f4f | |||
b4db73d0bf | |||
e15a3f273f | |||
213c713409 | |||
9a8423da36 | |||
f0b0762f4a | |||
b5c4bf1c59 | |||
56c361ff6a | |||
562f7a2f8b | |||
6dd5201765 | |||
72361fb68f | |||
5c6ec20c7e | |||
440ef02f29 | |||
4e3d58a792 | |||
61d7c1e0b3 | |||
bf93389615 | |||
4398056146 | |||
1b547886d0 | |||
9591a08dfb | |||
65965c27a8 | |||
13b41bd631 | |||
f3524af68f | |||
0a56f4ea82 | |||
cf52284ac3 | |||
4a09c81724 | |||
16efb13dd1 | |||
986abbe0b2 | |||
25c2141991 | |||
2893c2c0a2 | |||
393c1007a8 | |||
66b6fc010d | |||
f31c9470fa | |||
4bd8f58552 | |||
93556a5720 | |||
5614c4ff0f | |||
c3065aac7a | |||
c767df0e4e | |||
25e5b2fdf0 | |||
307c4693dc | |||
349ad75de3 | |||
f562cbf86c | |||
804943c9b1 | |||
dea59165de | |||
a1322873c8 | |||
b8c839bd51 | |||
d2e5198b93 | |||
6cf7a1bf84 | |||
d46b8deeea | |||
bbb7a39414 | |||
d7d8fab211 | |||
51b06924bd | |||
aa4bd14b3f | |||
3ff6554cbc | |||
dfd8140084 | |||
6ea3ab7e14 | |||
9761db5ac2 | |||
75d1617b63 | |||
614a35d539 | |||
9ab401f4d3 | |||
82c81cd0d2 | |||
12959f444c | |||
25a6da244c | |||
5908b66ae9 | |||
480ef20eb1 | |||
c066281bad | |||
1b9493f725 | |||
ae26504e84 | |||
d420080b3b | |||
2975d8933c | |||
43c0e9a6bb | |||
f275f36081 | |||
e628b66cca | |||
3e73bea3e7 | |||
42cf06fa12 | |||
c4bbafc291 | |||
2d6a003dba | |||
e45b7ffcd9 | |||
627282d2c8 | |||
2f7492c986 | |||
2452cd14e0 | |||
bc69c74be0 | |||
897555ca78 | |||
966bcbad5a | |||
94b8612e4e | |||
b2b72190f8 | |||
f5c8e0989d | |||
4a09251921 | |||
36caaaa8e4 | |||
808275a9d5 | |||
be3784c957 | |||
555301ce3a | |||
7194fc2b9e | |||
2a3ca7bfcf | |||
4cbf8ccf05 | |||
a6c4490fce | |||
2c02d34c05 | |||
6c2d931744 | |||
86ffa884b7 | |||
3e548de99d | |||
909268036b | |||
519a324454 | |||
ef96763fa4 | |||
7dcca307d9 | |||
491d5a22a9 | |||
44572f114f | |||
1ef4696cb7 | |||
07a986d330 | |||
59d2b4c831 | |||
2a5bd2f345 | |||
3c06a5dc25 | |||
adeea5d86a | |||
dddbb1c1cb | |||
bccf0e69dc | |||
b15039d228 | |||
2235048432 | |||
484119e59f | |||
24099bdbd2 | |||
912ca44979 | |||
664a6273e1 | |||
c1a62e2154 | |||
aac37bedc0 | |||
a3884db87c | |||
fc5ac1ebc4 | |||
ad20d7d260 | |||
602522beb2 | |||
4e047302f2 | |||
419a812f04 | |||
f340e1a414 | |||
481c9b3258 | |||
8b2dfb2eca | |||
824ea8406c | |||
1f96a93f59 | |||
009d545787 | |||
53c25210a6 | |||
927aa69726 | |||
ce89039036 | |||
42198cd7d5 | |||
d6ba092a27 | |||
773b31de8f | |||
f79b320fc4 | |||
6a212fd561 | |||
be010a292a | |||
7c36e7f956 | |||
13ba2f90b9 | |||
75277cd94b | |||
46d150266b | |||
1b5384ee54 | |||
9f7d32a326 | |||
9de76ebfa5 | |||
46023e4792 | |||
b55aaf094f | |||
d90b622fa4 | |||
79e2bb9291 | |||
efbbefd353 | |||
c2fae72bc6 | |||
7908679c4b | |||
9ed9ff40b3 | |||
2f14415836 | |||
76e4911e8b | |||
ed5e98d0df | |||
146af1fed9 | |||
c60ba7a72f | |||
05beffe0d0 | |||
08c038ebd9 | |||
582550a90d | |||
1d53a870dd | |||
a0c58a6b5c | |||
d3eff6c483 | |||
2524d510bc | |||
8f5dd1f11e | |||
77ee27c59e | |||
73593d4bf3 | |||
a965d11cce | |||
52be848f94 | |||
69dfcf7385 | |||
785b7b640e | |||
e5a753e111 | |||
768cddbe62 | |||
92f244aa26 | |||
2a4bf9a0df | |||
45ddd6ba78 | |||
7886561997 | |||
752edca81b | |||
1bd858fb43 | |||
fcb4e66493 | |||
ef881475e9 | |||
458ca7112a | |||
2aba8b0ff2 | |||
77dc1ab675 | |||
3052fb234f | |||
79383ce150 | |||
c3c0e2e2a2 | |||
44a142fc02 | |||
3d9d839c6c | |||
69f87ca075 | |||
f224ca1461 | |||
19e869e7c9 | |||
7cab30f85d | |||
73407351e7 | |||
2c110931f8 | |||
2ced2a8a5a | |||
634b3bb88b | |||
4595a61aeb | |||
f80a157b65 | |||
6e35d13fbc | |||
fe35bc34f6 | |||
ad3bf6c54f | |||
a0e9fde653 | |||
3dc61779f0 | |||
09092ac3c2 | |||
778e6ad3b4 | |||
55dc0e4a5f | |||
4708b248d5 | |||
7694f974af | |||
acbf1d859c | |||
f3793b5953 | |||
22c021c57f | |||
d8f23f4b7f | |||
32fcec9fcb | |||
78039b41d6 | |||
89fd54e8e3 | |||
77cbf7f2bb | |||
383f23b578 | |||
2a3f4d7b17 | |||
ec92f4b198 | |||
121e5080aa | |||
fe1d0e29c5 | |||
469010ea8e | |||
f0cdb428f5 | |||
051d74802a | |||
f2bbef3e33 | |||
80d36b8db4 | |||
e3687706c7 | |||
648ce5981b | |||
9c23884da4 | |||
d708a8859c | |||
9ddf9b3d3d | |||
69f006cd89 | |||
4aaae3eada | |||
2e78b76fcf | |||
b2cf379d1c | |||
e25baa08b3 | |||
7103754178 | |||
1a069e8372 | |||
0fc11a43f1 | |||
0e3d655220 | |||
7c5cc9bc41 | |||
5f1dddc5d0 | |||
20a4f9923f | |||
e7c00be19d | |||
74ede9aa9b | |||
d1035da85c | |||
13533d2a30 | |||
953cb50fa5 | |||
3fffcf6645 | |||
d509ee078b | |||
8e221b826f | |||
830a780cb3 | |||
6fda97287e | |||
234c5599f1 | |||
f6710fefeb | |||
bda1909ede | |||
b3e3cd3add | |||
e5fdf4c70a | |||
97471d74b6 | |||
1de04b23b1 | |||
a178bc6c83 | |||
642c1db9ef | |||
579deeb9c5 | |||
bad58824a0 | |||
5494169fb4 | |||
5a3d7a62a2 | |||
a382d6dd20 | |||
52bf188b8f | |||
6f412bb449 | |||
e9fd8645ed | |||
a0aecac0e5 | |||
938ed1c76d | |||
eb8288f76c | |||
0936ceeab4 | |||
e0ad413a8e | |||
3045d02b9a | |||
e86573bac8 | |||
0a94845435 | |||
262bd23b84 | |||
7b8dae19af | |||
7c16ef942e | |||
a318b57257 | |||
fe47e6b783 | |||
091c390032 | |||
e391cacdf9 | |||
32feb8a532 | |||
a664aba2c9 | |||
d520fae70e | |||
fa93fd672e | |||
f4be2f907d | |||
2ea27a76d3 | |||
ec0acf9a1b | |||
a26dd28bdb | |||
7742ec00e7 | |||
2b5c983c13 | |||
ef153649b3 | |||
d321b0ebf5 | |||
b4265e0685 | |||
178fb79b5c | |||
5a7a58b1e0 | |||
f66ac821a2 | |||
fe299f4dfc | |||
4cac650675 | |||
cb7643ccea | |||
faa3478514 | |||
bc3f4bc816 | |||
c9f58cf78c | |||
6ccbfd41dd | |||
7d2554baa1 | |||
52a853e257 | |||
8f2fa0f766 | |||
fc60fa790c | |||
b74185369f | |||
7221632228 | |||
02f1222a8d | |||
c27ce7318f | |||
a838aba756 | |||
bfc97ff2cd | |||
57051f01ce | |||
e319cfefc3 | |||
444014ad96 | |||
867494a060 | |||
69ad99dca6 | |||
da5fc696bb | |||
b44b6ef8f5 | |||
0f21a5823b | |||
5ae6915600 | |||
8b9ab44eee | |||
b0a03fcab3 | |||
c951822c35 | |||
acda82c1ed | |||
a8815d6b08 | |||
d6791ff0e0 | |||
a2d35641e3 | |||
76dd026447 | |||
0ecd9b2df0 | |||
0e9503b500 | |||
f77ab6a2d2 | |||
97bc97153b | |||
445e5922ec | |||
b9fc090143 | |||
592f40aa9c | |||
24facdea2d | |||
aa2d3372a5 | |||
bf60418fdc | |||
cca4a5c519 | |||
6e5f8b59b3 | |||
8409b65153 | |||
38e2203b24 | |||
bd1dcb5f11 | |||
3993279527 | |||
bf1e2613b2 | |||
f7db0668d1 | |||
27d76776b8 | |||
8603d9c269 | |||
d55f747858 | |||
52de0fa558 | |||
d61ecf0663 | |||
5a9c5f28b8 | |||
15fc5dd7ee | |||
a5419608e0 | |||
5f95bf1dd2 | |||
33c8948fd3 | |||
606e51881a | |||
fdf4309b50 | |||
af996ef0c4 | |||
68d2dfdd2a | |||
07bd4b0630 | |||
df1718d624 | |||
17e3410d98 | |||
5effc330ed | |||
3df00828d7 | |||
8c477b2f45 | |||
7787771aba | |||
7275e1beb3 | |||
12ba62e5e2 | |||
e6e007e2f1 | |||
91dd138fa5 | |||
d972d82354 | |||
bdcf46f82e | |||
79e1c7b807 | |||
d22eeb70b8 | |||
aa92512ac6 | |||
f782b08f58 | |||
4202936bbf | |||
e1faca6386 | |||
f5b0e22d35 | |||
00693d70a2 | |||
bcef5efffe | |||
13ecc140e8 | |||
709a6dea06 | |||
16cfb88c00 | |||
efee6f5199 | |||
2aa8aae76d | |||
afb4bd9ef6 | |||
d641c36a45 | |||
f4566f8128 | |||
a67c06708d | |||
d9d57d71dd | |||
e06303a987 | |||
40b92ddf21 | |||
1681e4f57f | |||
71b7654660 | |||
eaaec6979c | |||
c587c63591 | |||
f50c1da4e2 | |||
0254ce1f6c | |||
c9b765f5c0 | |||
8c975ed156 | |||
bb35fcb562 | |||
57230b70a9 | |||
43dc60ce4f | |||
230b3b73d8 | |||
0b7dc2f9ff | |||
de1f44f51f | |||
f1cfddf6d6 | |||
ef621a2f00 | |||
df9761951b | |||
f786c560f1 | |||
c5557de3e7 | |||
ec3a5b54de | |||
cf269d9ff4 | |||
5fa5ffb82a | |||
4a57dcfd8d | |||
43923ffcf5 | |||
50c37d45dc | |||
a63359689f | |||
43d3a84df3 | |||
8310c91823 | |||
b64b5ece65 | |||
ed9c2b6281 | |||
1cf5f5fa38 | |||
a32078f85e | |||
decd129a4d | |||
c3c9ecb302 | |||
af520947aa | |||
040bf57966 | |||
65a60b7456 | |||
756ef09d12 | |||
9316f95467 | |||
83d94b7504 | |||
a121136fae | |||
a6bb84e02b | |||
3898dc488e | |||
ca3f9926f9 | |||
1c012a035f | |||
38c5304b7f | |||
9a049be67f | |||
2045c9e8ee | |||
6c4ec05a4a | |||
f7bfda31ff | |||
a92b573309 | |||
4fd13d71c8 | |||
bf7b82b658 | |||
c143fee849 | |||
0286956107 | |||
e884f4854d | |||
df1822fc2a | |||
42b4b6d21b | |||
36bc2ff269 | |||
1564042fe8 | |||
41c8c30973 | |||
61129fa12d | |||
3a5b4882bc | |||
425c1e6042 | |||
58605cf350 | |||
34b31dea7c | |||
a241ab7c07 | |||
745e10e6d2 | |||
33340dbbd1 | |||
52812c08e2 | |||
52f5ae1961 | |||
9be895b6da | |||
9f1c82537e | |||
5ab5cc77bb | |||
f1b6c6efa1 | |||
45ad13560b | |||
2045268cec | |||
fb1076b44a | |||
6fc46526ae | |||
3ef5ede6d6 | |||
136621ebc9 | |||
f23b22a0f4 | |||
0ca971c5bd | |||
3a6fcee0e6 | |||
8972137c29 | |||
cc6481077f | |||
c041b93418 | |||
bc33765913 | |||
31dce72b7b | |||
212f8dbde7 | |||
44da4984f9 | |||
d95344430c | |||
131626fc61 | |||
676bb0fa7d | |||
5a849829c4 | |||
671f73448c | |||
51d73d3e4e | |||
bf81b06a28 | |||
0621f07a2c | |||
1225ecfb14 | |||
5509453e72 | |||
70488ed382 | |||
03aedbe54b | |||
8395aab25d | |||
0dc15eb64a | |||
cba885a1fb | |||
fa4723a208 | |||
5bf08b886f | |||
89802316b9 | |||
2300c23332 | |||
fa39965a37 | |||
115f0fa842 | |||
734b8b8c13 | |||
54b41f57be | |||
df4254ae89 | |||
14ee75924b | |||
bd4045b6e7 | |||
255099aa61 | |||
1c24096650 | |||
32aeb1052d | |||
838d4bbf6c | |||
c4114c2f66 | |||
37b8691c8c | |||
93054d4e3d | |||
cfc12c6539 | |||
c0bdd89b5d | |||
d5515473bf | |||
ffe5c49c3e | |||
ae1dd5bfd0 | |||
cb657c4b55 | |||
42f60ca303 | |||
e33037a2f1 | |||
9cee8bcc83 | |||
003294d5df | |||
785292f44f | |||
15c2912527 | |||
096ae7c404 | |||
5972fdc817 | |||
2c42a50fc3 | |||
caa1cd2470 | |||
5fad37df69 | |||
727c2b38a4 | |||
b6287ccc51 | |||
69e8ace884 | |||
85d9db6bc4 | |||
0a2132ef10 | |||
d299ce4bcf | |||
0b9425bbb4 | |||
1a035a0dc7 | |||
84b4338ab5 | |||
b847257b16 | |||
c65d139081 | |||
57f0269491 | |||
4e6c41b3a1 | |||
7105021c41 | |||
f7313db0be | |||
1d2e70e3a4 | |||
21516c32e6 | |||
00a24b63da | |||
e71558ba89 | |||
7ac47acc1c | |||
60e49a7e4b | |||
c71e35cbf5 | |||
1348c65b0c | |||
ff03d87cdd | |||
a2bf334e6e | |||
f8690caa98 | |||
aa713d1dd9 | |||
a2519c6164 | |||
fa994810d5 | |||
c54580a4af | |||
730415e048 | |||
42a287fabf | |||
42d442dcd5 | |||
cc2873a94d | |||
63e15ffaec | |||
1b15170c89 | |||
26d1423ae9 | |||
61aad7925f | |||
79055f727b | |||
220d8377fe | |||
cc7780adf7 | |||
051a6ebe12 | |||
c9513b713a | |||
66e38b6754 | |||
7b82877ee5 | |||
c9ad5e46d6 | |||
2cdd051109 | |||
57cb82052b | |||
dd8204a655 | |||
cdda4082de | |||
0614c8c99d | |||
a343a8e1c2 | |||
a41c1bbdf4 | |||
f2c6157e74 | |||
32564ece27 | |||
3eee62fa71 | |||
617475005f | |||
0822066175 | |||
82f30e09f0 | |||
c649a5c5ab | |||
53f0c2206d | |||
0bce3907b8 | |||
2170379251 | |||
5a4e46db20 | |||
f5d44a42c9 | |||
673de004d2 | |||
f386cb4ba9 | |||
71e9cae1d0 | |||
df6762a170 | |||
d296298282 | |||
077e0be1e7 | |||
a52d076912 | |||
dae7cfc454 | |||
436af15d63 | |||
7b24028437 | |||
6a2bbffe10 | |||
f78e184822 | |||
78ad9adc1a | |||
9e2ec7a1aa | |||
643afa4b15 | |||
ed2ebeb52a | |||
567900e550 | |||
cc958c74ad | |||
62af613741 | |||
3ff816afa6 | |||
dd03bf12e1 | |||
645108f25b | |||
882efd125e | |||
d91e92c2f5 | |||
8858ebc4ab | |||
df4c0a3d1f | |||
b4363bc8af | |||
d26a827494 | |||
ea95c391c1 | |||
aa9b617c9d | |||
7192fec841 | |||
ee88c3c976 | |||
1ff0add29e | |||
5ee0f09b92 | |||
70b0ab457b | |||
c25d1f7ecc | |||
a45769a0a2 | |||
109dc99d32 | |||
2371d22d49 | |||
6f4b6edfea | |||
8c09933803 | |||
d309f7799c | |||
93deff6c33 | |||
c31535982c | |||
f5101782d9 | |||
5e5ae3cde6 | |||
53cf71430f | |||
04d02b55d1 | |||
043493cb62 | |||
2581c0851a | |||
27d72e87c3 | |||
eef4c22e87 | |||
4287f1716d | |||
ebc8e808a9 | |||
c9e5b599e4 | |||
e42a057048 | |||
0bb94df1da | |||
50e171c09b | |||
96697029c9 | |||
7c3b1367bc | |||
18be339ee9 | |||
ddda62b1f2 | |||
0ddae9b727 | |||
625b105d3a | |||
f9eb1f33f4 | |||
046c1a8a25 | |||
08e48c8f73 | |||
1b5e2b5129 | |||
562c8263dc | |||
99c0a7fae2 | |||
f4f6f4b4d8 | |||
cc89ef6c8c | |||
6ea5b05e7c | |||
f7b5478e9f | |||
873233e825 | |||
942104d9ac | |||
6dceaf209d | |||
2ab07d9418 | |||
1ef122988e | |||
db280fc67e | |||
ef0f29c372 | |||
1818056912 | |||
1df69cb4d2 | |||
2b20db6c5a | |||
174c016104 | |||
71ae2c4525 | |||
0f68351979 | |||
c74a438f0c | |||
c350ba29f6 | |||
6e40ef0f6d | |||
24e046fd6a | |||
979657989b | |||
8cb1046ce9 | |||
d53a898f46 | |||
f9f80003c8 | |||
d59ee3caaa | |||
b8ea71afb6 | |||
e2241a2f92 | |||
e8a1566065 | |||
d2ad871279 | |||
0b665c0ece | |||
875e66409c | |||
d7de5c4f8e | |||
51877ef4ed | |||
c377e80670 | |||
61002733bc | |||
5ff14de1f3 | |||
38069aba35 | |||
7dee1ee4cf | |||
af63378fa0 | |||
abad6673e6 | |||
75553200c0 | |||
6c77d7182a | |||
4a44832114 | |||
27539c8b80 | |||
e220a80093 | |||
3dd85cb7f1 | |||
511fe3d9f8 | |||
9ce8ef76bf | |||
7c07bfff97 | |||
86ba072758 | |||
fc1e45db92 | |||
a2deafc50f | |||
2fc5c57b31 | |||
93f323cfa2 | |||
bb9dfbc578 | |||
0bb516fae2 | |||
2ffecc0e14 | |||
b9647b7347 | |||
f25c97671a | |||
0a053a4cd5 | |||
4d7d2a2daa | |||
0cf5ece7f8 | |||
66df335998 | |||
fc2fe00d16 | |||
811962b2bb | |||
b867764b0d | |||
ce08982f78 | |||
cbe0976426 | |||
515ff61fcb | |||
d7c82f5c0f | |||
566d4361e2 | |||
ea2e5521e8 | |||
eb7d8c702c | |||
5d294624fa | |||
3aaf064d11 | |||
f38a700e35 | |||
501b83441d | |||
c03e25a7b7 | |||
1f5a5895e5 | |||
8a2324f86a | |||
6335b31702 | |||
6ef7a76e39 | |||
cc79dcac7f | |||
dc6f72e963 | |||
2b313e4979 | |||
4f8f8cfc66 | |||
8b782818f5 | |||
bd510ccdbb | |||
f1ce7607a6 | |||
7dfcaac730 | |||
c7a874dd2f | |||
aa5c8ca61f | |||
5c93a8800a | |||
05bbb8efcf | |||
14a30f3ca0 | |||
5ddecb18a7 | |||
c02325dd06 | |||
4a740f23a4 | |||
a782232ca3 | |||
a29f9f3ab8 | |||
3c2b2ff332 | |||
939d318242 | |||
39a2c39cef | |||
45e8e73670 | |||
ca41b4f5ff | |||
3c561475c8 | |||
23a27776e2 | |||
01111b04ff | |||
8560e1e4bf | |||
e0fbca9fb0 | |||
a7b76826a0 | |||
ece7985b8a | |||
9883e19e2e | |||
c631cfc2fd | |||
53c99cfc95 | |||
c56f3f2246 | |||
cc0e3d2296 | |||
917d43e108 | |||
bb7d55244d | |||
8a5eb08672 | |||
477e425f57 | |||
654ff6115a | |||
628d06c17c | |||
91980382e8 | |||
2f41b5c8a0 | |||
cd8cbd3762 | |||
292ccf882a | |||
a0e13b9797 | |||
a5c0349d88 | |||
c48021ab97 | |||
beb79e75bf | |||
0b62b6f783 | |||
895c542a20 | |||
c4fd862e15 | |||
6f18bd18bb | |||
00e157dc3b | |||
4be863c223 | |||
3009be8d6e | |||
4829fbb95c | |||
40e160c22c | |||
951ecb4d90 | |||
9318033294 | |||
4648b3e5de | |||
740e80492d | |||
cc22b051e3 | |||
75405ae0f5 | |||
f12d51992d | |||
6fd5bc075d | |||
675e582ffd | |||
0a22e8eefd | |||
44a4814766 | |||
3c23238129 | |||
916ed55d82 | |||
2451eb9ded | |||
ed639784d4 | |||
b77a3794b8 | |||
73a9ee4a05 | |||
9adf80385b | |||
a86c554a8e | |||
62078eee45 | |||
24e280a21a | |||
f7ff6c5a12 | |||
f6a7d6504c | |||
96bf42261b | |||
72bb38f83b | |||
4c9900dc3a | |||
6b26102931 | |||
bec5c5fdad | |||
04c11bb749 | |||
3f5331be9d | |||
48751cceae | |||
4a9745ef78 | |||
acc0fe6cf9 | |||
b238414984 | |||
231ed69507 | |||
60b10134df | |||
73c0a9daaf | |||
398bbb6aa9 | |||
05d1312306 | |||
bc6d1c87a6 | |||
712c7d5c3b | |||
e9479b30e8 | |||
7f6685e451 | |||
ce4eae65a7 | |||
4df48b202c | |||
33ced7088f | |||
3329977ec9 | |||
f84c3fdc5f | |||
44e1b23813 | |||
12b0a3d0e5 | |||
d2825077b1 | |||
156a52e390 | |||
bb7221f922 | |||
2eb4ee8393 | |||
87fe47737a | |||
9317056138 | |||
a235ae16ed | |||
79afcf0766 | |||
161a4dd15f | |||
6580d67875 | |||
04c6b2fe85 | |||
203b2ba637 | |||
5b99b8c18a | |||
6a011f4e8e | |||
f0c1f9ef39 | |||
97f35714f7 | |||
00e5b7d30a | |||
39c0f9ebb3 | |||
e60c765280 | |||
91dd672aa4 | |||
a5d2aadecb | |||
cc6749c158 | |||
f48142e679 | |||
947f9c3f56 | |||
7cd4741fcb | |||
2d520ae7e7 | |||
5d59c6e80f | |||
50345b8c36 | |||
7606c96c80 | |||
3466232f8b | |||
6e842fc5bf | |||
50c795280f | |||
51b22cf14f | |||
2291929a15 | |||
7fac4efede | |||
b96869afd2 | |||
6f4ee6101c | |||
6db27153ef | |||
9a11ec2624 | |||
aff1bc9f2d | |||
43512aa5eb | |||
c7f3aa71fb | |||
f9da3c98d6 | |||
a20a420be6 | |||
beadf6167a | |||
c8da7e995f | |||
8be6b12c2b | |||
4728f29f67 | |||
2a942e49ac | |||
e3aa19049f | |||
ef1eadadcd | |||
f444c11d21 | |||
d75502eeee | |||
ebcd14f8e9 | |||
b65f66feff | |||
dd68ae3ef1 | |||
1b04d70626 | |||
01bca41168 | |||
94e1ab33ce | |||
0b08dd8674 | |||
b2b47177cd | |||
f08257ff4a | |||
d1f4222c83 | |||
d21331e902 | |||
37f138e83d | |||
5dab0bad3c | |||
85e70a4cde | |||
6b564ecda5 | |||
d4cceff0ef | |||
a415613457 | |||
1a41bd1ca4 | |||
5a99393355 | |||
afcb3c0035 | |||
d2d36c61f3 | |||
0bd97ecda2 | |||
46bbcefb36 | |||
74b57dfa7d | |||
8c9c0986e9 | |||
4028fcaa51 | |||
7a8ef1eae5 | |||
e811a5d97f | |||
df44e3e425 | |||
cdb1a237e5 | |||
fcafdff10b | |||
c586656d43 | |||
3a307c2794 | |||
4f17dbc721 | |||
99989f5d3f | |||
6baf3baedd | |||
0d1f3c3b07 | |||
83e2d3d1cb | |||
b4613ab2d2 | |||
0ca05eee45 | |||
26c9e1dc70 | |||
797cb5ae7b | |||
63b82cd730 | |||
2b704f0586 | |||
ce5ba80792 | |||
8b18ef4ba2 | |||
cd18de7a21 | |||
fd19671c07 | |||
3fcd6fd93f | |||
c8d53d71a3 | |||
790362e243 | |||
2eda7a5293 | |||
9925aa89dc | |||
6195a45ae2 | |||
422d380b3e | |||
550ab31bd0 | |||
5fceb21549 | |||
29caa37943 | |||
8efbcc996a | |||
91c64d2b8d | |||
82e7ecd611 | |||
3d53b33391 | |||
34624b2db2 | |||
1ab5eb0844 | |||
630028350a | |||
7e4fd7d7da | |||
af2e80e068 | |||
8e6091de6c | |||
ecdaded25f | |||
c161ed415d | |||
ff3b71f7b3 | |||
16cc9b46aa | |||
3ce11ed58c | |||
7db75fa361 | |||
d6d4568830 | |||
a55d796c4b | |||
73f02c7861 | |||
8c8754e573 | |||
c977a906b3 | |||
e0eea6c2f4 | |||
3e377f520e | |||
8dc82a0080 | |||
4624a35845 | |||
8d4499959a | |||
2dfc9c653b | |||
106db0aba8 | |||
28c4852cd6 | |||
13c8211065 | |||
e73d0511cf | |||
e18626b7a2 | |||
4df7b1cfbc | |||
f9573ece41 | |||
93ade740e2 | |||
a46437c57d | |||
633c7d1ebe | |||
251953218c | |||
0d6cc17252 | |||
c8989c900f | |||
6134320f16 | |||
7f647822bd | |||
e34a04d2ad | |||
44093905e2 | |||
3e2900f74b | |||
11fd2eccec | |||
0eee1d5de3 | |||
1b77604ee2 | |||
cc5cfe87c3 | |||
48f230a951 | |||
2be50bdbb0 | |||
f7258ea52a | |||
28e8b2faab | |||
3c3e9ddb10 | |||
5162fb6d52 | |||
2fdb39e60a | |||
43c71ae103 | |||
f0bd528d77 | |||
50a024b42f | |||
b48f7bcb8d | |||
763ca60f5b | |||
0eca7abdd8 | |||
d0a95e35af | |||
acc6c8d0b7 | |||
3dbc66c1ac | |||
4ad6bcce54 | |||
0988cc82b0 | |||
20b03bad11 | |||
81d27daf0d | |||
bb8b82b3f5 | |||
915a6666f8 | |||
72da547d6a | |||
7c76a75452 | |||
a32c4ad2f0 | |||
fb3608aa5d | |||
0a46f37444 | |||
9b39e499ac | |||
a67cc8229d | |||
b58e9ea775 | |||
422effdd18 | |||
3b690b68a6 | |||
43349dd373 | |||
e44e8668ea | |||
69e72c0786 | |||
553344739c | |||
367f0fd142 | |||
58d9e7fc5a | |||
9d9e9c6ff1 | |||
ba88db5141 | |||
62e7c0f464 | |||
fc83bbbe98 | |||
482c019199 | |||
b449467940 | |||
0aba42ae5b | |||
0d1bf8148b | |||
b42411ba1f | |||
5a21f168d6 | |||
00b726f695 | |||
f02da4e91a | |||
d6b65db9a7 | |||
6f4e49ed53 | |||
46b212706b | |||
ca16fc29a6 | |||
9edea0b139 | |||
d15a1d64e1 | |||
c87847974a | |||
6f68330fa5 | |||
2b63330a36 | |||
06e4ca4bb3 | |||
43437c175a | |||
8d90a5a4cf | |||
93a4ca652a | |||
41178367d1 | |||
54f2edbb90 | |||
b652a7fc9f | |||
e34eb4520f | |||
190bcc89c1 | |||
64fc4648b7 | |||
bdb59129d0 | |||
d455942389 | |||
cdb3678fe3 | |||
e73ac1e992 | |||
51f3d22e4f | |||
00aa7a76b6 | |||
27b87ef535 | |||
44709e0dca | |||
31a7709ece | |||
a441b5b8fe | |||
76b8a49bfb | |||
db54a84d14 | |||
eb6ff65af7 | |||
23ee29b6a2 | |||
73a69895d8 | |||
2799e7a3ca | |||
b43f95435b | |||
450f61d384 | |||
f3dd91e1d7 | |||
979946c062 | |||
51e661eb74 | |||
921a17960c | |||
7a4f6621ed | |||
83bc5c97ef | |||
3f08efa35d | |||
0914dc35e8 | |||
b6746cce9c | |||
8cd97c2054 | |||
32d8cde9c6 | |||
1803ed2512 | |||
f08060b0b0 | |||
b77a4a40a4 | |||
e1109d52e1 | |||
0668ba50e8 | |||
44ff005ce3 | |||
aa88438b54 | |||
85be729c70 | |||
a5dc5705a3 | |||
9e3d13f61f | |||
961c9d48ae | |||
9229bbbc80 | |||
34feecf60e | |||
4c762a6be3 | |||
0426325ef7 | |||
0b54e3cf0a | |||
5cf58971f1 | |||
6518ff88b2 | |||
42b0c1d8a2 | |||
4a965052f9 | |||
5725c5925c | |||
a46291b67c | |||
4ac76ca281 | |||
e7a8e2757b | |||
1266460386 | |||
0ccb6e0dfc | |||
3050ae155c | |||
402fd934d0 | |||
6c86e8d80a | |||
60e6f91a53 | |||
e676fded21 | |||
25e070dd65 | |||
da8eb9f8b8 | |||
806a25413c | |||
5af1e891cd | |||
79eda30f0f | |||
6d02d2f107 | |||
ded518d47f | |||
27436270fd | |||
b4ea0b1601 | |||
7b31178546 | |||
2ff83324af | |||
4ef86891a3 | |||
eb5763c23f | |||
d1a3e3aff1 | |||
93d0a01d3d | |||
9af2d8b810 | |||
94dc632a6d | |||
29231877e6 | |||
e68252a79b | |||
4ec2a30942 | |||
e6b24437a9 | |||
a05f7b2d76 | |||
61e18434d3 | |||
57473e72ec | |||
c3bdd504d0 | |||
daa9da4047 | |||
245b0910ed | |||
a77db44129 | |||
34b3c534e7 | |||
fa47890032 | |||
d84a43c828 | |||
9a1babb30c | |||
30a332ee36 | |||
426b002897 | |||
2de8364de2 | |||
eacc9e6541 | |||
749dec7dfb | |||
96a9e66616 | |||
46e105f3ab | |||
f7a0e9ecb6 | |||
93025d1bc6 | |||
98d49d4ce3 | |||
1426f680f5 | |||
c7fc51a185 | |||
b7e69bc1a1 | |||
72544ba551 | |||
c43dd5a655 | |||
7f4954bed6 | |||
f1fc1dc669 | |||
cbe85a0893 | |||
7073cf74fe | |||
9d265b6f61 | |||
776a83f9da | |||
f29457f3f0 | |||
a005d1595e | |||
8d746e3f67 | |||
37e6da6dfb | |||
8aa2a0c1b2 | |||
6bfd514caf | |||
ad3f18c0dd | |||
39d04b4a15 | |||
6fbe56dbf2 | |||
8ebb8e44c8 | |||
6fcf962fb5 | |||
2708ce6a17 | |||
30bec78da3 | |||
9a04fcd061 | |||
ae62f082fd | |||
9cc3b2ca9e | |||
3fe1cb0253 | |||
0ed7773223 | |||
3f55aa609f | |||
74b45dfbf8 | |||
5c9f871b21 | |||
77dc6ef411 | |||
5eca6e4e40 | |||
0c65d5cf2b | |||
f65ebec3ed | |||
81bf3f66ca | |||
3cbded6694 | |||
137fff9632 | |||
695c08b9dd | |||
119794249b | |||
afb72164e4 | |||
9fee5630fd | |||
01de58d650 | |||
dabf214f17 | |||
fb2539e1d5 | |||
ad9f02a73e | |||
2d73583253 | |||
73f017bad9 | |||
055282f156 | |||
fe7de53b89 | |||
17e4cfc748 | |||
1608d91728 | |||
a3b90411aa | |||
5781b96490 | |||
f208ee0d57 | |||
8aa388de6c | |||
51d4c9dcbd | |||
e81dea695c | |||
3fec27961e | |||
3784696b9e | |||
8c45aebc18 | |||
810c722413 | |||
e2116c53f3 | |||
296a447e3c | |||
0961bd1eff | |||
9340e1b065 | |||
ae4fa56ee9 | |||
2d9d7f1310 | |||
5ee84fe0f6 | |||
1620426393 | |||
bf598d6b8b | |||
24eb8389d2 | |||
fcfddbf79c | |||
dc64e90ab9 | |||
e12b1277df | |||
797914e948 | |||
e0b0a594bb | |||
ed0ade6f34 | |||
5cc7b41f39 | |||
f2f1ec0117 | |||
e913d9954d | |||
d20488752b | |||
855f3afb28 | |||
3f44377f2f | |||
90295e3252 | |||
a620f95891 | |||
db66509e66 | |||
6605eb30e9 | |||
3644eef860 | |||
fb2509675d | |||
eef9512ce6 | |||
9f00a1b902 | |||
c369bc747d | |||
c03e1f2f59 | |||
17dcbf66b9 | |||
40b907a657 | |||
a33195dcf3 | |||
c693c03f1d | |||
de127109f9 | |||
83208983b3 | |||
327d04c9c6 | |||
54edce2bab | |||
1a145ac500 | |||
9f978cf49d | |||
41b781107b | |||
dcf75126bf | |||
1143b0389a | |||
97a2119596 | |||
fbd2dd9ca2 | |||
f463e09b9f | |||
42a5b6cbda | |||
0ad1215a92 | |||
7733c97df3 | |||
8a9e9c7bd3 | |||
3d8eb8cbca | |||
894747c34c | |||
8d5a312585 | |||
8eb81b3741 | |||
22d8f73bc9 | |||
249a6bdd98 | |||
3ad81b1beb | |||
5ab0534164 | |||
5150344213 | |||
98cef76931 | |||
6c5b653593 | |||
9ed8f2d26e | |||
33a2f86b28 | |||
fed1672a43 | |||
54dbed4f48 | |||
df759b8d4b | |||
6edf0474cc | |||
826f89f862 | |||
c43aec2182 | |||
ae75e3640a | |||
a5f2cc73f6 | |||
e1e5c40ef7 | |||
6420f75320 | |||
5face35ae5 | |||
398060d5ff | |||
638fd744aa | |||
098b461b69 | |||
9decc3d823 | |||
a5f2e205ef | |||
8899b83927 | |||
f6a410a4a8 | |||
3d5bb23184 | |||
ef37d2ae0b | |||
2eb234bc63 | |||
758ee95880 | |||
40e1112a8e | |||
397f5e2390 | |||
1a212259af | |||
f114dd300b | |||
5954a26bce | |||
bdbbe5aa20 | |||
15911367a2 | |||
8dd3f59c81 | |||
c9d28492b7 | |||
d1f93072a8 | |||
92d8bf9619 | |||
bd2281e32d | |||
0c50bc6449 | |||
f164715678 | |||
2aa615b4ae | |||
42c89b1b9b | |||
f6b75f56ad | |||
280540e4a2 | |||
fea216db12 | |||
b260eb06f6 | |||
1c937a10f9 | |||
ca23b4c55f | |||
7e12208ca6 | |||
2773281338 | |||
f8e8d22e4e | |||
cf4a9236b9 | |||
4450e7b246 | |||
cdbf67ee05 | |||
9a67f38728 | |||
25560ed048 | |||
2aa19fd078 | |||
cca9a58ded | |||
d6a25325c7 | |||
a717da2d3e | |||
b3e801ed9e | |||
3683fb6886 | |||
3bd0ce291e | |||
523fc5536c | |||
f5efccfb44 | |||
b6ec22de6b | |||
15f27b5455 | |||
127401598b | |||
503b07f698 | |||
f0a6329005 | |||
2982892acc | |||
9de56481f1 | |||
777eb2f159 | |||
05eebe0fed | |||
fdfbbd5bac | |||
1f3f8ef6c8 | |||
820eeb49d1 | |||
2d4be1c9eb | |||
2fef30f619 | |||
10113b63b5 | |||
545caab433 | |||
3f90659cc1 | |||
131914ac94 | |||
29a7c4538c | |||
f195bb608c | |||
66caabca0c | |||
25c6a3715d | |||
97cf0e40d5 | |||
6988a550ea | |||
8a1cdc2dd5 | |||
dadd5ddded | |||
56f8c95ee9 | |||
ed50e17e5b | |||
33b518ad21 | |||
b0e7c14545 | |||
5742d4720a | |||
9b356d9b86 | |||
793ac3f6b4 | |||
9b094e42a3 | |||
6ce7a5a1ea | |||
88920bfee1 | |||
2717bcc3af | |||
5d386dc426 | |||
f34af4f249 | |||
f04b6978fb | |||
ab958598d7 | |||
1914847e72 | |||
d95f0fd83d | |||
243612e36d | |||
c5cca8e098 | |||
99f7404d8b | |||
9ff6b0828f | |||
6f052d1daf | |||
63c194b71f | |||
46911117f1 | |||
2de1030413 | |||
1f6ade894e | |||
8407cfeac7 | |||
91d64a2855 | |||
40a06af79b | |||
8aef86f4a0 | |||
5bdc6ecec8 | |||
c179b5033b | |||
86f47273bc | |||
2e1bd46bb1 | |||
a9e773b47b | |||
10d38cbb72 | |||
a5371bfb8a | |||
4b2740f270 | |||
5b371736b2 | |||
c9b4bcf689 | |||
013f9a2bbc | |||
5bf1c93ead | |||
4f6ec01932 | |||
0f79e504c9 | |||
1a4e911b8b | |||
1f98519380 | |||
aad7010952 | |||
1be9ea681b | |||
f259a2204b | |||
4b1db0e61c | |||
aee764d14d | |||
47585498af | |||
37c5320e33 | |||
01111a1122 | |||
0b2bb1b6f5 | |||
f57df3cf8a | |||
c9c81e1fbc | |||
e38e04c1c2 | |||
99587ea4ed | |||
58b18d7fe7 | |||
04a50f5832 | |||
e157a065b0 | |||
41ef4b3d4a | |||
262650ab39 | |||
8c076d5a73 | |||
c5c456120c | |||
fdf6bc18dd | |||
297f0fd2c3 | |||
86405345b7 | |||
12c49042ab | |||
ba46ca683b | |||
ca42b49fa2 | |||
1b28cf71f5 | |||
6fd52dfb38 | |||
af2f5c3d7d | |||
65be81baf8 | |||
7a3689f175 | |||
8675b8dc48 | |||
279e816ea7 | |||
2d60ff14ae | |||
dee1b774f2 | |||
c0f2a22a08 | |||
5c8d3154d7 | |||
40f8a45b95 | |||
76a418760e | |||
49bf3f5b3a | |||
773c34900f | |||
791153c93c | |||
721f53f0d6 | |||
7498050421 | |||
5e3ccbcea9 | |||
8879aa1df4 | |||
44e0ad4987 | |||
c449f325ba | |||
5fe60759f9 | |||
6c389ed32f | |||
45549cda61 | |||
a13052fc73 | |||
4e7bb03e81 | |||
935c39a7e2 | |||
e0c1c13004 | |||
c08ca22dba | |||
a3f6e19881 | |||
37b617dccf | |||
c60ef45bc8 | |||
2b1ac63e3a | |||
6686bc62f6 | |||
1eaa193c51 | |||
b620f4f456 | |||
e484c62a8d | |||
9ba400d7d5 | |||
9cbd8f7afc | |||
8e6e90e703 | |||
26676c4833 | |||
39e0b4903c | |||
54c577cfe0 | |||
27024915e4 | |||
80f3e7591e | |||
933f45ef31 | |||
4fc37aeabd | |||
2fd1e88199 | |||
17f317d31e | |||
5941c92a31 | |||
d44d0852e5 | |||
80deac5cde | |||
8a54c1a115 | |||
0dbff55bc6 | |||
22916bb5d1 | |||
fe01e2efb7 | |||
7afee97d1b | |||
6fc267f22c | |||
ac84468f1c | |||
387a90e546 | |||
6eeb9495d8 | |||
566b4ef481 | |||
a191e9697c | |||
5504ca1e38 | |||
5c0cfdee48 | |||
bc888bf3a1 | |||
1745366530 | |||
1fb0db4aeb | |||
61960c51a3 | |||
14a3ade662 | |||
de97687422 | |||
a0251305ea | |||
2b8d12ddf0 | |||
1f6fd3c8fc | |||
55860e1621 | |||
4d51158b1a | |||
7d9c1e1225 | |||
d53edfec47 | |||
a6e5ddc5af | |||
b866f32832 | |||
97833d48c1 | |||
9c0031f7a5 | |||
164a091c71 | |||
4ed6cf7519 | |||
5267115481 | |||
43148d8233 | |||
537e99b4ea | |||
e1fcab777c | |||
f39c9c9e75 | |||
bbed364e7b | |||
3aca5ff9e2 | |||
9146bb0816 | |||
0c9e8dbf60 | |||
b34a04d53a | |||
0658eb4429 | |||
e178ee4ba0 | |||
9f506cd330 | |||
729dc3b764 | |||
7ce0fc7d47 | |||
b60eecfc47 | |||
346304762e | |||
e213939f28 | |||
4c39eace52 | |||
86fbd50c3d | |||
87d824e1b4 | |||
50acb96130 | |||
29c2dcff61 | |||
cea103a7ff | |||
d18694a1c3 | |||
b746c64229 | |||
d38aa5e25f | |||
efdc2d5118 | |||
515a8e0765 | |||
45de65bd45 | |||
9d6b98794e | |||
7aa1790874 | |||
5cd490eba2 | |||
ac1156739d | |||
7cefec77ef | |||
36d25f2a07 | |||
c3d2459a4e | |||
8847580fd7 | |||
cf3548a02f | |||
c197e2bb42 | |||
d1c989b8a5 | |||
57c9a07fff | |||
a19c4e8f9a | |||
53083c0b52 | |||
994d9212c1 | |||
52ddc96c9f | |||
057abefe50 | |||
f0e24b1a1e | |||
a1e3004e62 | |||
e504d4eb05 | |||
a6ad61d83e | |||
27a47e7841 | |||
b00b9fe564 | |||
fa0718ba9a | |||
155b88213c | |||
35ea02fb81 | |||
ddd2ac4f55 | |||
6f281ab3c4 | |||
fe8a7b0e82 | |||
76e6214b9b | |||
2d8f776e38 | |||
cf2d3cf920 | |||
b160ada5d1 | |||
1090601e8b | |||
01dd7dde24 | |||
13c39a52c6 | |||
3b80ab51ba | |||
1a386a58c8 | |||
04220be8fd | |||
48bf349c3c | |||
21fc1bb655 | |||
d38d375fa6 | |||
602836800b | |||
2953ea10a7 | |||
a738d0d54d | |||
d781e69948 | |||
c9b71fb5e2 | |||
dd6cb233b5 | |||
a3cf58b67a | |||
70d944a59c | |||
a5a422f8e7 | |||
e93b3d2360 | |||
7bc2d9a93a | |||
1c929031a2 | |||
f2809d1ed8 | |||
f4f6b8721a | |||
7e352a27f7 | |||
0c6b16c208 | |||
10475b859d | |||
4d793c4eb8 | |||
3ae29c08ac | |||
3331321f64 | |||
c6064a30a1 | |||
040b101842 | |||
a78a43c816 | |||
ec198b0dc6 | |||
b5d14c26d2 | |||
2019050db2 | |||
5f999225ba | |||
307d105d2c | |||
0b6967fd74 | |||
ef0c32512c | |||
9096481744 | |||
5936624d11 | |||
83723671af | |||
4d825dd9fd | |||
8e38291156 | |||
f93512bf27 | |||
c3fafa0651 | |||
9036f78b74 | |||
263122ea5f | |||
324f0147f6 | |||
be48ba1b06 | |||
b2a7fd05cb | |||
84f859d7b2 | |||
cbc8d0adf8 | |||
420e83a396 | |||
89f61087c7 | |||
1dcb663917 | |||
b7b56785d1 | |||
3a62023260 | |||
fa2ce8100b | |||
172a5663ef | |||
f4b972815b | |||
0cb93a436d | |||
b2e804c961 | |||
85ce184197 | |||
29c77df4be | |||
c39e0463a3 | |||
c27bc1956b | |||
72707d80ab | |||
f18356307b | |||
00475f25c8 | |||
bab6023eee | |||
5e12a95789 | |||
e5904f4089 | |||
cf1122cf9e | |||
6da79673c2 | |||
352ee53202 | |||
a20639558b | |||
b9347eb01c | |||
4dbd8ed6b8 | |||
cb980d3e43 | |||
f154e2c6cf | |||
d0a64f9c86 | |||
16ef21d086 | |||
39ecd01b86 | |||
5e0f8cf3f0 | |||
6c6b316bd9 | |||
b49dac7be5 | |||
4c26397937 | |||
e26e4f922e | |||
2ab1085dfb | |||
acc3a2de83 | |||
12abdd8782 | |||
2bcdec5aaf | |||
16dfe3c63f | |||
b4a467e387 | |||
53628e19ac | |||
62dd3ceb64 | |||
d5066a9a0f | |||
32b37432b0 | |||
5f3d02bc7c | |||
97e94dd6e0 | |||
846c031ec9 | |||
92340350d2 | |||
d4827caa08 | |||
6ce13b68fa | |||
e82b700ad0 | |||
60a2ba87d4 | |||
83c19a1fbc | |||
1513e201bb | |||
a38c9a1ef7 | |||
d5f5ce82ca | |||
6dc88f5b61 | |||
7a2ce7ff21 | |||
1ac38bd69a | |||
982fad0c45 | |||
390cefac72 | |||
798bface7f | |||
276fec6e50 | |||
95af14b97c | |||
0f0a8ade7c | |||
e0c83f669e | |||
016f0d8e9e | |||
3e5716ec16 | |||
75e6dfb9ab | |||
9634e8d14a | |||
f95a604b59 | |||
3ff20cd7e3 | |||
17f73cb7bc | |||
fba0e2ff12 | |||
b62415c962 | |||
adc135e6c8 | |||
ceac045a7f | |||
4d6da7b1a7 | |||
01b9de7a15 | |||
0a872ffd38 | |||
6f3a6a55a0 | |||
0795dd307b | |||
49fb7ef421 | |||
cbeeff2bd6 | |||
ce013a3dd9 | |||
1f7449ccf4 | |||
c43636f2bb | |||
9c2fe660a3 | |||
abc266fa35 | |||
7d853dd9ad | |||
3ac2821a1b | |||
666dc75c15 | |||
e9332c66d2 | |||
830aecd1a7 | |||
ac6959c819 | |||
2bf21e1747 | |||
9105ab9596 | |||
165357bfa3 | |||
33c7f74cb9 | |||
cb84cbf545 | |||
b2e0946696 | |||
67c80fbb5e | |||
c574e6808f | |||
9175a049d3 | |||
0035575c82 | |||
7bfe8aa553 | |||
1bff47f97d | |||
e8e61de28d | |||
54f8308999 | |||
6c99746f0b | |||
4086b49046 | |||
0fad9c2786 | |||
d75f928fca | |||
68f9aaf214 | |||
efe4633b15 | |||
19e65382f7 | |||
5a9eda73b4 | |||
c6f2b3e96b | |||
55921be1af | |||
9b1b5b393d | |||
3857c8226e | |||
595bcdd1ac | |||
27c25bd0e8 | |||
aec95015f8 | |||
b2db6401cc | |||
ebe14720eb | |||
7112d008d0 | |||
90af4763d8 | |||
390046d7b3 | |||
587c119c75 | |||
3019140e7e | |||
7a80f0d1e1 | |||
0894318f50 | |||
f9fc524a74 | |||
9019c6f937 | |||
166b73f4f3 | |||
cb94111f18 | |||
a88b887a05 | |||
6e62217b78 | |||
a01a54c180 | |||
db8290632f | |||
7bb5167239 | |||
6cdc53c497 | |||
15ae710d22 | |||
dd50124254 | |||
ff36b0384a | |||
50c9bed630 | |||
8b1b427195 | |||
9a05ca95f6 | |||
05266241af | |||
4ddf5536b4 | |||
f389b5a961 | |||
bac1a6eab3 | |||
ff400726ca | |||
267d864976 | |||
97a1084c99 | |||
61b339678d | |||
d537a26297 | |||
d414734aac | |||
817ddfa847 | |||
c1154b30c7 | |||
0d71345b93 | |||
f235454dd6 | |||
6a80578d05 | |||
d33cd43db1 | |||
9e3df8eefe | |||
cf73ad7c8f | |||
3e68b7eb1f | |||
9fbafba993 | |||
7a524e3deb | |||
7b6c4d5acc | |||
99c0d503d7 | |||
f86edae9f3 | |||
df1b1f6957 | |||
9099160038 | |||
119abe7bb9 | |||
67ed2e2c0a | |||
6d36a7a45f | |||
e2b1e1577d | |||
b30ddfbfc5 | |||
abfb522f83 | |||
b8136cc26e | |||
d00b26d941 | |||
12637a761c | |||
1a0aea67a0 | |||
0f1465b899 | |||
c0cfd3c6ed | |||
a81923b793 | |||
7150ace7c7 | |||
bdce154282 | |||
5a84048f72 | |||
188bda813e | |||
29700aa188 | |||
3229bf1665 | |||
52595f52f9 | |||
edec158dd8 | |||
0297398f5e | |||
9485f5a813 | |||
8f8c017882 | |||
eba6e7946d | |||
3cfe281790 | |||
6eac4b68bc | |||
fcbfacb6d5 | |||
b600915953 | |||
905f38acb8 | |||
38f4c5f155 | |||
509f4ec611 | |||
27a7b51d99 | |||
a033f8335b | |||
b98c9e74e1 | |||
9f784dcc5a | |||
b625f2471a | |||
3aa2606ff1 | |||
89704e0f93 | |||
908a102a87 | |||
dd6e0cf1b5 | |||
52a6ba7ed9 | |||
43e0fa513b | |||
de978229b2 | |||
ba62fe974b | |||
3a40cb1a85 | |||
883e0c48b1 | |||
18b6a55764 | |||
00d3b6083c | |||
c386fc8379 | |||
43527172ed | |||
b88384eed8 | |||
107016ec12 | |||
d930ad1816 | |||
072446aed3 | |||
2e1f3f003d | |||
fdd8bd1a36 | |||
7db911fdd4 | |||
b6fd81169b | |||
3ae856ab8b | |||
ce5b37239e | |||
3e17c99f4e | |||
bb8976608d | |||
cd52318f48 | |||
2570b72158 | |||
6e79de794c | |||
c4be30d2e8 | |||
57240c85a5 | |||
a66cdb469f | |||
505da6c0a8 | |||
4fe0f1fa65 | |||
ec4ca0eace | |||
db95fd6ca9 | |||
ca13f1c024 | |||
277b1fc473 | |||
8836219b16 | |||
6f5e3f9390 | |||
a84c2d7fee | |||
f114d6c560 | |||
163d80adb7 | |||
9e05814212 | |||
ab56be46e1 | |||
6a0cbb8a57 | |||
4e2c68354e | |||
62a0809e81 | |||
76d6f5fa0d | |||
0f1b370117 | |||
e589f9949b | |||
0f774df811 | |||
351f24e8eb | |||
aecb60a604 | |||
4d691b61ee | |||
11955f9b13 | |||
5ff31f0713 | |||
deba804671 | |||
e5b87e55da | |||
d097784d57 | |||
15f6b27ae0 | |||
176e55927c | |||
365be6a309 | |||
713e6d4aff | |||
a8e277b067 | |||
3aa322a9c6 | |||
a02614beaa | |||
d2527b504a | |||
46cd868827 | |||
b1a9e445b3 | |||
5297c9d9cc | |||
ee7caceec7 | |||
a0b5964a63 | |||
cacdead96d | |||
96ae348648 | |||
78946fe9fa | |||
33e53c9a59 | |||
c493d88405 | |||
8bf6ef6544 | |||
ca40ef5ac7 | |||
7c0d4976b1 | |||
30de2db349 | |||
602641dffd | |||
560cc14d97 | |||
de56dd5f30 | |||
fa5bfe4b64 | |||
446657bdd5 | |||
79830f1c75 | |||
6e1fed42b7 | |||
d35c109cb9 | |||
fad3b6434c | |||
073ec0a7eb | |||
70b23ae2ca | |||
769835e53e | |||
ac55e1e27b | |||
0700c8a252 | |||
c79e657fcd | |||
d9648887b8 | |||
35cd0ded22 | |||
d2efac18ed | |||
ff2ae7a2e1 | |||
e1058a4d8a | |||
d327ac4b43 | |||
1ad2a02b11 | |||
1e8864c4a5 | |||
c209836fd0 | |||
7d1b6af073 | |||
140a878a3d | |||
b62bccf254 | |||
39eb34739a | |||
969b55326c | |||
2c8371654a | |||
5a897cf299 | |||
ef67a0c57f | |||
ef6163e652 | |||
f6985671dd | |||
90a1f7d5c4 | |||
3e114227f8 | |||
6103aa0a46 | |||
b7c6feff28 | |||
b48d907697 | |||
676ddfa065 | |||
c8d00dc191 | |||
0b6865d6c6 | |||
67d05eb65f | |||
152a117d5c | |||
d6626309fd | |||
c3daccd83b | |||
8db62151d2 | |||
bab81a9831 | |||
cc86fee1d1 | |||
386cc5dbb6 | |||
2f7045720a | |||
9889c21aaa | |||
e69cb40de3 | |||
12837e1c17 | |||
9092ac79d4 | |||
0a7d10ba55 | |||
efbd446d18 | |||
c06b0a2371 | |||
0c600cf6e3 | |||
41404057cf | |||
f4e6994634 | |||
b602bd8c83 | |||
30c43521d3 | |||
45f5df371d | |||
43e31c5abb | |||
13c8b13343 | |||
0fc9ec248e | |||
d094a85647 | |||
22c05b0834 | |||
8490921fb3 | |||
ecb9bb96f0 | |||
75463cd8df | |||
c6244d1470 | |||
22ae2d0976 | |||
88b0a239c4 | |||
7c9717bba8 | |||
7f297666ca | |||
d99823e2fd | |||
bb9fb21fac | |||
b64672b23c | |||
930f58718b | |||
2b34c88b69 | |||
45f09ba686 | |||
bb62905bef | |||
7bc9b19418 | |||
e9f7a00910 | |||
a5d6b6db8b | |||
fc496813e2 | |||
2abb414cfb | |||
0e56aaf189 | |||
3412aba46e | |||
347e71af7d | |||
d24df799d3 | |||
01e6b8c7ed | |||
60727c4d2b | |||
03627aa84d | |||
83b8f59297 | |||
c6f454f51d | |||
ccff17599a | |||
fb2773b8f3 | |||
5110121f6e | |||
27cf897239 | |||
5d33a12af4 | |||
08b295603c | |||
3b60503d2b | |||
3c2473bac6 | |||
f9426709ef | |||
e1e44a910e | |||
f371c9066d | |||
85c1927993 | |||
a596b887ff | |||
6cbf99086e | |||
26a3390549 | |||
9a1959f77a | |||
226e662cf1 | |||
7a1a1b80ed | |||
529988bc81 | |||
c17dc1c057 | |||
09a95a692e | |||
247964af62 | |||
5e2bc5c593 | |||
28e657d857 | |||
06ad112998 | |||
cfa1d17afe | |||
3ca6df87b8 | |||
e310bee9e2 | |||
4902244cce | |||
8db97b0b7a | |||
9be04f8d38 | |||
74e2bd7e3e | |||
52d3980d02 | |||
4e9809bcb2 | |||
bd8a4215dd | |||
d23b973e7a | |||
0dbf959548 | |||
20812f446f | |||
27a4d0ce11 | |||
9dec4c7485 | |||
90c87fa6ad | |||
291928feb1 | |||
c9c52fb353 | |||
0bcfcde63d | |||
1c20a62611 | |||
8430927e6b | |||
d2ca7d81c8 | |||
756121acc1 | |||
d7e1175df0 | |||
66cd84e0d5 | |||
506f4ce1e5 | |||
a0387d2835 | |||
9bdd5951d9 | |||
111afcdff1 | |||
85f3dc2fb5 | |||
430f367c2f | |||
d272f96e23 | |||
73a84a7098 | |||
17c8ec8a5d | |||
a1880c3576 | |||
91999e016e | |||
aa966f5de2 | |||
3e593b8221 | |||
440aca86a3 | |||
09f4d6f52d | |||
3f57fa6e0e | |||
ae876d1317 | |||
6de68e2f1f | |||
49527ab495 | |||
0898bca939 | |||
d940387beb | |||
27c45b05cf | |||
90f09d551f | |||
3739588e97 | |||
0730b753f2 | |||
cad693de0f | |||
bf911fc992 | |||
fb6d791ce9 | |||
0f8efce799 | |||
69c1405196 | |||
980491b08f | |||
72e24663ad | |||
363ed5140e | |||
b0f585ab08 | |||
8b67b07580 | |||
5c330ea492 | |||
06eaaf0ac5 | |||
9820271243 | |||
b6507e37ef | |||
c194f6695d | |||
967ae3e1b8 | |||
a5e6eaaebc | |||
d4e9b55fb6 | |||
048bd280dd | |||
8326ab3240 | |||
a7fe983be2 | |||
e1f8e54e34 | |||
2b165944ea | |||
ea11b3f1f8 | |||
3bd87147ab | |||
2f581ffc88 | |||
d61aaac400 | |||
310620fd12 | |||
f9fb72fb0e | |||
095db673c5 | |||
70d18b5b53 | |||
f1796d67f4 | |||
cb38d72ff4 | |||
b72bab49aa | |||
201475e8d8 | |||
c25b9fcf97 | |||
8755a8e188 | |||
127fbfd5a6 | |||
f33dda79e9 | |||
293fa5505b | |||
df1f78e302 | |||
43bb31c6c6 | |||
169869a195 | |||
b691da26af | |||
8e3e45097a | |||
aa43d2f87b | |||
128acbb6eb | |||
5824866a83 | |||
0d58b137a7 | |||
b5c769e1e4 | |||
7f22bd62ab | |||
83f0e7c975 | |||
adef68b4d6 | |||
14f0e9ada8 | |||
ef9e40e82b | |||
41e38e4330 | |||
2c7c3e3c69 | |||
756f5d884f | |||
45fd6f0a41 | |||
75ae4a9159 | |||
37d18d0112 | |||
773fe8f8c5 | |||
4da2b19ea0 | |||
9f3547e35d | |||
5a79358727 | |||
85bfbc13c1 | |||
1a01af9e68 | |||
dd95e901df | |||
9782d8c32e | |||
80764c6f71 | |||
d9e78e4fa8 | |||
10fedd0dfc | |||
315e73c47c | |||
912717ff31 | |||
b857fd1eeb | |||
6dce4f49c2 | |||
15e16148f4 | |||
ae49085481 | |||
11e8aa26f6 | |||
81beb1c788 | |||
6402d61f69 | |||
5a59e44765 | |||
7455b907d1 | |||
579b890446 | |||
19a08f3a43 | |||
a3d7629134 | |||
bc9644e86e | |||
a10c02cb41 | |||
9936e347ff | |||
7d44b8230e | |||
75343eb340 | |||
2548ce86db | |||
5586c29492 | |||
1174473e9c | |||
1d49b3e36b | |||
2830df4190 | |||
143cf89b5f | |||
69c1694900 | |||
01fe7f5fac | |||
9aedef208f | |||
39b6e0efba | |||
f60fa14767 | |||
d900f5c075 | |||
391a9edabb | |||
28a78117eb | |||
eeb594c010 | |||
0bb10d6bb6 | |||
59629a0801 | |||
b5e6319fa9 | |||
c9a3df970b | |||
f72f137261 | |||
ee3c580e88 | |||
05c185a7b1 | |||
b47f80ec76 | |||
ebd438ff5e | |||
331b9c1317 | |||
4a93f58b8b | |||
ebe531bf92 | |||
1779caf5f8 | |||
6ef2121e6a | |||
38cb526f60 | |||
f6a8d04c32 | |||
4b3b5d7c53 | |||
abff302e52 | |||
e1f6679c75 | |||
aaafdf03ce | |||
ee298baa1b | |||
d1abada5b7 | |||
ab36ea097b | |||
8bb66a5eb3 | |||
cfc1e56dd8 | |||
a1c3be21ec | |||
edad8e3f56 | |||
d4a4d81173 | |||
e7470d557d | |||
b634a25ae0 | |||
c1a0af514f | |||
c6afea61f1 | |||
ce10fe92b2 | |||
b81b1fb81c | |||
280b86ec55 | |||
2f5a2ba671 | |||
c45ec6f1be | |||
530470e0ce | |||
ce72ccf9e8 | |||
46d9c87ddc | |||
d736c31fea | |||
a7e9bc97f6 | |||
265703b950 | |||
ae275fa4e4 | |||
3478d5d450 | |||
e72dc16dbe | |||
40a043275d | |||
f161b5cc28 | |||
117d57e121 | |||
3dcce706fd | |||
efb89b83e1 | |||
3d96c2337f | |||
19cfb4eb12 | |||
3d715a2f7b | |||
c7261c295c | |||
1a26f8edd6 | |||
fc887774da | |||
7cbf88a691 | |||
1cb1c139cf | |||
1fd924f7d5 | |||
eb688f2c8e | |||
61cf499b0b | |||
f1f5b45361 | |||
50548fb565 | |||
8f47aa3530 | |||
df7885c9f5 | |||
0f10624b08 | |||
6f1ef33e32 | |||
231773ea76 | |||
e725542703 | |||
2337469753 | |||
55122cd57a | |||
7e0f02f96e | |||
e7ad03cba6 | |||
74be3d3fde | |||
a15ca23469 | |||
de77700da0 | |||
e73fee7156 | |||
72ab35bceb | |||
0f22dce036 | |||
c6036435f0 | |||
d86be245b8 | |||
a26053d3ff | |||
24d5b665e1 | |||
aa98fad338 | |||
9cb6dbbbab | |||
e21718faa9 | |||
b0f7d59e64 | |||
b86829f492 | |||
22929a1671 | |||
86c40f8474 | |||
16b521794c | |||
2a70f4e4c7 | |||
2f31c4c1c5 | |||
1435763383 | |||
05238df89b | |||
772d60d9fe | |||
24086bf0bb | |||
9b0e10e9a7 | |||
995a9e0cf8 | |||
b55f1764b5 | |||
5e9daed2e8 | |||
aa8c5aa2e2 | |||
f2c7946cca | |||
da1fcfd820 | |||
dbeff6f548 | |||
26e60d658a | |||
c2ceb7fba4 | |||
4bfe49cd42 | |||
cee2318110 | |||
cfef76f683 | |||
f56df65d48 | |||
3a40cd79f0 | |||
6acc99729c | |||
99e6500a2d | |||
5c782d6ba8 | |||
4e43d6f769 | |||
3529ee9973 | |||
29aa6a6c1c | |||
7918f3c1fc | |||
2f4e176054 | |||
d4565fdaf3 | |||
2a302aa73a | |||
31b819e9c2 | |||
27daeaff5e | |||
3e9b532409 | |||
c5aa6d17ef | |||
e480b0798e | |||
8a645d5e44 | |||
321193889f | |||
566d3ede04 | |||
8c36aa866a | |||
ed2dbf2db7 | |||
36a0e04604 | |||
8867afdaab | |||
a199772508 | |||
b008f542fa | |||
a78dcfa5f3 | |||
e1bf3d33f8 | |||
ae7d2ab515 | |||
c6adbf602c | |||
1f7a41c963 | |||
f4f614f3a9 | |||
94139c351f | |||
fc5b128b43 | |||
68a799af2e | |||
16d9c60a0e | |||
c0b5e7a672 | |||
6932b29acb | |||
c2a38c05aa | |||
8bea667a0b | |||
800c8f196f | |||
42231f5719 | |||
db87baeb98 | |||
c4c43f5a77 | |||
0ae77753f3 | |||
5f0baaac73 | |||
b5b6ece65a | |||
4282297c24 | |||
9c96b8affc | |||
132829e5e2 | |||
4a414420e9 | |||
fb6335ab60 | |||
89bd008445 | |||
caafb41eb5 | |||
31b81a7439 | |||
f7b1973358 | |||
32f01da49a | |||
59684c97b0 | |||
a32a0a3a97 | |||
96f5b0929d | |||
8e6cf7fca8 | |||
fdbe8741c9 | |||
775fb2c340 | |||
b60f594798 | |||
cc49790bdb | |||
a4bc19c530 | |||
f7985dbdb7 | |||
0bdcb5c1e0 | |||
a0d25db4a5 | |||
625474c4e2 | |||
1cd2a6328a | |||
d6bafe4fe3 | |||
6a2ef15355 | |||
a8ca560503 | |||
ad361808ec | |||
c47639f2b1 | |||
ba90a85f7b | |||
d3b569557f | |||
c9090ffa31 | |||
341bf39d23 | |||
3778ac26aa | |||
6cfc6f5bb2 | |||
47a3b4d56b | |||
c72ed991ad | |||
78bfdf78ea | |||
a24ee6add4 | |||
df3074fdfe | |||
f7424d5aeb | |||
a593ffa6f3 | |||
761c6d0df7 | |||
3e65d1458e | |||
a4b5cb8376 | |||
c785a1e474 | |||
3adc472f06 | |||
e7081b8b7c | |||
9b3a548f6f | |||
90b3502bb8 | |||
e19b31db29 | |||
bd015f14e8 | |||
ca7ba12fc6 | |||
ae05ec69c4 | |||
92dc3b91d8 | |||
8bd697b316 | |||
eda4c3eb4c | |||
4d0c2ed1f6 | |||
eda6a5d52a | |||
c1c54ed0f2 | |||
6b73d09ba1 | |||
ac85cbb28a | |||
b0cebdba6b | |||
933a9112da | |||
8c37b7e8f2 | |||
c8e909f8c9 | |||
69ae3634c7 | |||
95248f46a1 | |||
b3c7df1783 | |||
c56679e8e1 | |||
041c599511 | |||
6343f71be5 | |||
89f32f808f | |||
7ae23adaff | |||
a08f50badd | |||
0b6e75a85e | |||
4291758079 | |||
b44d36cf95 | |||
a038bb9ae3 | |||
9d28147acb | |||
d116861c8e | |||
9a70f1a1d9 | |||
8516473340 | |||
cab69f689f | |||
822e83ebb0 | |||
b2bc50dbd1 | |||
e748adda2e | |||
630d93150a | |||
76f1f9f1e3 | |||
c47d85b038 | |||
197cf09689 | |||
e67ebb7f70 | |||
3524946581 | |||
9276dad42c | |||
2a2f9a9a19 | |||
909e70bd61 | |||
8ac9719832 | |||
3eff7c6f59 | |||
17fbbfba91 | |||
b232dded77 | |||
f50affaf9c | |||
463754bf16 | |||
a45b27e7f9 | |||
af3ea16acb | |||
fc75220d63 | |||
00822c3415 | |||
3dca9d522a | |||
de996ec50b | |||
059e09c3be | |||
d5e4686e7e | |||
d55655f5a3 | |||
61b9468596 | |||
c6f52e3282 | |||
42ccff859c | |||
29600c0c87 | |||
5b63b6764f | |||
2835265916 | |||
e950dd6a2a | |||
321ed7d099 | |||
42b74f524a | |||
77b7caeceb | |||
b803ecf7e7 | |||
d3a79db48d | |||
e891baeea4 | |||
2aaef81b1b | |||
3191fd1440 | |||
80a5e47e61 | |||
5a04ffec3e | |||
1c779d8b9e | |||
a79fe057f9 | |||
b88a6d983f | |||
19396d14cc | |||
2983558e5e | |||
0f8e40bb42 | |||
006a96dd20 | |||
4deaf0bdd3 | |||
9917d7f8af | |||
1607ef8782 | |||
539c5633bf | |||
f83f4ace2d | |||
283962f810 | |||
892f9e19bc | |||
cacfb214b6 | |||
4e5cd1e558 | |||
43f42d9c6e | |||
a885f37dfa | |||
ed2c25eb2f | |||
b1b0593ddf | |||
200dc00dbb | |||
20c6eebb29 | |||
8c69497d8e | |||
44c648fc04 | |||
979162d324 | |||
2934b82113 | |||
92ddc62bed | |||
0cb32c2fef | |||
2ca5e38a78 | |||
b8e69a21a9 | |||
3fd898e91f | |||
a66cc50168 | |||
eb296756fb | |||
f1a9a537cb | |||
080469f8e6 | |||
7c13372721 | |||
778677ba75 | |||
f0d876a873 | |||
e9e2a4152e | |||
398f024b24 | |||
4a17e6906c | |||
8d3e5596dc | |||
df6d2d1e23 | |||
d26c338aa0 | |||
edcb34dc9f | |||
693d9dce5d | |||
194dc7da78 | |||
79399e1c51 | |||
fe1dd77d94 | |||
24dcd267b8 | |||
cf3ce171a5 | |||
06d076a6f2 | |||
3190c5941a | |||
30e25acb9f | |||
4975cb92ae | |||
c8d6ad2718 | |||
cde6726e25 | |||
b3d10af89a | |||
4724cc664e | |||
4e16feaf72 | |||
9e44dd85ad | |||
da9b46a071 | |||
b386d1134a | |||
1e740581ee | |||
f1741b10f2 | |||
7bce1477ef | |||
01ba94ba56 | |||
51cb7586e0 | |||
796eee1e6f | |||
c39828f0f2 | |||
28860d35b2 | |||
5f0ce30ee6 | |||
f4d937ad8d | |||
db096a5e22 | |||
bf484b19b3 | |||
56a254e6a5 | |||
793098bcce | |||
d6d759d722 | |||
61e8b60506 | |||
2f0744b089 | |||
ca73852746 | |||
72444c40a7 | |||
214148d58a | |||
cc8f1f9552 | |||
cbf788869d | |||
c1ae49d91e | |||
4432cf5438 | |||
869a392357 | |||
90c67b4b11 | |||
7d15e19f2b | |||
a4ba46cb99 | |||
0df8bc4e52 | |||
0d9a1de4d9 | |||
d58f017226 | |||
1d825eb685 | |||
b3c91b163b | |||
aa85856e1c | |||
fb4f1e8dc9 | |||
8657ca4298 | |||
80b025ae53 | |||
11f98c58b3 | |||
c1e3ea9f7f | |||
21542ed069 | |||
c39f4c3b38 | |||
1f35048d54 | |||
eb0ea931d0 | |||
47f1d12731 | |||
aecf68117a | |||
3a438615c3 | |||
9850e68703 | |||
daaa8ee1cd | |||
50490b55eb | |||
86c74cf3f3 | |||
7f0925eb2b | |||
85d89babce | |||
ad481694e1 | |||
2d313c4d1d | |||
e6170e8ac3 | |||
4b1618cb03 | |||
0a44fc69fe | |||
c6d6b75691 | |||
f664a9c4d5 | |||
a090843b84 | |||
d10224d21a | |||
7e18d4c539 | |||
22e9590981 | |||
d388c0ae62 | |||
56604468e0 | |||
b925ff5b8d | |||
654496b315 | |||
c6a5d9bc84 | |||
19b61b1cf3 | |||
5e50859a03 | |||
4ea5b6e57f | |||
e67e1952d0 | |||
0614797d84 | |||
0a3a17ff10 | |||
680f7e0299 | |||
688469c221 | |||
7a1fbf1c3a | |||
478a25ed27 | |||
1edb17b8d0 | |||
1710272b3c | |||
93a1ec29e1 | |||
d90a2269f9 | |||
69996b1740 | |||
35e32bbea1 | |||
e9f873a365 | |||
25a2d7b5db | |||
c635a73ed9 | |||
f76eea4f9b | |||
5514dc19d9 | |||
a16ac84840 | |||
ad99199d50 | |||
c7242a39d2 | |||
4fa1809f80 | |||
2a4ac63a34 | |||
c5ed2d219a | |||
fb16c39496 | |||
62c2ed7c43 | |||
9c6b929c7b | |||
070d818e68 | |||
7f783289ab | |||
1417e12f28 | |||
9a65ea7ea7 | |||
c58e7e0e91 | |||
bdfed9d850 | |||
b9b14dc731 | |||
cf3ceba2cc | |||
c08d76c7f8 | |||
d1c284a3da | |||
442d6866da | |||
093b7948be | |||
706990c65d | |||
f77ca7b5e2 | |||
922da62720 | |||
87449ab43c | |||
6b2ef25c69 | |||
3e364b0d41 | |||
47d0942f3f | |||
87ac36f65b | |||
015faeeaf2 | |||
909426e37d | |||
c4c4d045fb | |||
2ada3ecad5 | |||
fcc7ce225e | |||
604c8bbad5 | |||
4215afc639 | |||
909031e688 | |||
b7b3c85033 | |||
0c9596ae2b | |||
a8c3b9d67c | |||
65bdf42903 | |||
7f3223bd2c | |||
87ddc8fb6a | |||
6ddfff5cd5 | |||
a3253210b7 | |||
0dbd0b340c | |||
8c670822ce | |||
b90de66535 | |||
1bec4f6c61 | |||
b6ec2387b3 | |||
cf157b99d3 | |||
2cd0f076cc | |||
fa725b4512 | |||
5a27ffb5f5 | |||
d59c20c315 | |||
019cb41dd8 | |||
b4de41b74e | |||
87d56acdaa | |||
8daa9b202d | |||
89eefcd7b5 | |||
9ae171e0c8 | |||
cee67e6fe0 | |||
a3353a5e28 | |||
c5294c77d9 | |||
ba64b5ea5a | |||
230aad4047 | |||
564642d859 | |||
87549c77d4 | |||
fad354904d | |||
e1d7bdcfe7 | |||
46fc153f39 | |||
4332ccf72c | |||
201f189d0e | |||
a35a93d0da | |||
163164cb79 | |||
31f85f0297 | |||
225b9d306b | |||
9ca8a35553 | |||
5806babb0b | |||
30d35b5046 | |||
88afae15a8 | |||
cf7292fcb1 | |||
422a7b18f6 | |||
0b1ff2db9e | |||
a43ed79ee7 | |||
125fa3885e | |||
ae58934d52 | |||
3c8fa8c50d | |||
4d59985b74 | |||
4e12b0831e | |||
5ba9ced1ab | |||
36a423fac8 | |||
adb87562bb | |||
0db02523d3 | |||
3c43a8c549 | |||
3fa287aae2 | |||
929abb9aa3 | |||
837efc2a0f | |||
3eced6e1a9 | |||
c53a63acca | |||
621fa490c7 | |||
9691c045a7 | |||
c855c5ddc2 | |||
2c8fcec432 | |||
60a2bbb226 | |||
d013fc7604 | |||
dd1e212402 | |||
ac38812809 | |||
b571baab68 | |||
a31e2f5f47 | |||
bcd926adc5 | |||
b22eddf1cb | |||
857bef9e4f | |||
4e585bca28 | |||
94cf671c15 | |||
ad6fb067e9 | |||
c03fb36e11 | |||
bccd8a719d | |||
4e1d9c93df | |||
0611239a0e | |||
c5045ac8fe | |||
41dfaf393b | |||
96076862cf | |||
a8edc1eb58 | |||
86aeb8be0a | |||
e274ff8a69 | |||
9985968d89 | |||
bb9cfe6f36 | |||
406ace9b25 | |||
6d70cd78ec | |||
a70a919d14 | |||
b16fa45d83 | |||
1d9c44b34f | |||
2ecbd0eaaf | |||
8ab7781b2d | |||
cf0183ac7f | |||
2ce9e95fc1 | |||
49e261efd8 | |||
9c94ab1e8e | |||
d1d88c32c3 | |||
63639895ad | |||
0eab4fc72c | |||
d9f362a713 | |||
7f6289c1bf | |||
78280a48af | |||
f80321fd26 | |||
8f91ff84c7 | |||
3f4628c0b0 | |||
4e02e00373 | |||
9b3b721f08 | |||
756727b930 | |||
533b722c66 | |||
029c0534f3 | |||
d29563fdd3 | |||
4a43230de4 | |||
01ebff4080 | |||
344776f864 | |||
a3e6406b38 | |||
64bd9639a1 | |||
1ff1792642 | |||
e6bf33efbf | |||
5fecb3b3f2 | |||
ee07646059 | |||
e27665c368 | |||
2618becaa5 | |||
0dcca1a28e | |||
e667ad3e6b | |||
fb8b8157ff | |||
a8d9dbf110 | |||
2645fb0d6c | |||
18b508d14a | |||
b0009f03d5 | |||
79472b77ca | |||
3593d85807 | |||
6133f2c08b | |||
63e853dcd7 | |||
2d0c8f1b0e | |||
c6ad269f43 | |||
a0a627f2f9 | |||
c5693f07dc | |||
253e2b2285 | |||
aa70275b01 | |||
0b11051ac1 | |||
4bb9c46cf1 | |||
7343ef04ae | |||
4439106a1f | |||
2c201d3f34 | |||
fc50829481 | |||
695923dcd6 | |||
6edd964a83 | |||
f39bbff7bc | |||
b354b79b50 | |||
bcfb0732f9 | |||
febcde99fa | |||
0fbbce7a43 | |||
a98c27d974 | |||
ca3391525e | |||
a8f45a6b43 | |||
9d0b61bad5 | |||
f21e78244f | |||
fee5dea826 | |||
b84855f394 | |||
7e92d2e6b7 | |||
b91351469f | |||
c56efc0c5f | |||
5d9b1e90dc | |||
4909feddde | |||
adc0e32cff | |||
c70e07fd1f | |||
f54ba3cc1b | |||
f1989e7e1c | |||
a69e7fe297 | |||
a9b1270a5a | |||
31687efd64 | |||
69e4b62809 | |||
fd92dc0701 | |||
c9a3ba0f48 | |||
d0c65c144a | |||
686457890d | |||
a16214c614 | |||
c262bda1d3 | |||
62402457a2 | |||
5948abab7a | |||
0931195695 | |||
2cc6927d1a | |||
bff9dc26c7 | |||
2f047887d3 | |||
9220b0bbc1 | |||
16bc238f10 | |||
045919b595 | |||
6f1a89e3a9 | |||
134c6f57d5 | |||
bf07f9c3e1 | |||
c814dfbfa5 | |||
8dc079eee5 | |||
c4129071ef | |||
37c65b74e3 | |||
1c322f13e5 | |||
31c12af81f | |||
cf449ddaa9 | |||
53bd6e1642 | |||
d6e7a51d9c | |||
13447e3198 | |||
84fe0c9d3e | |||
1b78342e23 | |||
54f7e62c43 | |||
0ebe283b37 | |||
23784a2eca | |||
d8775e0e1f | |||
53bddec1d2 | |||
cb2b690471 | |||
7d154e38d1 | |||
78875d57c8 | |||
45b33c5a90 | |||
860e88c5be | |||
ebd15a7855 | |||
1dc8a0a95d | |||
fa44da16c8 | |||
56e736439b | |||
9d58f46ea5 | |||
bb2b961f93 | |||
39626a944d | |||
d1b54d6807 | |||
c930a533d1 | |||
389ed2d941 | |||
0378e55fab | |||
ca3986f31d | |||
72e65d6797 | |||
ef23fe66a0 | |||
993b3d62de | |||
5f2eb3e078 | |||
c17c33ca14 | |||
a87c5d989c | |||
7d83959be5 | |||
cc37d0a7fa | |||
6b40293c0a | |||
eba70736f1 | |||
e37799a2a5 | |||
c4964e7c9b | |||
6815acea32 | |||
b329a58416 | |||
df13e0a581 | |||
ae7f76e91f | |||
edd4b93589 | |||
97c60ed3f3 | |||
35328015b8 | |||
28be0a59cf | |||
8485ef9230 | |||
1de2d29f96 | |||
0abd218eed | |||
7f806f7687 | |||
e6a721d179 | |||
e47a9d9644 | |||
7677dc976e | |||
e7f9924b18 | |||
40586152d1 | |||
2f1f83a186 | |||
7ba426c3e6 | |||
fc016b59dc | |||
e1337dc325 | |||
534db7fe2b | |||
547e011abe | |||
9c63a471bb | |||
127d6b6441 | |||
098201d0b8 | |||
44188b9072 | |||
53fe0fa192 | |||
e3c9397717 | |||
bc10dc3ed0 | |||
5c48236f61 | |||
c90e1920f5 | |||
25ddd8718d | |||
3ed9796425 | |||
bdd031aecc | |||
798be2776d | |||
d69bd021ee | |||
26044026c9 | |||
ca5e31bc77 | |||
e9c4c61986 | |||
563a76304a | |||
c91fc49d01 | |||
a18358d484 | |||
d68955ac6d | |||
b318945680 | |||
150d3686c3 | |||
f9963d3d21 | |||
6514b8ced0 | |||
c02f2bdab0 | |||
4a1b873fad | |||
edfa35b11d | |||
a881f09b77 | |||
137549d010 | |||
5fc28e65ef | |||
1316c3e391 | |||
758062807a | |||
f98faf0702 | |||
42ea31b993 | |||
fdbb505a8a | |||
61e514bf77 | |||
7478105178 | |||
540b8c2a1a | |||
dc6a066fed | |||
ac52bfd80f | |||
27dbd2ded4 | |||
ed4826b08c | |||
689ded5c47 | |||
cd219b92a2 | |||
a31b2175dc | |||
b87da8f47c | |||
fbe748f273 | |||
4fe17923cf | |||
f59adf3fd7 | |||
14f8bcc40a | |||
bfe3efab3b | |||
ea6b316932 | |||
ef7050892e | |||
94274049d4 | |||
2a3e11d32d | |||
280cd33f2e | |||
07cdc2ff44 | |||
7af27f9617 | |||
9f8043e51e | |||
391a6fbc2a | |||
3416984cce | |||
abdd524911 | |||
e1e52c098b | |||
dd2598ccd8 | |||
b90d899408 | |||
d8b3601927 | |||
60bedb43de | |||
c5f490ba43 | |||
2e059dc916 | |||
2674eaca51 | |||
8dd3082ea3 | |||
b2dc5c2c7e | |||
2957b0b32e | |||
28db864690 | |||
28d88c5b12 | |||
c9fba3fa1f | |||
04b4035ecd | |||
608cdc4077 | |||
d29a9a99aa | |||
485c85bfe7 | |||
3118d5cebb | |||
56a9b020d4 | |||
de6774cd97 | |||
84d1f93d83 | |||
785abe5a1d | |||
27ead8c883 | |||
1caccc410a | |||
4639f449cf | |||
77604b8b18 | |||
491e1fdd2c | |||
a7c95ade2e | |||
711dbf4975 | |||
91f71d2c3f | |||
0a940211d5 | |||
fd0ba37734 | |||
6be95ae88a | |||
9d0d33f95a | |||
cf9d4662c9 | |||
be3e7db5db | |||
2c98a0f771 | |||
b09788993d | |||
e4e74ae65c | |||
c3ab20cc87 | |||
05d29a936d | |||
fd9b67537d | |||
5256457144 | |||
169cb5f270 | |||
6c7bc09f70 | |||
8efb49dd2d | |||
c066d696e8 | |||
d896e4350a | |||
486c1eda8e | |||
053b7a50e1 | |||
059e8faae2 | |||
d7ab5d44a5 | |||
65c737fc95 | |||
427860a5bd | |||
a941fb08f7 | |||
cec8b58373 | |||
b89c5bc581 | |||
7dde18b181 | |||
2be9fef86d | |||
a91ae291e4 | |||
b716d2335b | |||
6436f96fd1 | |||
efddc9069c | |||
f5159389b3 | |||
5a505975bf | |||
115ad4d062 | |||
bfbf18d983 | |||
9fc24b9c52 | |||
247479d017 | |||
57649d1839 | |||
e82a35d1fd | |||
50e922f37b | |||
3b036601cc | |||
e15e2428c5 | |||
3a801c16fa | |||
717bd23c37 | |||
d02b794af2 | |||
bb9d299b38 | |||
1bc35208df | |||
ea661fa10f | |||
c0b7bae9d3 | |||
8bc40d3f4d | |||
440fd11c72 | |||
f529236bfc | |||
5a504e6b78 | |||
a1fa2e472f | |||
eb2c15786e | |||
947bf11cb6 | |||
1aeafd31bd | |||
f443ecbfa6 | |||
8667b760f4 | |||
6abed8d996 | |||
eacc8e3803 | |||
da1272f368 | |||
0def28e594 | |||
b96784756c | |||
62005dd127 | |||
52ebb8f0dd | |||
35878c559f | |||
0c1f9dab54 | |||
1eb0162cde | |||
7c6130c2c5 | |||
df09389df8 | |||
90191ce261 | |||
19c1bd7375 | |||
84c3124292 | |||
cd90e6ed8f | |||
867c08ac84 | |||
95f984615b | |||
393b0526b4 | |||
6207b1af88 | |||
a8c34ae290 | |||
aab0c57aee | |||
c178ad476e | |||
597f79e0c7 | |||
31f48ae943 | |||
1272affe5c | |||
431ac33c26 | |||
cd2050b6e0 | |||
075011f2fe | |||
35a61b449a | |||
984b6fc487 | |||
1100c9b1e3 | |||
f3ab527688 | |||
bba0248989 | |||
bc8c194665 | |||
14fa00791e | |||
d60c7a9118 | |||
d63f3c123e | |||
8b725c77fd | |||
5458036de7 | |||
6075509f26 | |||
ee32b1bc37 | |||
6d4bd5d901 | |||
ff77230edb | |||
21b53c3143 | |||
04b3dee667 | |||
6b00b60488 | |||
bffab0f2db | |||
811d4c03bd | |||
af1119063c | |||
fcc6f2c561 | |||
c94f239536 | |||
5600a95e97 | |||
07572652ff | |||
aee176115b | |||
4ed642f921 | |||
a7b2ab771e | |||
a0277f1b3a | |||
aaa215514b | |||
b6537ad609 | |||
62e14dc529 | |||
15ab6f6ea8 | |||
dea6a4593b | |||
d38689677c | |||
a2e7ae568e | |||
bd31b01690 | |||
f7b75330e0 | |||
f7aa890ade | |||
4a36fd8203 | |||
ba6e0e11fa | |||
4ac29621f4 | |||
75187d605b | |||
5040a8e0df | |||
a4869c874b | |||
b6210be648 | |||
8e1d2fb325 | |||
bb4fd2de94 | |||
fd5cd84065 | |||
6117a7037b | |||
4d9de666c8 | |||
4ebb1a9096 | |||
9679fc94f6 | |||
076191cf9d | |||
74c0daab27 | |||
6093e28b61 | |||
ae6f549f10 | |||
74c852b160 | |||
349416ea53 | |||
f638834fcf | |||
09371a3f0b | |||
0b3e4fa090 | |||
0299d4af00 | |||
a9aef8e5e6 | |||
6fe8b85295 | |||
649d310c31 | |||
14b194ea21 | |||
758efba34b | |||
e21bf120b9 | |||
9fa57d06da | |||
9fc9704cdd | |||
39e9bb64ef | |||
a649992ccd | |||
2628631aff | |||
4b0013c7e7 | |||
5ff1eb75d0 | |||
1b20873433 | |||
36562ecaae | |||
fc764b42f6 | |||
9f688d314f | |||
150cc22532 | |||
208f3d4c65 | |||
7c4199cd1c | |||
2ebc74ddcc | |||
c7e9f86557 | |||
75cf0aeaeb | |||
decdbea7d7 | |||
01fb06a377 | |||
c9901c5fe0 | |||
5ea6dc844c | |||
b44c13bc46 | |||
6ae9686a0d | |||
4342a1eb7b | |||
13161ae5aa | |||
6b5d345a2b | |||
2450a3c5b0 | |||
34518f0f2d | |||
a251df9df4 | |||
a110ce95dc | |||
e8e57cdd73 | |||
aa3d94149f | |||
6248a5e846 | |||
9f4fa1ab0a | |||
43cca2de76 | |||
d21c7bdf90 | |||
b154f1a44f | |||
76247b7097 | |||
30ca0434a2 | |||
841f8789fd | |||
52236bd765 | |||
a5622304de | |||
074e289e62 | |||
617acf4cd6 | |||
a87ebb28e2 | |||
adbfd29fd7 | |||
33593cf8a2 | |||
00a4b2e28f | |||
7b2d8fce07 | |||
cec4b36d9b | |||
5557a5716d | |||
eafa482052 | |||
3aa204791b | |||
9b7378d132 | |||
fb9796130d | |||
e1853b33d3 | |||
4731714244 | |||
b4fe590b2d | |||
8ff65a30c7 | |||
cd0e9c9cd4 | |||
a7b8624b55 | |||
7ae74cf91d | |||
6a6396963f | |||
4319563bba | |||
e2f5d87ff7 | |||
7714d6a6eb | |||
1f2302e39e | |||
a88e6f3106 | |||
3dd9919bbd | |||
589ce31dfc | |||
e7d65ad96f | |||
af9f916a9c | |||
d348e5051f | |||
7771ef4873 | |||
7ee295ad94 | |||
0319417a1b | |||
5bf6a3af15 | |||
7a53f82516 | |||
2ee32fb02c | |||
1cf45757cd | |||
0ed6fc4f6b | |||
9c9769047d | |||
5f640c79bb | |||
0a88e7b736 | |||
711ab6d573 | |||
4e5c663b02 | |||
4efc4a5520 | |||
ce6b364dc5 | |||
ef61b81b0c | |||
225eab8f25 | |||
7c2c1a8e03 | |||
9d2d674ef8 | |||
7470ad1bd1 | |||
bffa2cb59b | |||
4f56a01b3b | |||
29f75c3c63 | |||
ea15d6646b | |||
44c171e399 | |||
4087e3115b | |||
4d4d20edb9 | |||
3b609fbae9 | |||
8427863bab | |||
db6d289d82 | |||
ec68074e69 | |||
3d6e3c2551 | |||
0366f317af | |||
8a2370750a | |||
c01f327194 | |||
5c0a9eff62 | |||
9c4ab2b2b8 | |||
5ea9c1e7fd | |||
662a585fc2 | |||
ae3713ef95 | |||
707e6f7671 | |||
a554f1c45d | |||
41b019f5f8 | |||
af2cd4d6f3 | |||
577ee3744a | |||
9dd32d658e | |||
fd3eae9623 | |||
238dfc1e17 | |||
29b56ceb40 | |||
820b30c181 | |||
cc0c30484f | |||
eb7839e0ec | |||
f600d88209 | |||
662ff47627 | |||
da6def3772 | |||
c868f40bef | |||
17af481134 | |||
b2695e46e1 | |||
b0effe8e27 | |||
794e3870c5 | |||
95c8eef97a | |||
b8c4d3e7fb | |||
aed34e1f82 | |||
5205a9e65f | |||
6e0ca7f39a | |||
43f97a951c | |||
a443ea64a1 | |||
c2a60f1624 | |||
2e9de0b169 | |||
5dbe292615 | |||
5809a02624 | |||
3525d8a394 | |||
dd9b3b4ed0 | |||
283415beab | |||
390aacd442 | |||
e166f6fe95 | |||
5a3ce87915 | |||
2acc1ad08b | |||
b9ea394c85 | |||
06f8330cfa | |||
f490565b09 | |||
d05df30a94 | |||
e1c0b1abcb | |||
b2e9da4905 | |||
be6d92c29a | |||
9179afb2a1 | |||
adb3813e85 | |||
563fffd9b0 | |||
a588d4894b | |||
dad40751d4 | |||
19274e744d | |||
608f35b4a7 | |||
457b689bf0 | |||
eaa20f661a | |||
626e1cda5f | |||
34aa1425b7 | |||
241632aaa1 | |||
06f0d6c046 | |||
d276370ba1 | |||
d9776b4112 | |||
53412a71e5 | |||
70586b668c | |||
8f985dd558 | |||
64e8f93f32 | |||
cc1d758eba | |||
045cb90a46 | |||
d6cda15879 | |||
73351ac00f | |||
5bab607f44 | |||
16bf335a4a | |||
7b3161a229 | |||
267121ee17 | |||
045cc8269f | |||
9f999dd8e4 | |||
d890c4f827 | |||
c2043ec681 | |||
0808eeaa0c | |||
bced3aaa17 | |||
105db02e07 | |||
61b6a475a6 | |||
6db9f9013d | |||
f7d46e7159 | |||
5b6d576f93 | |||
255ed69392 | |||
851b1cf013 | |||
dcd2df2486 | |||
5f15363dab | |||
a15b679494 | |||
db098650ee | |||
f7b6ff0520 | |||
df7f59b3a8 | |||
abc4ef31e2 | |||
55290b9b21 | |||
d6464633fa | |||
c83207f231 | |||
3a7b50f244 | |||
e889ec8335 | |||
cb4ff7491a | |||
5298eb0709 | |||
cb4a9a3c04 | |||
97d1844bfc | |||
193792c27f | |||
4f57990d45 | |||
9dc1d6ae81 | |||
e4f94f0678 | |||
bfbce542e6 | |||
d2458866c1 | |||
cac25fe003 | |||
309944931f | |||
63e785902f | |||
83715f06d1 | |||
b42b9fc42d | |||
39ce9d3397 | |||
effbb54f3d | |||
d1dbc973c4 | |||
feddefdc84 | |||
787d1f955f | |||
0246b2a2cb | |||
71cbb49672 | |||
67c79ba3f6 | |||
d9036c6cf3 | |||
acc2722cb8 | |||
5e49d7e624 | |||
4c2fb1f6e8 | |||
de9dc55852 | |||
013811c171 | |||
e34a29dafe | |||
9b009b3159 | |||
d4383af022 | |||
b91a966d05 | |||
958863d038 | |||
fd14460148 | |||
4df0604f09 | |||
a826f22698 | |||
7ccef08715 | |||
716ce08a93 | |||
646b9200a2 | |||
6449c3c1c6 | |||
1fba78b12a | |||
80a04b4323 | |||
41c7c57c65 | |||
f7fb5097b9 | |||
20fbbcc72d | |||
f94a2d86fb | |||
55358a39dc | |||
a2bcf71b6b | |||
18de0ceeb1 | |||
fc82700364 | |||
16ecc7e82d | |||
ed586f0b4a | |||
f66c3a21eb | |||
17eb41ff48 | |||
31e385c70d | |||
cc8a6ebf68 | |||
19408968f3 | |||
efaed076ab | |||
47e09a38e6 | |||
ffd4f06ab7 | |||
3c13f5fd4b | |||
f6cc573687 | |||
892d2b9652 | |||
8d538ff42e | |||
63141ab9ab | |||
6a4a8a60ab | |||
7ec4da40ce | |||
4fd9cc26d5 | |||
1926335b85 | |||
12dd44f7f6 | |||
2daf2eedb6 | |||
2ab8c59ad5 | |||
0653b82048 | |||
77e8304fc4 | |||
8aec215ca0 | |||
f91c087c46 | |||
39a6f85e95 | |||
3dfb7d406b | |||
8810f53435 | |||
998c7c2e03 | |||
5e013c4aef | |||
8dd6c4680b | |||
28a29f5557 | |||
f3da37c92f | |||
3b9c08676a | |||
a8bdb693b9 | |||
5a59e8be82 | |||
26a064ce87 | |||
70f6a46f1c | |||
e36966b83c | |||
f14b212dc9 | |||
6d13cf9b8f | |||
841aa1af5b | |||
2d4f331c63 | |||
86bda288bd | |||
3d38ec8aac | |||
ef88e0f804 | |||
8302afffb4 | |||
67b9414268 | |||
d8c5ab232c | |||
c320240086 | |||
15164a8e6c | |||
4ec4dcabe9 | |||
e9ad100b1f | |||
b025f94351 | |||
df8e15cab7 | |||
855cb16cc7 | |||
5ebeaf7c9b | |||
9d42b52d2c | |||
34b91c62c5 | |||
4bffd97edd | |||
be954115f8 | |||
2384082b5c | |||
2a126f72f3 | |||
896add7d77 | |||
337ce21149 | |||
d78261695b | |||
ad3b9cf232 | |||
34deda594f | |||
f6108c54ec | |||
687e7b565f | |||
ddde7117a7 | |||
44c303aad2 | |||
53d0861372 | |||
696edde17c | |||
3ff321475d | |||
d43bd9b4ca | |||
79994b2abf | |||
7736964a37 | |||
2fea0c2602 | |||
5c9613e084 | |||
01cdd31339 | |||
44a991e245 | |||
46f751bd2f | |||
358908e605 | |||
6532171997 | |||
b9cf945b30 | |||
5b8ce1e42a | |||
7c7888de4f | |||
42e1b07705 | |||
60ce884671 | |||
9934b3ec7f | |||
12a8064c27 | |||
ad1bd5fc11 | |||
fc7068550c | |||
a8028b87c4 | |||
78f11f6333 | |||
3791c4a682 | |||
ecf6ba3974 | |||
b29b045d78 | |||
c349bbbc08 | |||
e916836261 | |||
4415855683 | |||
cebd670a8e | |||
b8be4bfaaf | |||
6c3c6060a5 | |||
46dd5fcbb0 | |||
0f54ed0306 | |||
9619636ba7 | |||
fa2c6791b4 | |||
ad16e9d910 | |||
7de447e4b5 | |||
36eb9d392d | |||
de37729823 | |||
e1a7e0329c | |||
76e1f863a2 | |||
d49bc438e8 | |||
f93cd9ced7 | |||
0f4eb1b524 | |||
3468f7cfd5 | |||
be07390859 | |||
551d9a1688 | |||
ac3f5106e4 | |||
37b042b361 | |||
465f7c95b0 | |||
69926dd002 | |||
e41d7451bf | |||
3bb27deecc | |||
a34d4c6a5f | |||
02d9e18279 | |||
8536df16d9 | |||
a94f051d43 | |||
78200868f4 | |||
256b2dc9b7 | |||
51285666d8 | |||
557d309377 | |||
4ba4427510 | |||
9f576b0233 | |||
343dcfa0c0 | |||
457eb5d69c | |||
5863f50316 | |||
8ed22ce6e7 | |||
10437ab85c | |||
38a5a2a955 | |||
56e88058f1 | |||
5f6b7ffadb | |||
6d2345accb | |||
cc2a2e4bbc | |||
e72305e685 | |||
c2279dd651 | |||
9cc1cd29ed | |||
894af28529 | |||
bf4b75ee9c | |||
21f60c5dce | |||
aeef19e2a6 | |||
64ffd9e99c | |||
944ccc9a94 | |||
9262727ae1 | |||
3963e0ab39 | |||
d2a3b76a71 | |||
377e3ac962 | |||
a191c89193 | |||
5725f71777 | |||
88a5b8da0f | |||
92da5430e7 | |||
50eee42668 | |||
d07b9181fe | |||
5f0a0fd8d2 | |||
a205807191 | |||
b039ec3da3 | |||
5ee9630be1 | |||
c4044102d6 | |||
215c4aa8fb | |||
3871f89119 | |||
d853d19dd7 | |||
5d403966d5 | |||
20acb86ca2 | |||
e8e430e630 | |||
85ec34d1d9 | |||
a9ce454b21 | |||
b6146394ae | |||
764726d78e | |||
65344fcac9 | |||
ebb3236ad5 | |||
9d44ae3d32 | |||
d2d0715568 | |||
b986c54079 | |||
8336881a85 | |||
b0d27ee896 | |||
9ba2ab5cea | |||
1c9be9b5aa | |||
49997ca932 | |||
195c5c21d4 | |||
a0b240884b | |||
9afcb00216 | |||
bde6416b40 | |||
06487237e5 | |||
964884e761 | |||
09e0b0ac6f | |||
984e7b8e17 | |||
abb3bd266b | |||
298f1fb6a6 | |||
cef51a7e0d | |||
ddb62feae6 | |||
fde026a9e4 | |||
78a8ba2307 | |||
ffc63fc6d6 | |||
9757c137db | |||
0b59e664ec | |||
104302a958 | |||
ba2c077b01 | |||
94733069a4 | |||
cba388bb65 | |||
efbd8fca4c | |||
6b38d249c5 | |||
abb0e279a5 | |||
d191ec4c33 | |||
873b6da120 | |||
f0e7f13f30 | |||
ccfadb9b47 | |||
8dc509f688 | |||
72e0b8f7dc | |||
b5c4d8ba79 | |||
5c95b376b5 | |||
f2d3bdb801 | |||
3b9411cbeb | |||
16eb8ced58 | |||
63a94ee941 | |||
ddcfd465ad | |||
3b4965279c | |||
914ca88e5d | |||
675cb87c76 | |||
53df0d8b3f | |||
8a7a783ff2 | |||
e68c978202 | |||
272ad61ab1 | |||
5f7d4faa88 | |||
235dec26fc | |||
52da220016 | |||
cbfc9cb344 | |||
ed81cb94b0 | |||
1f54e64fcf | |||
20cf61756a | |||
ea6673947c | |||
5e6317fecc | |||
823fa4689e | |||
6c9e712c34 | |||
4845583dcf | |||
8b655c7be3 | |||
a06f48e357 | |||
841206c678 | |||
296851797b | |||
ee5df00146 | |||
89a0f2457d | |||
26d2ea8afc | |||
2686316c90 | |||
83b69e8edc | |||
35a83b495a | |||
dfe0130753 | |||
2fcb4cb769 | |||
da4bcd5d91 | |||
512340e39b | |||
284dc67076 | |||
38945955ab | |||
b7837389d7 | |||
5c328adb4b | |||
60af19f0e1 | |||
1d65b38b28 | |||
64ebf278c0 | |||
416fd085b1 | |||
839edaa15b | |||
ac311911c0 | |||
aa480fee72 | |||
b6ee20846b | |||
b5fb05b735 | |||
7b3cca20d2 | |||
8f5360c387 | |||
ed25a29cc8 | |||
a7a1851c0f | |||
f2f4b905e5 | |||
08dbe87819 | |||
218b037d98 | |||
2150a8f9d1 | |||
720a3c8edd | |||
585ea5d600 | |||
5b5d31fa9a | |||
02b7e61ef7 | |||
280d8f3148 | |||
5a405011de | |||
2374e16104 | |||
561066f899 | |||
903a0f0513 | |||
f83289b1a0 | |||
77d3668432 | |||
dfa5103b1d | |||
1f692ae263 | |||
1562bc91ba | |||
6bd95c1455 | |||
4f5e405676 | |||
86eb46af09 | |||
6651aab11f | |||
5a8b1bcaec | |||
ac6227e434 | |||
96e34c1d36 | |||
4038150246 | |||
24eabb9bb1 | |||
574bbea747 | |||
a1c53eec6b | |||
84463cf0bd | |||
2dcf714d2b | |||
06da60f4b7 | |||
ff1b110ae1 | |||
748c2d6c97 | |||
339071cb07 | |||
a37de36fa6 | |||
cf6ffd5469 | |||
d40ff0bb89 | |||
c4296285f3 | |||
106a28b8dc | |||
bd498977bd | |||
7c52bc9768 | |||
643c71740e | |||
40a3cd2ab1 | |||
3db0ae1dac | |||
07b9be798c | |||
b4a062983b | |||
f11f4e0b45 | |||
450d3630cc | |||
166688348a | |||
39ad50657e | |||
a62a6ba40a | |||
0bb78b7ef4 | |||
861be30021 | |||
27aa9187f0 | |||
c58b0ff787 | |||
392de4af67 | |||
c20a5d65d8 | |||
4422819754 | |||
6eaa09ac20 | |||
c0adae69ac | |||
cfedc77ce1 | |||
96eefdfebc | |||
7bf7ec6d9c | |||
60f38eab78 | |||
209aefee57 | |||
be79942ebd | |||
1beaf81e98 | |||
12e4c738c9 | |||
8822460858 | |||
53788ef827 | |||
b8e82e4db3 | |||
94690ec5b0 | |||
77875a270d | |||
6d272cc5f9 | |||
6d280ea31f | |||
7354206c74 | |||
39b0286d6b | |||
dad9338c82 | |||
f6da89f74f | |||
3437d56904 | |||
3c58878b19 | |||
c5cb7009ca | |||
adc27398fd | |||
dd06a871b7 | |||
014b6cb397 | |||
d44827a4c5 | |||
3cda7128d0 | |||
70bc485755 | |||
0a40024995 | |||
985627bd65 | |||
a9ec6b9064 | |||
f5864afdbb | |||
21e2f3c1db | |||
7b94bbf3e4 | |||
71ea19902a | |||
9e7363f686 | |||
2768158eaf | |||
f8fa47e939 | |||
d4ded1a60d | |||
4e76cac5b7 | |||
0dbdd5cd3c | |||
c08403935f | |||
4893002408 | |||
29095766e6 | |||
eee2146735 | |||
5c21af95c7 | |||
cb6fc9c7cb | |||
68a581a04c | |||
7b834e02ec | |||
8e960d4052 | |||
34acef58e7 | |||
c1ee943533 | |||
f7d7789915 | |||
9c19eb906b | |||
73b7d99dc4 | |||
192cf9ddf5 | |||
d894aa9101 | |||
aae5a4cece | |||
16e3d7e96e | |||
e40ff36832 | |||
c5f8c9586f | |||
4cfe92c47a | |||
9d2776183a | |||
2faa89852b | |||
d84993faf1 | |||
a9efc48e71 | |||
8543c347a8 | |||
1d4502944c | |||
448ca384cc | |||
d426af741c | |||
6ab2a871ce | |||
2c9951273a | |||
6fac901151 | |||
74b311a472 | |||
81d298dc6b | |||
35597a8349 | |||
45cbc430e8 | |||
03fc7fe8c2 | |||
8a91d71625 | |||
4dc6d748a9 | |||
99587a9907 | |||
eebd736cfe | |||
bb50cda181 | |||
05c4fb2fac | |||
448264be39 | |||
78fdf9a11f | |||
71bb4b3ee5 | |||
a2bb81c406 | |||
30bd2a3fc7 | |||
7cbaf1076f | |||
a8b57256c8 | |||
329a6e00dc | |||
c83a3f3372 | |||
0906ee8a4e | |||
23cd385f20 | |||
45b10a1f0f | |||
469afda53e | |||
c2bbda02a1 | |||
e744409cb9 | |||
0a8b3816f7 | |||
bc21aa0124 | |||
2577f5eebf | |||
f575ba60fb | |||
5b5de6662f | |||
a8b75c3d41 | |||
19d8b221b4 | |||
345fa521dd | |||
16493e9769 | |||
dbbb7385f5 | |||
3a7c9e4c62 | |||
408618b836 | |||
771c0170d9 | |||
21b988f554 | |||
1438922ffb | |||
f1e4292072 | |||
fd46b49ea6 | |||
46502e4d61 | |||
b44b06c2c9 | |||
5ec67ee2a7 | |||
61b7703406 | |||
49dc819d23 | |||
03c8e7428f | |||
70792c744d | |||
fdf226ab69 | |||
bd65b63c65 | |||
09226cdd75 | |||
3c2b165de1 | |||
76f63bc6a5 | |||
3531bb7118 | |||
55e8dca8de | |||
820c4b9b16 | |||
fdffcaba9b | |||
a9e7c90960 | |||
5a86f85936 | |||
8ecb632d70 | |||
8ad4ad57d1 | |||
854b5b7da8 | |||
231962aaf7 | |||
51e6f33d32 | |||
476988876c | |||
c3d61bc63c | |||
6f4a39c337 | |||
a472eacc07 | |||
078475a082 | |||
de18da2a0d | |||
6d760666a9 | |||
b2a0be87e8 | |||
4c8ea12903 | |||
e94270946a | |||
40d21b808d | |||
095def3845 | |||
153660fe7b | |||
3dd05ef7db | |||
cfc18b5a6f | |||
57496926ca | |||
19e4ee81b9 | |||
f74d97e1f1 | |||
011fab37af | |||
8296dcec09 | |||
3df8363a94 | |||
5cc84ed4bb | |||
2f08ed8d3e | |||
1386977a34 | |||
cdb6c9cda2 | |||
13b1d85058 | |||
c6409cb624 | |||
573c047d50 | |||
f42382db3b | |||
762a94f2cd | |||
5b597de18c | |||
4d28167bc0 | |||
61c73576c8 | |||
116b64de25 | |||
b785503543 | |||
fc8f4688c7 | |||
3f6dd6cd42 | |||
2147ce45c2 | |||
c701664e07 | |||
a4915ad634 | |||
fe3a55966d | |||
f1e8176995 | |||
621604dc66 | |||
5654f2f4e2 | |||
b1231593b6 | |||
b1df54501a | |||
d449ea5ca4 | |||
583c5ffcb5 | |||
7879761a41 | |||
f7dfd2325d | |||
b03560b670 | |||
f25e43fab8 | |||
903ff9047f | |||
66ec4d1f5c | |||
93055f78ea | |||
33500e986b | |||
b26f99787e | |||
9d66b5b09e | |||
8bdca5c03e | |||
ccb41632c7 | |||
cd532b00d4 | |||
81abc39929 | |||
b4cde697b5 | |||
7531b48d02 | |||
2bc1217409 | |||
b73ba68215 | |||
e1e7912ab2 | |||
e988f59c08 | |||
3810e4bed3 | |||
27233cff31 | |||
34993f7691 | |||
7dc1dff816 | |||
5677bf73ca | |||
97ef1c27df | |||
04baa46efe | |||
4bdc91892a | |||
b3a763a718 | |||
7ee6963f5d | |||
1eab4f5f07 | |||
cf103de4a7 | |||
a9a552c112 | |||
f5f85bb528 | |||
bdfef4ed16 | |||
4d80ce5b4a | |||
09bb114a4d | |||
3bf8c18c56 | |||
45994a53ce | |||
875db11822 | |||
2e4a2a0e5a | |||
9fa7d38133 | |||
927454c8fa | |||
0e28297e68 | |||
1eebceab27 | |||
9a70f84e60 | |||
8b3efdf229 | |||
1427d73b66 | |||
62589293aa | |||
749d043258 | |||
a6210466c7 | |||
71c65b47f9 | |||
0ed5dd0d7b | |||
b716046b97 | |||
3143d188ae | |||
b54e7214f0 | |||
d6dadc6efc | |||
546a8f9218 | |||
fe49a7fc40 | |||
447926dc08 | |||
258da88765 | |||
e79dd6aa2d | |||
2c37cc5fcb | |||
206c9bdd74 | |||
4264bd3bd2 | |||
ae5cd51f50 | |||
df877a7d5b | |||
4572157c49 | |||
6596c72131 | |||
f1f578436b | |||
f827e1532e | |||
bab271fcb4 | |||
0792f1a7a1 | |||
ac50ffca5e | |||
caa252e57b | |||
d5edc748d2 | |||
718fa35167 | |||
c177d889a2 | |||
3f7ebde037 | |||
4656c6f5cf | |||
e0fb50cc3c | |||
7d9f5d7538 | |||
2ac8ebd3ef | |||
871267d578 | |||
d050ce20a9 | |||
6c933a4485 | |||
c33e3be735 | |||
3ab8a0c438 | |||
12a427e158 | |||
0052c6b120 | |||
65a767d9b0 | |||
0e945e465d | |||
72257ec87d | |||
e5405e4ba2 | |||
b60d714acf | |||
edf5053bf0 | |||
3869818d8f | |||
abc1580fa9 | |||
286a249a9a | |||
d828664d0c | |||
355ced92eb | |||
9e1158de4f | |||
569766fa8b | |||
e987ac4034 | |||
c2efa23e94 | |||
d2774421e8 | |||
8681f79182 | |||
b10d7a2e51 | |||
a56d33d7ca | |||
2b45bd2a63 | |||
7986e7ce7e | |||
311b47720b | |||
582551bea9 | |||
19a0349681 | |||
883b506445 | |||
d381c5fc8a | |||
ad506a7aaa | |||
ef3cc8e6eb | |||
561b78a5b3 | |||
a7ea2e5566 | |||
1c94c32f4d | |||
d5ace7a562 | |||
2ed251a5db | |||
8d0d05c65f | |||
ac24a301bd | |||
ba440a04d1 | |||
cd65fc2a5e | |||
e69af1a3cd | |||
d1393b0581 | |||
46bb4e37ba | |||
3a8e1661fa | |||
0598226e24 | |||
0b50258814 | |||
600d53c68e | |||
f0e962c55e | |||
73a939e76c | |||
dcdd73065a | |||
34eaf65a79 | |||
27e710019c | |||
c2c361efcf | |||
f020a5cdea | |||
530e742628 | |||
a90063a827 | |||
de05d1bf46 | |||
1fb948461e | |||
27c050be86 | |||
f66ce096d8 | |||
2335075506 | |||
b3fc357a15 | |||
b3d98cba77 | |||
146dbf1270 | |||
55bf0e554f | |||
fa7da0ca5d | |||
d49459750a | |||
d6b56c2380 | |||
7fc1ee67d1 | |||
3e6503789f | |||
8bab6dd239 | |||
a9008eecba | |||
73b3ed18c1 | |||
a93ec73e72 | |||
9a290f0c22 | |||
5de916ecd0 | |||
44891996b5 | |||
bc585f2724 | |||
d629ed7d5b | |||
8c66a25270 | |||
82e8e8c638 | |||
27ad984626 | |||
1f04f70eda | |||
eea989bef8 | |||
d6cef88dd8 | |||
da4de21f28 | |||
eb0fd7967c | |||
56245c6aa2 | |||
ab3f2365fd | |||
66d0e4e656 | |||
0f7dd62f16 | |||
c4e10ea9ac | |||
f1cf5298d8 | |||
22d3943831 | |||
b688dee4c8 | |||
71e0f89594 | |||
5a21dc5340 | |||
d037c082fb | |||
9c768501c4 | |||
b50edfd1f3 | |||
dd7910347a | |||
65769699b0 | |||
8b685466f5 | |||
91d9e8d649 | |||
746efe7eba | |||
ecb2bd0cbe | |||
7e8a2b9cec | |||
1f7296c093 | |||
d1f7900eeb | |||
393f703a97 | |||
7a7b3a6cb9 | |||
0949a4b045 | |||
7a4a3c850f | |||
8a5cf8f6bd | |||
aeb17d8d44 | |||
85d6ae38b9 | |||
d3dda614dd | |||
1c8a58963c | |||
19a9dc67bd | |||
a0e0f3123b | |||
b15474c6f2 | |||
356c927d12 | |||
b89c0672e6 | |||
0a2f6ddc64 | |||
3ea655918e | |||
3875f02a52 | |||
06aaa0c50e | |||
8c993dca03 | |||
2c11205b96 | |||
d800d2f5d7 | |||
24646e7eb8 | |||
6149ce28a7 | |||
c8bdacb195 | |||
5c9e53a25e | |||
ba9fecd068 | |||
2c3c235969 | |||
7b2f757b2b | |||
a67f2314f9 | |||
0a51ccbd68 | |||
2932377769 | |||
e5de1f771a | |||
b48f000657 | |||
d8929c1d73 | |||
92ffc465d6 | |||
c1a494bc37 | |||
783654e6a3 | |||
dee0e008f5 | |||
d7b9345b6d | |||
f158fbd131 | |||
1c4d233fe7 | |||
d575915d7a | |||
ed9d9d5096 | |||
2d2ae9b8d8 | |||
fa7a3e3449 | |||
a057789235 | |||
20a8f0dbe5 | |||
ad7aca631d | |||
c899b0a74c | |||
5ba5da5d25 | |||
4d1ed509e3 | |||
85b8a15374 | |||
920982c4e8 | |||
254e58c28f | |||
f9d72bd85b | |||
b8ef20e353 | |||
c8ef5b5811 | |||
22f4cd26ae | |||
aadaa20706 | |||
f2ef90b240 | |||
f80f97253c | |||
ee8da36d08 | |||
9d4111d69d | |||
180e617866 | |||
bc798b182d | |||
941362014b | |||
dfd30910aa | |||
be7ac9fd41 | |||
35e882e74f | |||
58b38c9201 | |||
ed3af5f751 | |||
5beaf6d735 | |||
b0e2ebda70 | |||
cd21df3572 | |||
c7e48350d3 | |||
6af41a4543 | |||
f9eb8a44d1 | |||
d43394f7b7 | |||
dcc4bc2735 | |||
5dee8e26cc | |||
df6acedd25 | |||
ffd1ac425e | |||
edd01615c3 | |||
9700e80698 | |||
cd735c4837 | |||
f93aae4802 | |||
b2c66949b2 | |||
eb3586d777 | |||
5b5ffe75d0 | |||
e68e69e7e5 | |||
70ffd267f8 | |||
b68e561c0f | |||
93596dff3f | |||
ea27704ea9 | |||
35589a6b3c | |||
598a75ec1c | |||
cdfb635737 | |||
37fceda7e8 | |||
2d499de2bd | |||
91c75f99fe | |||
6e38515402 | |||
d599fd3434 | |||
b2e6ad85ea | |||
d8e2795368 | |||
7a41b19e58 | |||
bc9e482b39 | |||
cab1d0ef0f | |||
0c282e826a | |||
8112b0baa7 | |||
c34cb01404 | |||
f1541e65b3 | |||
9bad70be5e | |||
5bfcca2d5b | |||
73d152506b | |||
3154cea0bf | |||
ac3e624d0f | |||
f065a2ecb7 | |||
a46df6f829 | |||
98fcf8c6ef | |||
da60381c89 | |||
7d32879929 | |||
d64cc8d87d | |||
cebf69933c | |||
c3ae34f066 | |||
4f581671dc | |||
5a542d8ba8 | |||
dd23bab3ad | |||
14d28d7473 | |||
992293a196 | |||
9908def857 | |||
552d1ed61b | |||
5782f063f1 | |||
4ae7df27d2 | |||
c3c2ad1454 | |||
c51aef9f7d | |||
bbfb4e1dcc | |||
e0fbd4b624 | |||
8e3bf3907a | |||
21dcfc89e9 | |||
9613772455 | |||
f3d741854a | |||
c4ecbf0a7f | |||
13466604f9 | |||
cdc7b03e67 | |||
e372cc779d | |||
6834c4992d | |||
1cf807c319 | |||
833048f310 | |||
38e5c3f918 | |||
b4e82b8bc7 | |||
db3d5d4941 | |||
a6e7123995 | |||
1c2abbc61d | |||
7648bb8ee3 | |||
35197acc1a | |||
6622826587 | |||
4fe919335c | |||
a858f6ac42 | |||
cee26826d7 | |||
e89fe0a9ff | |||
d10bbf0cbc | |||
05d02fa90b | |||
796fc66771 | |||
6cafaba993 | |||
60b97b27fa | |||
355ab5b3a6 | |||
ca09701343 | |||
4f27611ae6 | |||
24e647e0f7 | |||
9cd510abaa | |||
d07ed581a9 | |||
5ab92ce844 | |||
76797dfbd4 | |||
591f742d42 | |||
20953ed492 | |||
f3b49378e4 | |||
47b6b05017 | |||
f9745327e6 | |||
659adf83dc | |||
a187c782aa | |||
950f2a38cd | |||
f2371487a1 | |||
6ca81fb98c | |||
af35ab56a3 | |||
15dab7c5b2 | |||
37f8fd6551 | |||
f04b606bb0 | |||
2ccc65d7fd | |||
7501ad11ca | |||
331a051e75 | |||
92f1af86d8 | |||
a6cb86bab3 | |||
76beaa2097 | |||
94272af45b | |||
ad95601e3c | |||
17c6d6a92d | |||
633cf63682 | |||
92d565848b | |||
617d693102 | |||
4530b93a6e | |||
dc45559c17 | |||
efab03274f | |||
f2e2ce15cd | |||
ddd5a235c3 | |||
2cc2196140 | |||
65cbcb2f73 | |||
002101521c | |||
902759e1c7 | |||
c564475251 | |||
4cd29f791f | |||
3eff7be9a6 | |||
e7e82cbee6 | |||
73bce40287 | |||
5fc23caef7 | |||
1a4d23742b | |||
8923103c3b | |||
f34f8df319 | |||
21568106b1 | |||
363b9ba415 | |||
0409b4ca49 | |||
7611f92f5b | |||
7aa9751054 | |||
77b52d65c7 | |||
5df56b47d6 | |||
1eefde7f0d | |||
44b31f326b | |||
b5431e4cc0 | |||
83e99fc72d | |||
cd6175827f | |||
e77710a372 | |||
b6e95bb96e | |||
cd95e078fe | |||
548f3dd5cc | |||
d5195d4097 | |||
fda8b1d87c | |||
7140c9cc34 | |||
4d338a4f5c | |||
6a6b43de07 | |||
309ef0f354 | |||
81fc657356 | |||
29c72abcc4 | |||
79f3f3b456 | |||
d1b35f9174 | |||
f3dd9b5b31 | |||
72736a1b09 | |||
a418397174 | |||
ab8eb4f652 | |||
8d081ea7af | |||
d5c528ac2b | |||
7141c15e65 | |||
5357b1548a | |||
928ec1c5f8 | |||
dc8dac7c35 | |||
c593dfc26c | |||
6b31d82263 | |||
4ee3fdaf7f | |||
41ae8e76f0 | |||
8a52375fb8 | |||
87b3b718e3 | |||
46eeee6b5e | |||
529805508a | |||
851797aecb | |||
13d0815839 | |||
dc6e7eb19b | |||
e5419febe4 | |||
69b75b7fd8 | |||
4eb8c9b2dd | |||
827841ec5b | |||
0a50a3f564 | |||
ce9271739f | |||
2621d6be8b | |||
d76a2ee9c9 | |||
b2596dd302 | |||
4d0973d7ba | |||
1afdb3cbb1 | |||
53694eb64a | |||
31a3a19dac | |||
a50b8a2694 | |||
9e8108ee14 | |||
d53c898499 | |||
552985e305 | |||
20e874d3c6 | |||
471a1b6d12 | |||
f999d5a156 | |||
f74d7727ca | |||
3baf815d76 | |||
96cadcc29e | |||
31b6687894 | |||
381d4cb30a | |||
5030ffb01c | |||
9ce0870f6c | |||
246151b2f9 | |||
83f1856d6a | |||
c280fe816c | |||
b071b66b45 | |||
fde65c7e88 | |||
bae6b91e7d | |||
2b714df64e | |||
c7572ac1f9 | |||
ec3a78289f | |||
f303f0c17a | |||
f543834be9 | |||
6bef1c4169 | |||
652ed0cf6d | |||
559f54e92b | |||
17e1d7f117 | |||
5fa54a92bc | |||
ba7956f521 | |||
c2fa4b7191 | |||
d32f58926d | |||
6a0fe93ba9 | |||
1fae8d6377 | |||
dc060e8b64 | |||
b746e0c9f0 | |||
e67b7e87b2 | |||
0a0b84a07d | |||
927b4d01a9 | |||
5035a42287 | |||
40150379ae | |||
1d24e2cf23 | |||
9e36539052 | |||
0602f68ae3 | |||
2b60d1bae1 | |||
0b43e3cf32 | |||
c9d636aa11 | |||
be88cc7697 | |||
ba07f39347 | |||
4c8e11a577 | |||
3d6c44e2a7 | |||
c60091b949 | |||
a504fa835e | |||
8811337622 | |||
921fb9f2ce | |||
e93b5a1d5b | |||
db7a1f19ba | |||
ef27919f7f | |||
c571b2693e | |||
8bcfb2d465 | |||
93f464a145 | |||
95b7896d9b | |||
ad26bed0ed | |||
62a95823e0 | |||
c8d83dba7d | |||
22f5925202 | |||
cd52d8a3be | |||
a9d6fd9afa | |||
5c53cf6486 | |||
74882c6c38 | |||
c8947d77bf | |||
4f3acdb004 | |||
6404dd8293 | |||
f19970a481 | |||
6f0631c978 | |||
e5d06e479a | |||
d523613329 | |||
cfcae6b293 | |||
000a8e25a2 | |||
8a3b0b366f | |||
383f0a1f30 | |||
e323c07ab9 | |||
f9908cd436 | |||
24bc4b66d0 | |||
2351896cc0 | |||
307011a96c | |||
6f3368ef16 | |||
cdf791f0c5 | |||
75578f41e7 | |||
ffb219fb91 | |||
eb2784eb81 | |||
28ee0612cb | |||
a80921b45d | |||
0db88f34b8 | |||
35f0ee510a | |||
d7df853bde | |||
0387221da8 | |||
c39c8ebcd0 | |||
5d2af54730 | |||
a9be2ebf1b | |||
ec2d8cc2c8 | |||
05d66bba3f | |||
b14417498a | |||
05becf8431 | |||
160c38b5ca | |||
9b0fa0dedc | |||
533c64d4ea | |||
c1157d62a8 | |||
7b1e9286d8 | |||
01fb8e6635 | |||
9d90128463 | |||
34cfc9f474 | |||
ebe1e73b1a | |||
8ce0a67c81 | |||
c065fb1422 | |||
cda35101df | |||
c32dbad747 | |||
30b6542fc8 | |||
2b6a653050 | |||
34d75e8918 | |||
2c25055828 | |||
96f629d441 | |||
a2770c8a52 | |||
4a3fd5e855 | |||
608017776e | |||
0c7f05f56a | |||
c6335c128e | |||
fb42d5908e | |||
8609543ad0 | |||
f83f1ee0ce | |||
1db6870a81 | |||
c19c69f336 | |||
b390f441a1 | |||
79f564be46 | |||
23d59df81a | |||
ef3e12e803 | |||
5fe88d63ef | |||
0f3a8f369a | |||
26d5d17ebe | |||
bb7ffce7eb | |||
551586ced0 | |||
1dc8ba6920 | |||
d773b6a00a | |||
f6cd26b0a6 | |||
5a52c0b71d | |||
662da0d728 | |||
df59e969cf | |||
d27e5512c0 | |||
d48fae3566 | |||
3525c9c074 | |||
05774f6c8a | |||
16447ce75c | |||
15f1eb28a2 | |||
e50f537667 | |||
ed8364741b | |||
6c1cb089b5 | |||
4b98ed114e | |||
d308e55e12 | |||
10bc7e948c | |||
9988471fb8 | |||
05fa9bc9fb | |||
57b88ec2d6 | |||
b1c9bf14b2 | |||
588fbfd848 | |||
b2a24e021f | |||
661a04798e | |||
665ccafd73 | |||
f35dbb99b5 | |||
a393f84fa4 | |||
92c2c33a84 | |||
9802debf71 | |||
2287938f5a | |||
5103f080e9 | |||
1f20ef9787 | |||
1ad6558229 | |||
d61a0dfa22 | |||
ac510b67cc | |||
5ed091e260 | |||
cc2c8f6b00 | |||
c28952c707 | |||
30c3e5a84e | |||
2ff3873881 | |||
aec51d616b | |||
c5996529c3 | |||
00c3693daa | |||
fed86fc8ac | |||
705ee46f31 | |||
f210c41c1f | |||
863eb3c559 | |||
b6b52e62b2 | |||
dd9b08cce8 | |||
e61d82b9be | |||
aabc898f3b | |||
bdeac30a96 | |||
4afd2b4138 | |||
dee4ecbb3f | |||
4210b0e66a | |||
2d6c44b54a | |||
c45283216f | |||
826af401a9 | |||
28c2b8f432 | |||
c9ab8e4be8 | |||
1054f6a9ab | |||
f6eeb9aa66 | |||
91ccc9af98 | |||
ec90fcd290 | |||
a664f5a6de | |||
7643d979c7 | |||
d18463dcdc | |||
f9f917bfa4 | |||
e89bf01c2b | |||
d04a515eb0 | |||
0ae89ac096 | |||
6ec5d5daaf | |||
62b1a08f06 | |||
c54f5e0ba2 | |||
37a8f1037e | |||
4ba81bf3eb | |||
c204835969 | |||
ac28ac324d | |||
8aa3fcfb63 | |||
1beadb8607 | |||
bd8724e652 | |||
73d15edef5 | |||
adaa157317 | |||
791caf0037 | |||
8ab773538b | |||
5c88f662cd | |||
cd7aef2139 | |||
50c6efa187 | |||
302c5d5005 | |||
b6b9ede425 | |||
118f0520a2 | |||
ba80bd43ad | |||
ed6298c33f | |||
db5486a347 | |||
b9b58f7ed9 | |||
33f5aafd6c | |||
4b34ef9036 | |||
8c409e9251 | |||
398e70ad39 | |||
9407c12923 | |||
a4693ef679 | |||
9d5f760597 | |||
8bebcfb844 | |||
8a0eb08745 | |||
1dce4699de | |||
7bff919782 | |||
c6dc78183d | |||
9a72f19b97 | |||
25a952755e | |||
b2da2978ee | |||
8b9400ad92 | |||
3571450b42 | |||
72bb5bdd5a | |||
04a9eb8820 | |||
0f002a5b18 | |||
b066b8d15a | |||
7b511462af | |||
3a53f67911 | |||
155b1e2b35 | |||
aad5795408 | |||
83b97c485b | |||
5db89071d4 | |||
c29ab86d85 | |||
6b02cb9b44 | |||
88c607da03 | |||
f9fd4926ef | |||
986038242a | |||
8e84f8a1c4 | |||
edfbc25768 | |||
05a1c6c183 | |||
534cbb4bf5 | |||
d9ceb42bfe | |||
8d6943227d | |||
3011cd86bd | |||
cfba38b462 | |||
11e4385173 | |||
ad29b12cde | |||
842459aa46 | |||
b033416a45 | |||
7310b09a1a | |||
bb2eda2d15 | |||
0114cd97b6 | |||
fc13cdab3a | |||
3644036693 | |||
c397297eef | |||
1eea2b254e | |||
0e04467b8a | |||
9fbb3adbe2 | |||
b6f29b4448 | |||
421d8916a6 | |||
a38a0d6f87 | |||
7a4a635399 | |||
557d54b3de | |||
c47902a471 | |||
25cd6e4321 | |||
6ad5fa0d9d | |||
666336be1a | |||
77bf90dff1 | |||
8ad0205948 | |||
7ff17db113 | |||
1d11fdecdc | |||
b1ef30aa20 | |||
28659efa69 | |||
6c59894a29 | |||
47b8b48ee7 | |||
3969009fe7 | |||
ecb068019b | |||
5114411749 | |||
08f21dbf51 | |||
d8c7c274e4 | |||
fadabf79e3 | |||
23cec1e8e2 | |||
c36ea0221e | |||
685a6507b6 | |||
846354473d | |||
390cfb793b | |||
17392f663f | |||
8b6fa1cf19 | |||
909233f724 | |||
0e82970a29 | |||
cdbb2473bb | |||
c20060d259 | |||
38926f7123 | |||
0efd89ae5d | |||
718d2ae2ee | |||
af9dcad8e3 | |||
772b529a8e | |||
111fa60a93 | |||
e9f236b70f | |||
78d3f62b6a | |||
d310a9c0b4 | |||
7dc524ed58 | |||
032f8b7840 | |||
4f2b9a4c28 | |||
1ac7bb3bb8 | |||
f302f70330 | |||
555dd93ed9 | |||
96b0a1c75e | |||
c8a0ed40bd | |||
e11c20541a | |||
c75e216871 | |||
fd1d60f03b | |||
e8a6c95e2a | |||
358a6750ed | |||
4320859e1b | |||
98e7a38e50 | |||
229e770a1d | |||
5036086fb3 | |||
97d24563f4 | |||
655ed851f0 | |||
f8f79dc76c | |||
a574154108 | |||
7f976381d5 | |||
ac80df0959 | |||
aff85b5037 | |||
5691063ba0 | |||
7498758584 | |||
92d6aa1f32 | |||
3256ff1c73 | |||
f9c1de46b3 | |||
a9ce0f7afb | |||
1a4ab2c57a | |||
77d1fc149a | |||
c2a42d5d2b | |||
01d5c29513 | |||
7844e3a275 | |||
a5638a940c | |||
4665726f48 | |||
e8ad0d1776 | |||
28022f472d | |||
4f3433b5bd | |||
2185e7cee9 | |||
c82cc47767 | |||
66f5e30d7c | |||
1a0da11e55 | |||
abc8878547 | |||
75e9d3f634 | |||
248caefb7e | |||
853d1de6ec | |||
84dc6ae76b | |||
05219a54cd | |||
4b62a722f0 | |||
61b69c63ed | |||
09b39bf77a | |||
42f6baeaec | |||
8ef183b593 | |||
2cb066215a | |||
200e190f70 | |||
44f829dbc6 | |||
401c9efad7 | |||
900bf8e483 | |||
271ced8ac4 | |||
c5bd3f0773 | |||
ad23921814 | |||
31cbec0857 | |||
d717529e9a | |||
c68fa27444 | |||
d2507ac760 | |||
4ce0d5e024 | |||
5d9e573b3e | |||
51839ca677 | |||
7225416661 | |||
5e4fa5cf07 | |||
fa28b28d0a | |||
f0ef72d6cc | |||
a58c9f83bd | |||
624a33f7f8 | |||
20a033e4c9 | |||
93c331d103 | |||
51c477925a | |||
1daa8aa3a1 | |||
62bf777ef1 | |||
aaf3edd131 | |||
6bba289a3c | |||
b0c735f72c | |||
0e2047f9ca | |||
e30ad2ec2c | |||
c509057f65 | |||
e138add584 | |||
49777648b3 | |||
cb87fa0970 | |||
649e276610 | |||
5ef11774c2 | |||
75db2c5241 | |||
c8ebd11d63 | |||
6651aa1e1d | |||
3f28d08778 | |||
ab28676d02 | |||
577a80371f | |||
01fdb4afc6 | |||
be7504d451 | |||
169e4e862d | |||
abc3de7efe | |||
0b1bb172c9 | |||
0856516ae9 | |||
705d3aacff | |||
1d0078415f | |||
9d1df21d91 | |||
3f36a3c119 | |||
8c15ccecd1 | |||
e966869744 | |||
6b017fb388 | |||
bb6f59e423 | |||
c9cec60007 | |||
f356d03362 | |||
0520ca68b4 | |||
8e1d53b5e9 | |||
f5b56c627b | |||
740d85cad8 | |||
33bba094d2 | |||
f88c4b77ca | |||
75da6e4c4a | |||
1864f60afb | |||
457c15cd6c | |||
28feac9411 | |||
9153331303 | |||
9d5c33f9dd | |||
2713b7877b | |||
2f0fef8ee1 | |||
259f872cea | |||
68ed8f1b6b | |||
ef7014fe19 | |||
46ad3552c7 | |||
4965226f3f | |||
ea546f5069 | |||
cf32213079 | |||
ce6a2ba836 | |||
0f4a089c32 | |||
3c77855b39 | |||
c1579222bd | |||
f863ea0db5 | |||
e4342743c0 | |||
9e8d31d532 | |||
f75a50c1dd | |||
c671706518 | |||
ead21c91a4 | |||
87dcd5eb6f | |||
8faf6364dc | |||
b71fe311fc | |||
bb50fc131b | |||
3aac2fefd7 | |||
fb67e37339 | |||
648c514c28 | |||
511e832ee2 | |||
09f8d8f7ba | |||
1205f54d01 | |||
b5032fd374 | |||
a7a9463624 | |||
59824e40e8 | |||
a51a5c2968 | |||
e3c11045bf | |||
414e58edb5 | |||
3bb3bff1f2 | |||
d2d4e7d783 | |||
ee1b574baf | |||
c0f3778dda | |||
d4925b61ff | |||
5b104936ae | |||
14988d4415 | |||
cd953ceb48 | |||
726fecbfb6 | |||
818bb9b697 | |||
e4586249fa | |||
4c1e978536 | |||
3d62546314 | |||
b9eab463f7 | |||
dff4795e49 | |||
ab74e1ed4e | |||
902984cc10 | |||
ce431f279e | |||
7fb2f2069c | |||
c269bd5d3c | |||
b72eb0783b | |||
a801da6f7c | |||
6fcd3709cf | |||
1b2754dacd | |||
e617ca6323 | |||
15376a6d24 | |||
867705bd2c | |||
6ab19dd095 | |||
99fdb9ac41 | |||
2827ca1559 | |||
8ea03d0380 | |||
d1ec2e18cd | |||
aa58e4bba5 | |||
0a97f0b645 | |||
8a5cf896d0 | |||
22c79df98d | |||
a52798543a | |||
1cbdb9cd17 | |||
4c9b8ebb0c | |||
6aea629cd3 | |||
649fd5a7a9 | |||
40c4eb7240 | |||
cd05ed8de9 | |||
42e7fc5252 | |||
7740fc071c | |||
bdf6af9bd6 | |||
2f83efaac8 | |||
32c5ab956c | |||
b111ca9471 | |||
725f909ff8 | |||
427f0d021c | |||
9fc9d53566 | |||
6dece68bb8 | |||
0676fef61f | |||
1d52cfba13 | |||
bfa381b35a | |||
f78406392b | |||
623edcd2d8 | |||
b5e350b18c | |||
87cf434929 | |||
4bab25b366 | |||
6896305e34 | |||
8ccafb0524 | |||
8a92a1f13e | |||
d0059b5d75 | |||
fa8e059f28 | |||
8e18d6c6cf | |||
afe0e45453 | |||
2e3e41ba64 | |||
d74dd1126b | |||
0ff99081bd | |||
6f4b6783c0 | |||
b1bc792b56 | |||
d4b8a86509 | |||
642e7e5c46 | |||
4650d25a53 | |||
7551a28f1a | |||
e51a48fe4c | |||
22c6c09daf | |||
e70a2f21dd | |||
97e6fb6835 | |||
14a7b9f794 | |||
fa1ec48549 | |||
f7f06c5ad4 | |||
e23004df52 | |||
fe70c2647a | |||
ada1e642c5 | |||
817c79ca77 | |||
a97a2266d3 | |||
8b3c808cb0 | |||
2d929e73ec | |||
681d06386d | |||
77b31ab42f | |||
5b4eb0c6d7 | |||
5c25248582 | |||
64ad74acbe | |||
02997f473a | |||
abda569b55 | |||
447018b54b | |||
0a200aff70 | |||
883e1c1541 | |||
aabe83cf63 | |||
fbd6851860 | |||
d6dae0cc85 | |||
376d508934 | |||
a00cb1de50 | |||
56f3429cc9 | |||
4943c0f887 | |||
00e2d70f05 | |||
e52d71060f | |||
01869f9fa8 | |||
526c51d1a6 | |||
2b4d30d931 | |||
3dc4df2ffa | |||
f830cfca12 | |||
eac5c88893 | |||
abfe175c9e | |||
0fc66daef6 | |||
5a095bb257 | |||
de31aca7a7 | |||
97220dd2ba | |||
e1b0bab9a6 | |||
66a2f9b23a | |||
a8533b2133 | |||
87ac100c66 | |||
487c4d23c1 | |||
8906cdbab8 | |||
88963b438f | |||
4fd4a1d15c | |||
371c8b8a1c | |||
eb87f5f851 | |||
27d227283c | |||
ea9d24be31 | |||
5408abca68 | |||
233cb0f96a | |||
8b28e99373 | |||
923d90bce8 | |||
97fc248e00 | |||
7bd682bb27 | |||
e927342e58 | |||
ae84eb7462 | |||
f89bb8eaf3 | |||
0d0b3a35da | |||
cf7bef58b0 | |||
c65fd31e86 | |||
6600ac7031 | |||
957384ceeb | |||
d3e391d176 | |||
0658d5602e | |||
458213d055 | |||
cd1295a823 | |||
5d302c504e | |||
68faddbf5c | |||
dc9c614da2 | |||
8c1adabe1c | |||
213dabdceb | |||
6ecaa9aebb | |||
cb2e646332 | |||
fef1dee7aa | |||
e14543498c | |||
c25478380c | |||
e819e97f9a | |||
f149ae79c6 | |||
ffe13078e5 | |||
f0d0fe0801 | |||
d630d5baa5 | |||
7cac7c5157 | |||
aba61f22a6 | |||
8475c63a6a | |||
2d09f84182 | |||
ef6e0d8eb8 | |||
db97d73c3b | |||
0e3d0fbec6 | |||
896a1564ef | |||
8b97cf1479 | |||
b5c9f9ed9b | |||
bda120d862 | |||
3177576ad6 | |||
896a0457f8 | |||
caf8e2723d | |||
0107543a33 | |||
7d29636087 | |||
70433e6b73 | |||
3667854a8f | |||
c5c1c9e38e | |||
308823b6ea | |||
c05bad381c | |||
4a961f4ecb | |||
6c8398df9b | |||
ff6e7754ae | |||
28ba179e31 | |||
b96e560c8d | |||
7c95cea3a8 | |||
34501aaae6 | |||
dbfc4c1c16 | |||
301863b105 | |||
ef8dc40492 | |||
6dbd4d969b | |||
3dd0ac1f0a | |||
5b42272365 | |||
1f6c6dbf2f | |||
0012caa4d5 | |||
8499cf84c3 | |||
daf0f472b3 | |||
a3decad4c2 | |||
7b790a3369 | |||
e18920884e | |||
6f8fef4f13 | |||
e295940833 | |||
2ed7622239 | |||
6ce085a21a | |||
e34146fc14 | |||
4e2316c742 | |||
785900f722 | |||
5ce5a87abe | |||
afe5465862 | |||
678d541da7 | |||
f0477e164a | |||
b5002fb46b | |||
82127571b5 | |||
f6e9d1f857 | |||
2cab7c79c3 | |||
bba849909c | |||
cac74c73e1 | |||
f375dbd013 | |||
ea58ef85fc | |||
bf7933714a | |||
564477b8a0 | |||
7e2c04e805 | |||
8fa1539bac | |||
f45281a10a | |||
e9f70293ac | |||
61cb99ea42 | |||
5408a9a72d | |||
22c1a0d030 | |||
8c3007e4b5 | |||
838aa2aaa9 | |||
3285ffba16 | |||
17e8857efc | |||
226cbc7db3 | |||
cc7c7b3321 | |||
70cea03b4b | |||
a027912891 | |||
3bdf669ddf | |||
b94b04c074 | |||
cfc5dd830c | |||
a3097aaf05 | |||
69c3bff086 | |||
50098767fc | |||
de581ea8b3 | |||
9f8a9c6fc7 | |||
ad083ed28f | |||
105ba30ce9 | |||
ee8bf0b3c0 | |||
41262f4265 | |||
c349eb4fa4 | |||
ca958464c4 | |||
d6003ee0ab | |||
bc248e9a15 | |||
42c0171b40 | |||
1a99090b45 | |||
b7eea4f577 | |||
9c62b5867e | |||
2560af731a | |||
86211eb5f0 | |||
a3387b7f48 | |||
94a48e8640 | |||
d8aeb40b49 | |||
52c55d0ee8 | |||
438c2b31e4 | |||
57e308dd46 | |||
c922b5a112 | |||
d552303cd5 | |||
1d4d18d9db | |||
069bbf3ed0 | |||
a4a2d4e56d | |||
d77f409093 | |||
25c709c58e | |||
bc909d1d0f | |||
a6736ff9f2 | |||
894a0f0ee5 | |||
abea92af59 | |||
bcbed2812d | |||
c0b04ca0bc | |||
86dc3e5b07 | |||
c1aa65239e | |||
be5ccf6957 | |||
09067ebdc5 | |||
08697e71fa | |||
90d9a1df3f | |||
a96c149793 | |||
1037cef22e | |||
09948f4403 | |||
788461b7e2 | |||
4f56628566 | |||
bcbf1ccc68 | |||
ae30d7ba40 | |||
9adf41ca2d | |||
1d79d534d9 | |||
60e4197026 | |||
2fabca77b9 | |||
47542b0cb0 | |||
6c60c3e547 | |||
814d389b6e | |||
e81e5fb2b9 | |||
f68cdf3878 | |||
91e0e9e1dd | |||
59c1299168 | |||
27c6afbeb4 | |||
514ba54282 | |||
a11f683e7b | |||
b65b145122 | |||
982bb8b01d | |||
eb7b7581ca | |||
adab6c0728 | |||
609201e109 | |||
54a4e4a67c | |||
aca4604879 | |||
48811cd805 | |||
136f64f4ac | |||
123ee8e06f | |||
a55efbd8b8 | |||
7bf9525353 | |||
3915e1b242 | |||
ed5975d3e5 | |||
1a788e6b0d | |||
d822793229 | |||
b46d0bc48c | |||
65320126c2 | |||
c63b3164bd | |||
dbffa88dc2 | |||
8c5d9d372f | |||
50f8892c6b | |||
3bfbfa8ae0 | |||
8598c87ef4 | |||
33bfc4c24a | |||
3afb744e77 | |||
e92918bbfe | |||
723e8fde93 | |||
507f7ea70a | |||
6b985d56a5 | |||
c8385ad998 | |||
9d21a6f40d | |||
d304f41197 | |||
8d85b839b6 | |||
dd235f38a3 | |||
5306b6dd0c | |||
b09624024b | |||
edc3709451 | |||
e706f3477b | |||
6298cb3999 | |||
878fce6482 | |||
b02bd65871 | |||
ee36aaf163 | |||
ff84506bd5 | |||
0ae33b7e3c | |||
b1dc6239ef | |||
3ce0f1146f | |||
3ec837bfdb | |||
18ff2be9bb | |||
c0d296334c | |||
9a0a2e319c | |||
a0d86ac2bb | |||
99045b2f6a | |||
c34ca36778 | |||
58dd75a1c8 | |||
f995b07876 | |||
101a4aa3cf | |||
65d759316b | |||
19c1773133 | |||
9b3b3d325f | |||
43f4374944 | |||
81e6d13241 | |||
f8e7a37c0d | |||
c686e7ea30 | |||
7e89af8190 | |||
539e8e2cce | |||
aab084866c | |||
0e61a86763 | |||
1c9938ed98 | |||
47c1a0f381 | |||
514529b5d9 | |||
a12dc7d75a | |||
41b53e71e1 | |||
0fb9f3bd6c | |||
81f3f32217 | |||
b35f288794 | |||
4e82cc0861 | |||
c735644c57 | |||
5d479fa0ae | |||
8baedca972 | |||
02aa8e7945 | |||
ee523efcb4 | |||
eef5f7e06d | |||
83402930f2 | |||
bd48c927d0 | |||
b61b8d60b7 | |||
f1fca5abb6 | |||
045ce3c77a | |||
f822066e2a |
3
.clang-format
Normal file
3
.clang-format
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Language: JavaScript
|
||||||
|
BasedOnStyle: Google
|
||||||
|
ColumnLimit: 100
|
6
.gitattributes
vendored
6
.gitattributes
vendored
@ -1,5 +1,9 @@
|
|||||||
# Auto detect text files and perform LF normalization
|
# Auto detect text files and perform LF normalization
|
||||||
* text=auto
|
* text=auto
|
||||||
|
|
||||||
# JS files must always use LF for tools to work
|
# JS and TS files must always use LF for tools to work
|
||||||
*.js eol=lf
|
*.js eol=lf
|
||||||
|
*.ts eol=lf
|
||||||
|
|
||||||
|
# Must keep Windows line ending to be parsed correctly
|
||||||
|
scripts/windows/packages.txt eol=crlf
|
||||||
|
39
.github/ISSUE_TEMPLATE.md
vendored
Normal file
39
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<!--
|
||||||
|
IF YOU DON'T FILL OUT THE FOLLOWING INFORMATION WE MIGHT CLOSE YOUR ISSUE WITHOUT INVESTIGATING
|
||||||
|
-->
|
||||||
|
|
||||||
|
**I'm submitting a ...** (check one with "x")
|
||||||
|
```
|
||||||
|
[ ] bug report => search github for a similar issue or PR before submitting
|
||||||
|
[ ] feature request
|
||||||
|
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
|
||||||
|
```
|
||||||
|
|
||||||
|
**Current behavior**
|
||||||
|
<!-- Describe how the bug manifests. -->
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
<!-- Describe what the behavior would be without the bug. -->
|
||||||
|
|
||||||
|
**Minimal reproduction of the problem with instructions**
|
||||||
|
<!--
|
||||||
|
If the current behavior is a bug or you can illustrate your feature request better with an example,
|
||||||
|
please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
|
||||||
|
https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5).
|
||||||
|
-->
|
||||||
|
|
||||||
|
**What is the motivation / use case for changing the behavior?**
|
||||||
|
<!-- Describe the motivation or the concrete use case -->
|
||||||
|
|
||||||
|
**Please tell us about your environment:**
|
||||||
|
<!-- Operating system, IDE, package manager, HTTP server, ... -->
|
||||||
|
|
||||||
|
* **Angular version:** 2.0.X
|
||||||
|
<!-- Check whether this is still an issue in the most recent Angular version -->
|
||||||
|
|
||||||
|
* **Browser:** [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
|
||||||
|
<!-- All browsers where this could be reproduced -->
|
||||||
|
|
||||||
|
* **Language:** [all | TypeScript X.X | ES6/7 | ES5]
|
||||||
|
|
||||||
|
* **Node (for AoT issues):** `node --version` =
|
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
36
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
**Please check if the PR fulfills these requirements**
|
||||||
|
- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit
|
||||||
|
- [ ] Tests for the changes have been added (for bug fixes / features)
|
||||||
|
- [ ] Docs have been added / updated (for bug fixes / features)
|
||||||
|
|
||||||
|
|
||||||
|
**What kind of change does this PR introduce?** (check one with "x")
|
||||||
|
```
|
||||||
|
[ ] Bugfix
|
||||||
|
[ ] Feature
|
||||||
|
[ ] Code style update (formatting, local variables)
|
||||||
|
[ ] Refactoring (no functional changes, no api changes)
|
||||||
|
[ ] Build related changes
|
||||||
|
[ ] CI related changes
|
||||||
|
[ ] Other... Please describe:
|
||||||
|
```
|
||||||
|
|
||||||
|
**What is the current behavior?** (You can also link to an open issue here)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**What is the new behavior?**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
**Does this PR introduce a breaking change?** (check one with "x")
|
||||||
|
```
|
||||||
|
[ ] Yes
|
||||||
|
[ ] No
|
||||||
|
```
|
||||||
|
|
||||||
|
If this PR contains a breaking change, please describe the impact and migration path for existing applications: ...
|
||||||
|
|
||||||
|
|
||||||
|
**Other information**:
|
||||||
|
|
29
.gitignore
vendored
29
.gitignore
vendored
@ -1,26 +1,27 @@
|
|||||||
# Don’t commit the following directories created by pub.
|
|
||||||
/dist/
|
|
||||||
packages/
|
|
||||||
.buildlog
|
|
||||||
node_modules
|
|
||||||
bower_components
|
|
||||||
.pub
|
|
||||||
.DS_STORE
|
.DS_STORE
|
||||||
|
|
||||||
# Or the files created by dart2js.
|
/dist/
|
||||||
*.dart.js
|
node_modules
|
||||||
*.dart.precompiled.js
|
bower_components
|
||||||
*.js_
|
|
||||||
*.js.deps
|
|
||||||
*.js.map
|
|
||||||
|
|
||||||
# Include when developing application packages.
|
# Include when developing application packages.
|
||||||
pubspec.lock
|
pubspec.lock
|
||||||
.c9
|
.c9
|
||||||
.idea/
|
.idea/
|
||||||
|
.settings/
|
||||||
*.swo
|
*.swo
|
||||||
|
modules/.settings
|
||||||
|
.vscode
|
||||||
|
modules/.vscode
|
||||||
|
|
||||||
# Don't check in secret files
|
# Don't check in secret files
|
||||||
*secret.js
|
*secret.js
|
||||||
|
|
||||||
/docs/bower_components/
|
# Ignore npm debug log
|
||||||
|
npm-debug.log
|
||||||
|
|
||||||
|
# build-analytics
|
||||||
|
.build-analytics
|
||||||
|
|
||||||
|
# rollup-test output
|
||||||
|
/modules/rollup-test/dist/
|
||||||
|
32
.pullapprove.yml
Normal file
32
.pullapprove.yml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Configuration for pullapprove.com
|
||||||
|
# See ownership spreadsheet:
|
||||||
|
# https://docs.google.com/spreadsheets/d/1-HIlzfbPYGsPr9KuYMe6bLfc4LXzPjpoALqtYRYTZB0/edit?pli=1#gid=0&vpid=A5
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
group_defaults:
|
||||||
|
required: 1
|
||||||
|
reset_on_reopened:
|
||||||
|
enabled: true
|
||||||
|
approve_by_comment:
|
||||||
|
enabled: true
|
||||||
|
approve_regex: '^(Approved|:\+1:|LGTM)'
|
||||||
|
|
||||||
|
groups:
|
||||||
|
config:
|
||||||
|
conditions:
|
||||||
|
files:
|
||||||
|
- "*.yml"
|
||||||
|
- "*.json"
|
||||||
|
teams:
|
||||||
|
- repoowners
|
||||||
|
|
||||||
|
compiler:
|
||||||
|
conditions:
|
||||||
|
files:
|
||||||
|
- "tools/@angular/tsc-wrapped/*"
|
||||||
|
- "modules/@angular/compiler/*"
|
||||||
|
- "modules/@angular/compiler-cli/*"
|
||||||
|
teams:
|
||||||
|
- compiler-owners
|
||||||
|
- repoowners
|
71
.travis.yml
71
.travis.yml
@ -1,38 +1,51 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
sudo: false
|
sudo: false
|
||||||
node_js:
|
node_js:
|
||||||
- '0.10'
|
- '6.6.0'
|
||||||
|
|
||||||
|
addons:
|
||||||
|
# firefox: "38.0"
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
# needed to install g++ that is used by npms's native modules
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.8
|
||||||
|
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- g3_v2_0
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- ./node_modules
|
||||||
|
- ./.chrome/chromium
|
||||||
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- KARMA_BROWSERS=DartiumWithWebPlatform
|
# GITHUB_TOKEN_ANGULAR
|
||||||
- E2E_BROWSERS=Dartium
|
# This is needed for the e2e Travis matrix task to publish packages to github for continuous packages delivery.
|
||||||
- LOGS_DIR=/tmp/angular-build/logs
|
- secure: "fq/U7VDMWO8O8SnAQkdbkoSe2X92PVqg4d044HmRYVmcf6YbO48+xeGJ8yOk0pCBwl3ISO4Q2ot0x546kxfiYBuHkZetlngZxZCtQiFT9kyId8ZKcYdXaIW9OVdw3Gh3tQyUwDucfkVhqcs52D6NZjyE2aWZ4/d1V4kWRO/LMgo="
|
||||||
- ARCH=linux-x64
|
|
||||||
matrix:
|
matrix:
|
||||||
- MODE=js DART_CHANNEL=dev
|
# Order: a slower build first, so that we don't occupy an idle travis worker waiting for others to complete.
|
||||||
# Dissabled until Dart v1.9 hits stable
|
- CI_MODE=js
|
||||||
# - MODE=dart DART_CHANNEL=stable
|
- CI_MODE=e2e
|
||||||
- MODE=dart DART_CHANNEL=dev
|
- CI_MODE=saucelabs_required
|
||||||
|
- CI_MODE=browserstack_required
|
||||||
|
- CI_MODE=saucelabs_optional
|
||||||
|
- CI_MODE=browserstack_optional
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
allow_failures:
|
||||||
|
- env: "CI_MODE=saucelabs_optional"
|
||||||
|
- env: "CI_MODE=browserstack_optional"
|
||||||
|
|
||||||
|
install:
|
||||||
|
- ./scripts/ci-lite/install.sh
|
||||||
|
|
||||||
before_install:
|
|
||||||
- export DISPLAY=:99.0
|
|
||||||
- export GIT_SHA=$(git rev-parse HEAD)
|
|
||||||
- ./scripts/ci/init_android.sh
|
|
||||||
- ./scripts/ci/install_dart.sh ${DART_CHANNEL} ${ARCH}
|
|
||||||
- sh -e /etc/init.d/xvfb start
|
|
||||||
- if [[ -e SKIP_TRAVIS_TESTS ]]; then { cat SKIP_TRAVIS_TESTS ; exit 0; } fi
|
|
||||||
before_script:
|
|
||||||
- mkdir -p $LOGS_DIR
|
|
||||||
script:
|
script:
|
||||||
- ./scripts/ci/build_and_test.sh ${MODE}
|
- ./scripts/ci-lite/build.sh && ./scripts/ci-lite/test.sh
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
- ./scripts/ci/print-logs.sh
|
- ./scripts/ci-lite/cleanup.sh
|
||||||
notifications:
|
|
||||||
webhooks:
|
|
||||||
urls:
|
|
||||||
- https://webhooks.gitter.im/e/1ef62e23078036f9cee4
|
|
||||||
on_success: change # options: [always|never|change] default: always
|
|
||||||
on_failure: always # options: [always|never|change] default: always
|
|
||||||
on_start: false # default: false
|
|
||||||
slack:
|
|
||||||
secure: EP4MzZ8JMyNQJ4S3cd5LEPWSMjC7ZRdzt3veelDiOeorJ6GwZfCDHncR+4BahDzQAuqyE/yNpZqaLbwRWloDi15qIUsm09vgl/1IyNky1Sqc6lEknhzIXpWSalo4/T9ZP8w870EoDvM/UO+LCV99R3wS8Nm9o99eLoWVb2HIUu0=
|
|
||||||
|
4835
CHANGELOG.md
Normal file
4835
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
34
COMMITTER.md
Normal file
34
COMMITTER.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Pushing changes into the Angular 2 tree
|
||||||
|
|
||||||
|
Please see [Using git with Angular repositories](https://docs.google.com/document/d/1h8nijFSaa1jG_UE8v4WP7glh5qOUXnYtAtJh_gwOQHI/edit)
|
||||||
|
for details about how we maintain a linear commit history, and the rules for committing.
|
||||||
|
|
||||||
|
As a contributor, just read the instructions in [CONTRIBUTING.md](CONTRIBUTING.md) and send a pull request.
|
||||||
|
Someone with committer access will do the rest.
|
||||||
|
|
||||||
|
## The `PR: merge` label and `presubmit-*` branches
|
||||||
|
|
||||||
|
We have automated the process for merging pull requests into master. Our goal is to minimize the disruption for
|
||||||
|
Angular committers and also prevent breakages on master.
|
||||||
|
|
||||||
|
When a PR has `pr_state: LGTM` and is ready to merge, you should add the `pr_action: merge` label.
|
||||||
|
Currently (late 2015), we need to ensure that each PR will cleanly merge into the Google-internal version control,
|
||||||
|
so the caretaker reviews the changes manually.
|
||||||
|
|
||||||
|
After this review, the caretaker adds `zomg_admin: do_merge` which is restricted to admins only.
|
||||||
|
A robot running as [mary-poppins](https://github.com/mary-poppins)
|
||||||
|
is notified that the label was added by an authorized person,
|
||||||
|
and will create a new branch in the angular project, using the convention `presubmit-{username}-pr-{number}`.
|
||||||
|
|
||||||
|
(Note: if the automation fails, committers can instead push the commits to a branch following this naming scheme.)
|
||||||
|
|
||||||
|
When a Travis build succeeds for a presubmit branch named following the convention,
|
||||||
|
Travis will re-base the commits, merge to master, and close the PR automatically.
|
||||||
|
|
||||||
|
Finally, after merge `mary-poppins` removes the presubmit branch.
|
||||||
|
|
||||||
|
## Administration
|
||||||
|
|
||||||
|
The list of users who can trigger a merge by adding the `zomg_admin: do_merge` label is stored in our appengine app datastore.
|
||||||
|
Edit the contents of the [CoreTeamMember Table](
|
||||||
|
https://console.developers.google.com/project/angular2-automation/datastore/query?queryType=KindQuery&namespace=&kind=CoreTeamMember)
|
118
CONTRIBUTING.md
118
CONTRIBUTING.md
@ -1,6 +1,6 @@
|
|||||||
# Contributing to Angular 2
|
# Contributing to Angular
|
||||||
|
|
||||||
We would love for you to contribute to Angular 2 and help make it even better than it is
|
We would love for you to contribute to Angular and help make it even better than it is
|
||||||
today! As a contributor, here are the guidelines we would like you to follow:
|
today! As a contributor, here are the guidelines we would like you to follow:
|
||||||
|
|
||||||
- [Code of Conduct](#coc)
|
- [Code of Conduct](#coc)
|
||||||
@ -17,61 +17,59 @@ Help us keep Angular open and inclusive. Please read and follow our [Code of Con
|
|||||||
|
|
||||||
## <a name="question"></a> Got a Question or Problem?
|
## <a name="question"></a> Got a Question or Problem?
|
||||||
|
|
||||||
If you have questions about how to *use* Angular, please direct them to the [Google Group][angular-group]
|
Please, do not open issues for the general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [StackOverflow](https://stackoverflow.com/questions/tagged/angular) where the questions should be tagged with tag `angular`.
|
||||||
discussion list or [StackOverflow][stackoverflow]. We are also available on [Gitter][gitter].
|
|
||||||
|
|
||||||
## <a name="issue"></a> Found an Issue?
|
StackOverflow is a much better place to ask questions since:
|
||||||
If you find a bug in the source code or a mistake in the documentation, you can help us by
|
|
||||||
|
- there are thousands of people willing to help on StackOverflow
|
||||||
|
- questions and answers stay available for public viewing so your question / answer might help someone else
|
||||||
|
- StackOverflow's voting system assures that the best answers are prominently visible.
|
||||||
|
|
||||||
|
To save your and our time we will be systematically closing all the issues that are requests for general support and redirecting people to StackOverflow.
|
||||||
|
|
||||||
|
If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter].
|
||||||
|
|
||||||
|
## <a name="issue"></a> Found a Bug?
|
||||||
|
If you find a bug in the source code, you can help us by
|
||||||
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
|
[submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can
|
||||||
[submit a Pull Request](#submit-pr) with a fix.
|
[submit a Pull Request](#submit-pr) with a fix.
|
||||||
|
|
||||||
## <a name="feature"></a> Want a Feature?
|
## <a name="feature"></a> Missing a Feature?
|
||||||
You can *request* a new feature by [submitting an issue](#submit-issue) to our [GitHub
|
You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub
|
||||||
Repository][github]. If you would like to *implement* a new feature then consider what kind of
|
Repository. If you would like to *implement* a new feature, please submit an issue with
|
||||||
change it is:
|
a proposal for your work first, to be sure that we can use it.
|
||||||
|
Please consider what kind of change it is:
|
||||||
|
|
||||||
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
|
* For a **Major Feature**, first open an issue and outline your proposal so that it can be
|
||||||
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
|
discussed. This will also allow us to better coordinate our efforts, prevent duplication of work,
|
||||||
and help you to craft the change so that it is successfully accepted into the project.
|
and help you to craft the change so that it is successfully accepted into the project.
|
||||||
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
|
||||||
|
|
||||||
## <a name="docs"></a> Want a Doc Fix?
|
|
||||||
If you want to help improve the docs, then consider what kind of improvement it is:
|
|
||||||
|
|
||||||
* For **Major Changes**, it's a good idea to let others know what you're working on to
|
|
||||||
minimize duplication of effort. Before starting, check out the issue queue for
|
|
||||||
issues labeled [#docs](https://github.com/angular/angular/labels/%23docs).
|
|
||||||
Comment on an issue to let others know what you're working on, or [create a new issue](#submit-issue)
|
|
||||||
if your work doesn't fit within the scope of any of the existing doc issues.
|
|
||||||
Please build and test the documentation before [submitting the Pull Request](#submit-pr), to be sure
|
|
||||||
you haven't accidentally introduced any layout or formatting issues. Also ensure that your commit
|
|
||||||
message is labeled "docs" and follows the [Commit Message Guidelines](#commit) given below.
|
|
||||||
* For **Small Changes**, there is no need to file an issue first. Simply [submit a Pull Request](#submit-pr).
|
|
||||||
|
|
||||||
## <a name="submit"></a> Submission Guidelines
|
## <a name="submit"></a> Submission Guidelines
|
||||||
|
|
||||||
### <a name="submit-issue"></a> Submitting an Issue
|
### <a name="submit-issue"></a> Submitting an Issue
|
||||||
Before you submit an issue, search the archive, maybe your question was already answered.
|
|
||||||
|
|
||||||
If your issue appears to be a bug, and hasn't been reported, open a new issue.
|
Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.
|
||||||
Help us to maximize the effort we can spend fixing issues and adding new
|
|
||||||
features, by not reporting duplicate issues. Providing the following information will increase the
|
We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a minimal reproduction scenario using http://plnkr.co. Having a live, reproducible scenario gives us wealth of important information without going back & forth to you with additional questions like:
|
||||||
chances of your issue being dealt with quickly:
|
|
||||||
|
- version of Angular used
|
||||||
|
- 3rd-party libraries and their versions
|
||||||
|
- and most importantly - a use-case that fails
|
||||||
|
|
||||||
|
A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem. If plunker is not a suitable way to demonstrate the problem (for example for issues related to our npm packaging), please create a standalone git repository demonstrating the problem.
|
||||||
|
|
||||||
|
We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
|
||||||
|
|
||||||
|
Unfortunately we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that don't have enough info to be reproduced.
|
||||||
|
|
||||||
|
You can file new issues by filling out our [new issue form](https://github.com/angular/angular/issues/new).
|
||||||
|
|
||||||
* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
|
|
||||||
* **Motivation for or Use Case** - explain why this is a bug for you
|
|
||||||
* **Angular Version(s)** - is it a regression?
|
|
||||||
* **Browsers and Operating System** - is this a problem with all browsers?
|
|
||||||
* **Reproduce the Error** - provide a live example (using [Plunker][plunker],
|
|
||||||
[JSFiddle][jsfiddle] or [Runnable][runnable]) or a unambiguous set of steps.
|
|
||||||
* **Related Issues** - has a similar issue been reported before?
|
|
||||||
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
|
|
||||||
causing the problem (line of code or commit)
|
|
||||||
|
|
||||||
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
### <a name="submit-pr"></a> Submitting a Pull Request (PR)
|
||||||
Before you submit your Pull Request (PR) consider the following guidelines:
|
Before you submit your Pull Request (PR) consider the following guidelines:
|
||||||
|
|
||||||
* Search [GitHub](https://github.com/angular/angular.dart/pulls) for an open or closed PR
|
* Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR
|
||||||
that relates to your submission. You don't want to duplicate effort.
|
that relates to your submission. You don't want to duplicate effort.
|
||||||
* Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
* Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs.
|
||||||
We cannot accept code without this.
|
We cannot accept code without this.
|
||||||
@ -103,7 +101,7 @@ Before you submit your Pull Request (PR) consider the following guidelines:
|
|||||||
* In GitHub, send a pull request to `angular:master`.
|
* In GitHub, send a pull request to `angular:master`.
|
||||||
* If we suggest changes then:
|
* If we suggest changes then:
|
||||||
* Make the required updates.
|
* Make the required updates.
|
||||||
* Re-run the Angular 2 test suites for JS and Dart to ensure tests are still passing.
|
* Re-run the Angular test suites to ensure tests are still passing.
|
||||||
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@ -147,9 +145,9 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
|
|||||||
|
|
||||||
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
* All features or bug fixes **must be tested** by one or more specs (unit-tests).
|
||||||
* All public API methods **must be documented**. (Details TBC).
|
* All public API methods **must be documented**. (Details TBC).
|
||||||
* With the exceptions listed below, we follow the rules contained in
|
* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at
|
||||||
[Google's JavaScript Style Guide][js-style-guide]:
|
**100 characters**. An automated formatter is available, see
|
||||||
* Wrap all code at **100 characters**.
|
[DEVELOPER.md](DEVELOPER.md#clang-format).
|
||||||
|
|
||||||
## <a name="commit"></a> Commit Message Guidelines
|
## <a name="commit"></a> Commit Message Guidelines
|
||||||
|
|
||||||
@ -169,9 +167,27 @@ format that includes a **type**, a **scope** and a **subject**:
|
|||||||
<footer>
|
<footer>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The **header** is mandatory and the **scope** of the header is optional.
|
||||||
|
|
||||||
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
|
||||||
to read on GitHub as well as in various git tools.
|
to read on GitHub as well as in various git tools.
|
||||||
|
|
||||||
|
Footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
|
||||||
|
|
||||||
|
Samples: (even more [samples](https://github.com/angular/angular/commits/master))
|
||||||
|
|
||||||
|
```
|
||||||
|
docs(changelog): update change log to beta.5
|
||||||
|
```
|
||||||
|
```
|
||||||
|
fix(release): need to depend on latest rxjs and zone.js
|
||||||
|
|
||||||
|
The version in our package.json gets copied to the one we publish, and users need the latest of these.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Revert
|
||||||
|
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
|
||||||
|
|
||||||
### Type
|
### Type
|
||||||
Must be one of the following:
|
Must be one of the following:
|
||||||
|
|
||||||
@ -180,14 +196,15 @@ Must be one of the following:
|
|||||||
* **docs**: Documentation only changes
|
* **docs**: Documentation only changes
|
||||||
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
|
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
|
||||||
semi-colons, etc)
|
semi-colons, etc)
|
||||||
* **refactor**: A code change that neither fixes a bug or adds a feature
|
* **refactor**: A code change that neither fixes a bug nor adds a feature
|
||||||
* **perf**: A code change that improves performance
|
* **perf**: A code change that improves performance
|
||||||
* **test**: Adding missing tests
|
* **test**: Adding missing tests or correcting existing tests
|
||||||
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
|
* **build**: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
|
||||||
generation
|
* **ci**: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
|
||||||
|
* **chore**: Other changes that don't modify `src` or `test` files
|
||||||
|
|
||||||
### Scope
|
### Scope
|
||||||
The scope could be anything specifying place of the commit change. For example
|
The scope could be anything specifying place of the commit change. For example
|
||||||
`Compiler`, `ElementInjector`, etc.
|
`Compiler`, `ElementInjector`, etc.
|
||||||
|
|
||||||
### Subject
|
### Subject
|
||||||
@ -205,6 +222,7 @@ The body should include the motivation for the change and contrast this with pre
|
|||||||
The footer should contain any information about **Breaking Changes** and is also the place to
|
The footer should contain any information about **Breaking Changes** and is also the place to
|
||||||
reference GitHub issues that this commit **Closes**.
|
reference GitHub issues that this commit **Closes**.
|
||||||
|
|
||||||
|
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
|
||||||
|
|
||||||
A detailed explanation can be found in this [document][commit-message-format].
|
A detailed explanation can be found in this [document][commit-message-format].
|
||||||
|
|
||||||
@ -226,8 +244,8 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
|
|||||||
[github]: https://github.com/angular/angular
|
[github]: https://github.com/angular/angular
|
||||||
[gitter]: https://gitter.im/angular/angular
|
[gitter]: https://gitter.im/angular/angular
|
||||||
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
|
||||||
[js-style-guide]: http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
|
[js-style-guide]: https://google.github.io/styleguide/jsguide.html
|
||||||
[jsfiddle]: http://jsfiddle.net/
|
[jsfiddle]: http://jsfiddle.net
|
||||||
[plunker]: http://plnkr.co/edit
|
[plunker]: http://plnkr.co/edit
|
||||||
[runnable]: http://runnable.com/
|
[runnable]: http://runnable.com
|
||||||
[stackoverflow]: http://stackoverflow.com/questions/tagged/angular
|
[stackoverflow]: http://stackoverflow.com/questions/tagged/angular
|
||||||
|
255
DEVELOPER.md
255
DEVELOPER.md
@ -1,58 +1,47 @@
|
|||||||
# Building and Testing Angular 2 for JS and Dart
|
# Building and Testing Angular
|
||||||
|
|
||||||
This document describes how to set up your development environment to build and test Angular, both
|
This document describes how to set up your development environment to build and test Angular.
|
||||||
JS and Dart versions. It also explains the basic mechanics of using `git`, `node`, and `npm`.
|
It also explains the basic mechanics of using `git`, `node`, and `npm`.
|
||||||
|
|
||||||
See the [contributing guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md)
|
* [Prerequisite Software](#prerequisite-software)
|
||||||
for how to contribute your own code to
|
* [Getting the Sources](#getting-the-sources)
|
||||||
|
* [Installing NPM Modules](#installing-npm-modules)
|
||||||
|
* [Building](#building)
|
||||||
|
* [Running Tests Locally](#running-tests-locally)
|
||||||
|
|
||||||
1. [Prerequisite Software](#prerequisite-software)
|
See the [contribution guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md)
|
||||||
2. [Getting the Sources](#getting-the-sources)
|
if you'd like to contribute to Angular.
|
||||||
3. [Environment Variable Setup](#environment-variable-setup)
|
|
||||||
4. [Installing NPM Modules and Dart Packages](#installing-npm-modules-and-dart-packages)
|
|
||||||
5. [Running Tests Locally](#running-tests-locally)
|
|
||||||
6. [Project Information](#project-information)
|
|
||||||
7. [CI using Travis](#ci-using-travis)
|
|
||||||
8. [Debugging](#debugging)
|
|
||||||
|
|
||||||
## Prerequisite Software
|
## Prerequisite Software
|
||||||
|
|
||||||
Before you can build and test Angular, you must install and configure the
|
Before you can build and test Angular, you must install and configure the
|
||||||
following products on your development machine:
|
following products on your development machine:
|
||||||
|
|
||||||
* [Dart](https://www.dartlang.org) (version `>=1.9.0-dev.8.0`), specifically the Dart-SDK and
|
* [Git](http://git-scm.com) and/or the **GitHub app** (for [Mac](http://mac.github.com) or
|
||||||
Dartium (a version of [Chromium](http://www.chromium.org) with native support for Dart through
|
[Windows](http://windows.github.com)); [GitHub's Guide to Installing
|
||||||
the Dart VM). One of the **simplest** ways to get both is to install the **Dart Editor bundle**,
|
|
||||||
which includes the editor, SDK and Dartium. See the [Dart tools](https://www.dartlang.org/tools)
|
|
||||||
download [page for instructions](https://www.dartlang.org/tools/download.html); note that you can
|
|
||||||
download both **stable** and **dev** channel versions from the [download
|
|
||||||
archive](https://www.dartlang.org/tools/download-archive).
|
|
||||||
|
|
||||||
* [Git](http://git-scm.com) and/or the **Github app** (for [Mac](http://mac.github.com) or
|
|
||||||
[Windows](http://windows.github.com)): the [Github Guide to Installing
|
|
||||||
Git](https://help.github.com/articles/set-up-git) is a good source of information.
|
Git](https://help.github.com/articles/set-up-git) is a good source of information.
|
||||||
|
|
||||||
* [Node.js](http://nodejs.org) which is used to run a development web server, run tests, and
|
* [Node.js](http://nodejs.org), (version `>=5.4.1 <6`) which is used to run a development web server,
|
||||||
generate distributable files. We also use Node's Package Manager (`npm`). Depending on your
|
run tests, and generate distributable files. We also use Node's Package Manager, `npm`
|
||||||
system, you can install Node either from source or as a pre-packaged bundle.
|
(version `>=3.5.3 <4.0`), which comes with Node. Depending on your system, you can install Node either from
|
||||||
|
source or as a pre-packaged bundle.
|
||||||
* [Chrome Canary](https://www.google.com/chrome/browser/canary.html), a version of Chrome with
|
|
||||||
bleeding edge functionality, built especially for developers (and early adopters).
|
|
||||||
|
|
||||||
|
* [Java Development Kit](http://www.oracle.com/technetwork/es/java/javase/downloads/index.html) which is used
|
||||||
|
to execute the selenium standalone server for e2e testing.
|
||||||
|
|
||||||
## Getting the Sources
|
## Getting the Sources
|
||||||
|
|
||||||
Forking and cloning the Angular repository:
|
Fork and clone the Angular repository:
|
||||||
|
|
||||||
1. Login to your Github account or create one by following the instructions given
|
1. Login to your GitHub account or create one by following the instructions given
|
||||||
[here](https://github.com/signup/free).
|
[here](https://github.com/signup/free).
|
||||||
2. [Fork](http://help.github.com/forking) the [main Angular
|
2. [Fork](http://help.github.com/forking) the [main Angular
|
||||||
repository](https://github.com/angular/angular).
|
repository](https://github.com/angular/angular).
|
||||||
3. Clone your fork of the Angular repository and define an `upstream` remote pointing back to
|
3. Clone your fork of the Angular repository and define an `upstream` remote pointing back to
|
||||||
the Angular repository that you forked in the first place:
|
the Angular repository that you forked in the first place.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Clone your Github repository:
|
# Clone your GitHub repository:
|
||||||
git clone git@github.com:<github username>/angular.git
|
git clone git@github.com:<github username>/angular.git
|
||||||
|
|
||||||
# Go to the Angular directory:
|
# Go to the Angular directory:
|
||||||
@ -61,175 +50,129 @@ cd angular
|
|||||||
# Add the main Angular repository as an upstream remote to your repository:
|
# Add the main Angular repository as an upstream remote to your repository:
|
||||||
git remote add upstream https://github.com/angular/angular.git
|
git remote add upstream https://github.com/angular/angular.git
|
||||||
```
|
```
|
||||||
|
## Installing NPM Modules
|
||||||
|
|
||||||
## Environment Variable Setup
|
Next, install the JavaScript modules needed to build and test Angular:
|
||||||
|
|
||||||
Define the environment variables listed below. These are mainly needed for the testing. The
|
|
||||||
notation shown here is for [`bash`](http://www.gnu.org/software/bash); adapt as appropriate for
|
|
||||||
your favorite shell.
|
|
||||||
|
|
||||||
Examples given below of possible values for initializing the environment variables assume **Mac OS
|
|
||||||
X** and that you have installed the Dart Editor in the directory named by
|
|
||||||
`DART_EDITOR_DIR=/Applications/dart`. This is only for illustrative purposes.
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# DARTIUM_BIN: path to a Dartium browser executable; used by Karma to run Dart tests
|
|
||||||
export DARTIUM_BIN="$DART_EDITOR_DIR/chromium/Chromium.app/Contents/MacOS/Chromium"
|
|
||||||
```
|
|
||||||
|
|
||||||
Add the Dart SDK `bin` directory to your path and/or define `DART_SDK` (this is also detailed
|
|
||||||
[here](https://www.dartlang.org/tools/pub/installing.html)):
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# DART_SDK: path to a Dart SDK directory
|
|
||||||
export DART_SDK="$DART_EDITOR_DIR/dart-sdk"
|
|
||||||
|
|
||||||
# Update PATH to include the Dart SDK bin directory
|
|
||||||
PATH+=":$DART_SDK/bin"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Installing NPM Modules and Dart Packages
|
|
||||||
|
|
||||||
Next, install the modules and packages needed to build Angular and run tests:
|
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Install Angular project dependencies (package.json)
|
# Install Angular project dependencies (package.json)
|
||||||
npm install
|
npm install
|
||||||
|
|
||||||
# Ensure protractor has the latest webdriver
|
|
||||||
$(npm bin)/webdriver-manager update
|
|
||||||
|
|
||||||
# Install Dart packages
|
|
||||||
pub get
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Optional**: In this document, we make use of project local `npm` package scripts and binaries
|
**Optional**: In this document, we make use of project local `npm` package scripts and binaries
|
||||||
(stored under `./node_modules/.bin`) by prefixing these command invocations with `$(npm bin)`; in
|
(stored under `./node_modules/.bin`) by prefixing these command invocations with `$(npm bin)`; in
|
||||||
particular `gulp` and `protractor` commands. If you prefer, you can drop this path prefix by
|
particular `gulp` and `protractor` commands. If you prefer, you can drop this path prefix by either:
|
||||||
globally installing these two packages as follows:
|
|
||||||
|
*Option 1*: globally installing these two packages as follows:
|
||||||
|
|
||||||
* `npm install -g gulp` (you might need to prefix this command with `sudo`)
|
* `npm install -g gulp` (you might need to prefix this command with `sudo`)
|
||||||
* `npm install -g protractor` (you might need to prefix this command with `sudo`)
|
* `npm install -g protractor` (you might need to prefix this command with `sudo`)
|
||||||
|
|
||||||
Since global installs can become stale, we avoid their use in these instructions.
|
Since global installs can become stale, and required versions can vary by project, we avoid their
|
||||||
|
use in these instructions.
|
||||||
|
|
||||||
## Build commands
|
*Option 2*: defining a bash alias like `alias nbin='PATH=$(npm bin):$PATH'` as detailed in this
|
||||||
|
[Stackoverflow answer](http://stackoverflow.com/questions/9679932/how-to-use-package-installed-locally-in-node-modules/15157360#15157360) and used like this: e.g., `nbin gulp build`.
|
||||||
|
|
||||||
To build Angular and prepare tests run
|
## Installing Bower Modules
|
||||||
|
|
||||||
|
Now run `bower` to install additional dependencies:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$(npm bin)/gulp build
|
# Install other Angular project dependencies (bower.json)
|
||||||
|
bower install
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes:
|
## Windows only
|
||||||
* Results are put in the `dist` folder.
|
|
||||||
* This will also run `pub get` for the subfolders in `modules` and run `dartanalyzer` for
|
|
||||||
every file that matches `<module>/src/<module>.dart`, e.g. `di/src/di.dart`
|
|
||||||
|
|
||||||
To clean out the `dist` folder use:
|
In order to create the right symlinks, run **as administrator**:
|
||||||
```shell
|
```shell
|
||||||
$(npm bin)/gulp clean
|
./scripts/windows/create-symlinks.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Before submitting a PR, do not forget to remove them:
|
||||||
|
```shell
|
||||||
|
./scripts/windows/remove-symlinks.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To build Angular run:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./build.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
* Results are put in the dist folder.
|
||||||
|
|
||||||
## Running Tests Locally
|
## Running Tests Locally
|
||||||
|
|
||||||
### Basic tests
|
To run tests:
|
||||||
|
|
||||||
1. `$(npm bin)/gulp test.unit.js`: JS tests in a browser; runs in **watch mode** (i.e. karma
|
```shell
|
||||||
watches the test files for changes and re-runs tests when files are updated).
|
$ ./test.sh node # Run all angular tests on node
|
||||||
2. `$(npm bin)/gulp test.unit.cjs`: JS tests in NodeJS; runs in **watch mode**
|
|
||||||
3. `$(npm bin)/gulp test.unit.dart`: Dart tests in Dartium; runs in **watch mode**.
|
|
||||||
|
|
||||||
If you prefer running tests in "single-run" mode rather than watch mode use
|
$ ./test.sh browser # Run all angular tests in browser
|
||||||
|
$ ./test.sh browserNoRouter # Optionally run all angular tests without router in browser
|
||||||
|
|
||||||
* `$(npm bin)/gulp test.unit.js/ci`
|
$ ./test.sh tools # Run angular tooling (not framework) tests
|
||||||
* `$(npm bin)/gulp test.unit.dart/ci`
|
```
|
||||||
|
|
||||||
**Note**: If you want to only run a single test you can alter the test you wish
|
You should execute the 3 test suites before submitting a PR to github.
|
||||||
to run by changing `it` to `iit` or `describe` to `ddescribe`. This will only
|
|
||||||
run that individual test and make it much easier to debug. `xit` and `xdescribe`
|
|
||||||
can also be useful to exclude a test and a group of tests respectively.
|
|
||||||
|
|
||||||
**Note** for transpiler tests: The karma preprocessor is setup in a way so that after every test
|
All the tests are executed on our Continuous Integration infrastructure and a PR could only be merged once the tests pass.
|
||||||
run the transpiler is reloaded. With that it is possible to make changes to the preprocessor and
|
|
||||||
run the tests without exiting karma (just touch a test file that you would like to run).
|
|
||||||
|
|
||||||
### E2e tests
|
- CircleCI fails if your code is not formatted properly,
|
||||||
|
- Travis CI fails if any of the test suites described above fails.
|
||||||
|
|
||||||
1. `$(npm bin)/gulp build.js.cjs` (builds benchpress and tests into `dist/js/cjs` folder).
|
## Update the public API tests
|
||||||
2. `$(npm bin)/gulp serve.js.prod serve.js.dart2js` (runs local webserver).
|
|
||||||
3. `$(npm bin)/protractor protractor-js.conf.js`: JS e2e tests.
|
|
||||||
4. `$(npm bin)/protractor protractor-dart2js.conf.js`: Dart2JS e2e tests.
|
|
||||||
|
|
||||||
Angular specific command line options when running protractor:
|
If you happen to modify the public API of Angular, API golden files must be updated using:
|
||||||
- `$(npm bin)/protractor protractor-{js|dart2js}-conf.js --ng-help`
|
|
||||||
|
|
||||||
### Performance tests
|
``` shell
|
||||||
|
$ gulp public-api:update
|
||||||
|
```
|
||||||
|
|
||||||
1. `$(npm bin)/gulp build.js.cjs` (builds benchpress and tests into `dist/js/cjs` folder)
|
Note: The command `gulp public-api:enforce` fails when the API doesn't match the golden files. Make sure to rebuild
|
||||||
2. `$(npm bin)/gulp serve.js.prod serve.js.dart2js` (runs local webserver)
|
the project before trying to verify after an API change.
|
||||||
3. `$(npm bin)/protractor protractor-js.conf.js --benchmark`: JS performance tests
|
|
||||||
4. `$(npm bin)/protractor protractor-dart2js.conf.js --benchmark`: Dart2JS performance tests
|
|
||||||
|
|
||||||
Angular specific command line options when running protractor (e.g. force gc, ...):
|
## <a name="clang-format"></a> Formatting your source code
|
||||||
`$(npm bin)/protractor protractor-{js|dart2js}-conf.js --ng-help`
|
|
||||||
|
|
||||||
## Project Information
|
Angular uses [clang-format](http://clang.llvm.org/docs/ClangFormat.html) to format the source code. If the source code
|
||||||
|
is not properly formatted, the CI will fail and the PR can not be merged.
|
||||||
|
|
||||||
### Folder structure
|
You can automatically format your code by running:
|
||||||
|
|
||||||
* `modules/*`: modules that will be loaded in the browser
|
``` shell
|
||||||
* `tools/*`: tools that are needed to build Angular
|
$ gulp format
|
||||||
* `dist/*`: build files are placed here.
|
```
|
||||||
|
|
||||||
### File suffixes
|
## Linting/verifying your source code
|
||||||
|
|
||||||
* `*.js`: javascript files that get transpiled to Dart and EcmaScript 5
|
You can check that your code is properly formatted and adheres to coding style by running:
|
||||||
* `*.es6`: javascript files that get transpiled only to EcmaScript 5
|
|
||||||
* `*.es5`: javascript files that don't get transpiled
|
|
||||||
* `*.dart`: dart files that don't get transpiled
|
|
||||||
|
|
||||||
## CI using Travis
|
``` shell
|
||||||
|
$ gulp lint
|
||||||
|
```
|
||||||
|
|
||||||
For instructions on setting up Continuous Integration using Travis, see the instructions given
|
## Publishing your own personal snapshot build
|
||||||
[here](https://github.com/angular/angular.dart/blob/master/travis.md).
|
|
||||||
|
|
||||||
## Debugging
|
You may find that your un-merged change needs some validation from external participants.
|
||||||
|
Rather than requiring them to pull your Pull Request and build Angular locally, you can
|
||||||
|
publish the `*-builds` snapshots just like our Travis build does.
|
||||||
|
|
||||||
### Debug the transpiler
|
First time, you need to create the github repositories:
|
||||||
|
|
||||||
If you need to debug the transpiler:
|
``` shell
|
||||||
|
$ export TOKEN=[get one from https://github.com/settings/tokens]
|
||||||
|
$ CREATE_REPOS=1 ./scripts/publish/publish-build-artifacts.sh [github username]
|
||||||
|
```
|
||||||
|
|
||||||
- add a `debugger;` statement in the transpiler code,
|
For subsequent snapshots, just run
|
||||||
- from the root folder, execute `node debug $(npm bin)/gulp build` to enter the node
|
|
||||||
debugger
|
|
||||||
- press "c" to execute the program until you reach the `debugger;` statement,
|
|
||||||
- you can then type "repl" to enter the REPL and inspect variables in the context.
|
|
||||||
|
|
||||||
See the [Node.js manual](http://nodejs.org/api/debugger.html) for more information.
|
``` shell
|
||||||
|
$ ./scripts/publish/publish-build-artifacts.sh [github username]
|
||||||
Notes:
|
```
|
||||||
- You can also execute `node $(npm bin)/karma start karma-dart.conf.js` depending on which
|
|
||||||
code you want to debug (the former will process the "modules" folder while the later processes
|
|
||||||
the transpiler specs).
|
|
||||||
- You can also add `debugger;` statements in the specs (JavaScript). The execution will halt when
|
|
||||||
the developer tools are opened in the browser running Karma.
|
|
||||||
|
|
||||||
### Debug the tests
|
|
||||||
|
|
||||||
If you need to debug the tests:
|
|
||||||
|
|
||||||
- add a `debugger;` statement to the test you want to debug (oe the source code),
|
|
||||||
- execute karma `$(npm bin)/gulp test.js`,
|
|
||||||
- press the top right "DEBUG" button,
|
|
||||||
- open the dev tools and press F5,
|
|
||||||
- the execution halt at the `debugger;` statement
|
|
||||||
|
|
||||||
**Note (WebStorm users)**:
|
|
||||||
You can create a Karma run config from WebStorm.
|
|
||||||
Then in the "Run" menu, press "Debug 'karma-js.conf.js'", WebStorm will stop in the generated code
|
|
||||||
on the `debugger;` statement.
|
|
||||||
You can then step into the code and add watches.
|
|
||||||
The `debugger;` statement is needed because WebStorm will stop in a transpiled file. Breakpoints in
|
|
||||||
the original source files are not supported at the moment.
|
|
||||||
|
|
||||||
|
The script will publish the build snapshot to a branch with the same name as your current branch,
|
||||||
|
and create it if it doesn't exist.
|
||||||
|
215
LICENSE
215
LICENSE
@ -1,202 +1,21 @@
|
|||||||
Apache License
|
The MIT License
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
Copyright (c) 2014-2016 Google, Inc. http://angular.io
|
||||||
|
|
||||||
1. Definitions.
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
The above copyright notice and this permission notice shall be included in
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
32
NAMING.md
Normal file
32
NAMING.md
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Naming Conventions in Angular2
|
||||||
|
---
|
||||||
|
|
||||||
|
In general Angular2 should follow TypeScript naming conventions.
|
||||||
|
See: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines
|
||||||
|
|
||||||
|
|
||||||
|
Classes:
|
||||||
|
- Example: `Compiler`, `ApplicationMetadata`
|
||||||
|
- Camel case with first letter upper-case
|
||||||
|
- In general prefer single words. (This is so that when appending `Proto` or `Factory` the class
|
||||||
|
is still reasonable to work with.)
|
||||||
|
- Should not end with `Impl` or any other word which describes a specific implementation of an
|
||||||
|
interface.
|
||||||
|
|
||||||
|
|
||||||
|
Interfaces:
|
||||||
|
- Follow the same rules as Classes
|
||||||
|
- Should not have `I` or `Interface` in the name or any other way of identifying it as an interface.
|
||||||
|
|
||||||
|
|
||||||
|
Methods and functions:
|
||||||
|
- Example: `bootstrap`, `someMethod`
|
||||||
|
- Should be camel case with first lower case
|
||||||
|
|
||||||
|
|
||||||
|
Constants
|
||||||
|
- Example: `CORE_DIRECTIVES`
|
||||||
|
- Should be all uppercase with SNAKE_CASE
|
||||||
|
|
||||||
|
|
||||||
|
|
57
README.md
57
README.md
@ -1,52 +1,37 @@
|
|||||||
Angular [](https://travis-ci.org/angular/angular) [](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://travis-ci.org/angular/angular)
|
||||||
|
[](https://circleci.com/gh/angular/angular/tree/master)
|
||||||
|
[](https://gitter.im/angular/angular?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
|
[](http://issuestats.com/github/angular/angular)
|
||||||
|
[](http://issuestats.com/github/angular/angular)
|
||||||
|
[](https://badge.fury.io/js/%40angular%2Fcore)
|
||||||
|
|
||||||
|
[](https://saucelabs.com/u/angular2-ci)
|
||||||
|
*Safari (7+), iOS (7+), Edge (14) and IE mobile (11) are tested on [BrowserStack][browserstack].*
|
||||||
|
|
||||||
|
Angular
|
||||||
=========
|
=========
|
||||||
|
|
||||||
Angular is a development platform for building mobile and desktop web applications. This is the
|
Angular is a development platform for building mobile and desktop web applications. This is the
|
||||||
repository for [Angular 2][ng2], both the JavaScript (JS) and [Dart][dart] versions.
|
repository for [Angular 2][ng2] Typescript/JavaScript (JS).
|
||||||
|
|
||||||
Angular 2 is currently in **Alpha Preview**. We recommend using Angular 1.X for production
|
Angular2 for [Dart][dart] can be found at [dart-lang/angular2][ng2dart].
|
||||||
applications:
|
|
||||||
|
|
||||||
* [AngularJS][ngJS]: [angular/angular.js](http://github.com/angular/angular.js).
|
|
||||||
* [AngularDart][ngDart]: [angular/angular.dart](http://github.com/angular/angular.dart).
|
|
||||||
|
|
||||||
|
|
||||||
## Setup & Install Angular 2
|
## Quickstart
|
||||||
|
|
||||||
Follow the instructions given on the [Angular download page][download].
|
[Get started in 5 minutes][quickstart].
|
||||||
|
|
||||||
|
|
||||||
## Want to help?
|
## Want to help?
|
||||||
|
|
||||||
Want to file a bug, or contribute some code or improve documentation? Excellent! Read up on our
|
Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our
|
||||||
guidelines for [contributing][contributing].
|
guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help).
|
||||||
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
To see the examples, first build the project as described
|
|
||||||
[here](http://github.com/angular/angular/blob/master/DEVELOPER.md).
|
|
||||||
|
|
||||||
### Hello World Example
|
|
||||||
|
|
||||||
This example consists of three basic pieces - a component, a decorator and a
|
|
||||||
service. They are all constructed via injection. For more information see the
|
|
||||||
comments in the source `modules/examples/src/hello_world/index.js`.
|
|
||||||
|
|
||||||
You can build this example as either JS or Dart app:
|
|
||||||
|
|
||||||
* JS:
|
|
||||||
* `$(npm bin)/gulp serve.js.dev`, and
|
|
||||||
* open `localhost:8000/examples/src/hello_world/` in Chrome.
|
|
||||||
* Dart:
|
|
||||||
* `$(npm bin)/gulp serve/examples.dart`, and
|
|
||||||
* open `localhost:8080/src/hello_world` in Chrome (for dart2js) or
|
|
||||||
[Dartium][dartium] (for Dart VM).
|
|
||||||
|
|
||||||
|
[browserstack]: https://www.browserstack.com/
|
||||||
[contributing]: http://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
[contributing]: http://github.com/angular/angular/blob/master/CONTRIBUTING.md
|
||||||
[dart]: http://www.dartlang.org
|
[dart]: http://www.dartlang.org
|
||||||
[dartium]: http://www.dartlang.org/tools/dartium
|
[quickstart]: https://angular.io/docs/ts/latest/quickstart.html
|
||||||
[download]: http://angular.io/download
|
|
||||||
[ng2]: http://angular.io
|
[ng2]: http://angular.io
|
||||||
[ngDart]: http://angulardart.org
|
[ngDart]: http://angulardart.org
|
||||||
[ngJS]: http://angularjs.org
|
[ngJS]: http://angularjs.org
|
||||||
|
[ng2dart]: https://github.com/dart-lang/angular2
|
||||||
|
62
SAVED_REPLIES.md
Normal file
62
SAVED_REPLIES.md
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# Saved Responses for Angular's Issue Tracker
|
||||||
|
|
||||||
|
The following are canned responses that the Angular team should use to close issues on our issue tracker that fall into the listed resolution categories.
|
||||||
|
|
||||||
|
Since GitHub currently doesn't allow us to have a repository-wide or organization-wide list of [saved replies](https://help.github.com/articles/working-with-saved-replies/), these replies need to be maintained by individual team members. Since the responses can be modified in the future, all responses are versioned to simplify the process of keeping the responses up to date.
|
||||||
|
|
||||||
|
|
||||||
|
## Angular: Already Fixed (v1)
|
||||||
|
```
|
||||||
|
Thanks for reporting this issue. Luckily it has already been fixed in one of the recent releases. Please update to the most recent version to resolve the problem.
|
||||||
|
|
||||||
|
If after upgrade the problem still exists in your application please open a new issue and provide a plunker reproducing the problem and describing the difference between the expected and current behavior. You can use this plunker template: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=catalogue
|
||||||
|
```
|
||||||
|
|
||||||
|
## Angular: Don't Understand (v1)
|
||||||
|
```
|
||||||
|
I'm sorry but we don't understand the problem you are reporting.
|
||||||
|
|
||||||
|
If the problem still exists please open a new issue and provide a plunker reproducing the problem and describing the difference between the expected and current behavior. You can use this plunker template: http://plnkr.co/edit/tpl:AvJOMERrnz94ekVua0u5?p=catalogue
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Angular: Duplicate (v1)
|
||||||
|
```
|
||||||
|
Thanks for reporting this issue. However this issue is a duplicate of an existing issue #<ISSUE_NUMBER>. Please subscribe to that issue for future updates.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Angular: Insufficient Information Provided (v1)
|
||||||
|
```
|
||||||
|
Thanks for reporting this issue. However, you didn't provide sufficient information for us to understand and reproduce the problem. Please check out [our submission guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue) to understand why we can't act on issues that are lacking important information.
|
||||||
|
|
||||||
|
If the problem still persists, please file a new issue and ensure you provide all of the required information when filling out the issue template.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Angular: Issue Outside of Angular (v1)
|
||||||
|
```
|
||||||
|
I'm sorry but this issue is not caused by Angular. Please contact the author(s) of project <PROJECT NAME> or file issue on their issue tracker.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Angular: Non-reproducible (v1)
|
||||||
|
```
|
||||||
|
I'm sorry but we can't reproduce the problem following the instructions you provided.
|
||||||
|
|
||||||
|
If the problem still exists please open a new issue following [our submission guidelines](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-submitting-an-issue).
|
||||||
|
```
|
||||||
|
|
||||||
|
## Angular: Obsolete (v1)
|
||||||
|
```
|
||||||
|
Thanks for reporting this issue. This issue is now obsolete due to changes in the recent releases. Please update to the most recent Angular version.
|
||||||
|
|
||||||
|
If the problem still persists, please file a new issue and ensure you provide the version of Angular affected and include the steps to reproduce the problem when filling out the issue template.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Angular: Support Request (v1)
|
||||||
|
```
|
||||||
|
Hello, we reviewed this issue and determined that it doesn't fall into the bug report or feature request category. This issue tracker is not suitable for support requests, please repost your issue on [StackOverflow](http://stackoverflow.com/) using tag `angular`.
|
||||||
|
|
||||||
|
If you are wondering why we don't resolve support issues via the issue tracker, please [check out this explanation](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-got-a-question-or-problem).
|
||||||
|
```
|
140
TOOLS.md
Normal file
140
TOOLS.md
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# Developer Tools for Angular 2
|
||||||
|
|
||||||
|
Here you will find a collection of tools and tips for keeping your application
|
||||||
|
perform well and contain fewer bugs.
|
||||||
|
|
||||||
|
## Angular debug tools in the dev console
|
||||||
|
|
||||||
|
Angular provides a set of debug tools that are accessible from any browser's
|
||||||
|
developer console. In Chrome the dev console can be accessed by pressing
|
||||||
|
Ctrl + Shift + j.
|
||||||
|
|
||||||
|
### Enabling debug tools
|
||||||
|
|
||||||
|
By default the debug tools are disabled. You can enable debug tools as follows:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {enableDebugTools} from '@angular/platform-browser';
|
||||||
|
|
||||||
|
bootstrap(Application).then((appRef) => {
|
||||||
|
enableDebugTools(appRef);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using debug tools
|
||||||
|
|
||||||
|
In the browser open the developer console (Ctrl + Shift + j in Chrome). The
|
||||||
|
top level object is called `ng` and contains more specific tools inside it.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ng.profiler.timeChangeDetection();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
### Change detection profiler
|
||||||
|
|
||||||
|
If your application is janky (it misses frames) or is slow according to other
|
||||||
|
metrics it is important to find the root cause of the issue. Change detection
|
||||||
|
is a phase in Angular's lifecycle that detects changes in values that are
|
||||||
|
bound to UI, and if it finds a change it performs the corresponding UI update.
|
||||||
|
However, sometimes it is hard to tell if the slowness is due to the act of
|
||||||
|
computing the changes being slow, or due to the act of applying those changes
|
||||||
|
to the UI. For your application to be performant it is important that the
|
||||||
|
process of computing changes is very fast. For best results it should be under
|
||||||
|
3 milliseconds in order to leave room for the application logic, the UI updates
|
||||||
|
and browser's rendering pipeline to fit withing the 16 millisecond frame
|
||||||
|
(assuming the 60 FPS target frame rate).
|
||||||
|
|
||||||
|
Change detection profiler repeatedly performs change detection without invoking
|
||||||
|
any user actions, such as clicking buttons or entering text in input fields. It
|
||||||
|
then computes the average amount of time it took to perform a single cycle of
|
||||||
|
change detection in milliseconds and prints it to the console. This number
|
||||||
|
depends on the current state of the UI. You will likely see different numbers
|
||||||
|
as you go from one screen in your application to another.
|
||||||
|
|
||||||
|
#### Running the profiler
|
||||||
|
|
||||||
|
Enable debug tools (see above), then in the dev console enter the following:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ng.profiler.timeChangeDetection();
|
||||||
|
```
|
||||||
|
|
||||||
|
The results will be printed to the console.
|
||||||
|
|
||||||
|
#### Recording CPU profile
|
||||||
|
|
||||||
|
Pass `{record: true}` an argument:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ng.profiler.timeChangeDetection({record: true});
|
||||||
|
```
|
||||||
|
|
||||||
|
Then open the "Profiles" tab. You will see the recorded profile titled
|
||||||
|
"Change Detection". In Chrome, if you record the profile repeatedly, all the
|
||||||
|
profiles will be nested under "Change Detection".
|
||||||
|
|
||||||
|
#### Interpreting the numbers
|
||||||
|
|
||||||
|
In a properly-designed application repeated attempts to detect changes without
|
||||||
|
any user actions should result in no changes to be applied on the UI. It is
|
||||||
|
also desirable to have the cost of a user action be proportional to the amount
|
||||||
|
of UI changes required. For example, popping up a menu with 5 items should be
|
||||||
|
vastly faster than rendering a table of 500 rows and 10 columns. Therefore,
|
||||||
|
change detection with no UI updates should be as fast as possible. Ideally the
|
||||||
|
number printed by the profiler should be well below the length of a single
|
||||||
|
animation frame (16ms). A good rule of thumb is to keep it under 3ms.
|
||||||
|
|
||||||
|
#### Investigating slow change detection
|
||||||
|
|
||||||
|
So you found a screen in your application on which the profiler reports a very
|
||||||
|
high number (i.e. >3ms). This is where a recorded CPU profile can help. Enable
|
||||||
|
recording while profiling:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
ng.profiler.timeChangeDetection({record: true});
|
||||||
|
```
|
||||||
|
|
||||||
|
Then look for hot spots using
|
||||||
|
[Chrome CPU profiler](https://developer.chrome.com/devtools/docs/cpu-profiling).
|
||||||
|
|
||||||
|
#### Reducing change detection cost
|
||||||
|
|
||||||
|
There are many reasons for slow change detection. To gain intuition about
|
||||||
|
possible causes it would help to understand how change detection works. Such a
|
||||||
|
discussion is outside the scope of this document (TODO link to docs), but here
|
||||||
|
are some key concepts in brief.
|
||||||
|
|
||||||
|
By default Angular uses "dirty checking" mechanism for finding model changes.
|
||||||
|
This mechanism involves evaluating every bound expression that's active on the
|
||||||
|
UI. These usually include text interpolation via `{{expression}}` and property
|
||||||
|
bindings via `[prop]="expression"`. If any of the evaluated expressions are
|
||||||
|
costly to compute they could contribute to slow change detection. A good way to
|
||||||
|
speed things up is to use plain class fields in your expressions and avoid any
|
||||||
|
kinds of computation. Example:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
@Component({
|
||||||
|
template: '<button [enabled]="isEnabled">{{title}}</button>'
|
||||||
|
})
|
||||||
|
class FancyButton {
|
||||||
|
// GOOD: no computation, just return the value
|
||||||
|
isEnabled: boolean;
|
||||||
|
|
||||||
|
// BAD: computes the final value upon request
|
||||||
|
_title: String;
|
||||||
|
get title(): String { return this._title.trim().toUpperCase(); }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Most cases like these could be solved by precomputing the value and storing the
|
||||||
|
final value in a field.
|
||||||
|
|
||||||
|
Angular also supports a second type of change detection - the "push" model. In
|
||||||
|
this model Angular does not poll your component for changes. Instead, the
|
||||||
|
component "tells" Angular when it changes and only then does Angular perform
|
||||||
|
the update. This model is suitable in situations when your data model uses
|
||||||
|
observable or immutable objects (also a discussion for another time).
|
158
TRIAGE_AND_LABELS.md
Normal file
158
TRIAGE_AND_LABELS.md
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
# Triage Process and Github Labels for Angular 2
|
||||||
|
|
||||||
|
This document describes how the Angular team uses labels and milestones
|
||||||
|
to triage issues on github. The basic idea of the process is that
|
||||||
|
caretaker only assigns a component and type (bug, feature) label. The
|
||||||
|
owner of the component than is in full control of how the issues should
|
||||||
|
be triaged further.
|
||||||
|
|
||||||
|
Once this process is implemented and in use, we will revisit it to see
|
||||||
|
if further labeling is needed.
|
||||||
|
|
||||||
|
## Components
|
||||||
|
|
||||||
|
A caretaker should be able to determine which component the issue
|
||||||
|
belongs to. The components have a clear piece of source code associated
|
||||||
|
with it.
|
||||||
|
|
||||||
|
* `comp: animations`: `@matsko`
|
||||||
|
* `comp: benchpress`: `@tbosch`
|
||||||
|
* `comp: build & ci`: `@IgorMinar` -- All build and CI scripts
|
||||||
|
* `comp: common`: `@mhevery` -- This includes core components / pipes.
|
||||||
|
* `comp: core & compiler`: `@tbosch` -- Because core and compiler are very
|
||||||
|
intertwined, we will be treating them as one.
|
||||||
|
* `comp: forms`: `@kara`
|
||||||
|
* `comp: http`: `@jeffbcross`
|
||||||
|
* `comp: i18n`: `@vicb`
|
||||||
|
* `comp: language service`: `@chuckjaz`
|
||||||
|
* `comp: metadata-extractor`: `@chuckjaz`
|
||||||
|
* `comp: router`: `@vicb`
|
||||||
|
* `comp: testing`: `@juliemr`
|
||||||
|
* `comp: upgrade`: `@mhevery`
|
||||||
|
* `comp: web-worker`: `@vicb`
|
||||||
|
* `comp: zones`: `@mhevery`
|
||||||
|
|
||||||
|
There are few components which are cross-cutting. They don't have
|
||||||
|
a clear location in the source tree. We will treat them as a component
|
||||||
|
even thought no specific source tree is associated with them.
|
||||||
|
|
||||||
|
* `comp: docs`: `@naomiblack`
|
||||||
|
* `comp: packaging`: `@IgorMinar`
|
||||||
|
* `comp: performance`: `@tbosch`
|
||||||
|
* `comp: security`: `@IgorMinar`
|
||||||
|
|
||||||
|
|
||||||
|
## Type
|
||||||
|
What kind of problem is this?
|
||||||
|
|
||||||
|
* `type: RFC / discussion / question`
|
||||||
|
* `type: bug`
|
||||||
|
* `type: chore`
|
||||||
|
* `type: feature`
|
||||||
|
* `type: performance`
|
||||||
|
* `type: refactor`
|
||||||
|
|
||||||
|
## Caretaker Triage Process
|
||||||
|
|
||||||
|
It is the caretaker's responsibility to assign `comp: *` to each new
|
||||||
|
issue as they come in. The reason why we limit the responsibility of the
|
||||||
|
caretaker to this one label is that it is likely that without domain
|
||||||
|
knowledge the caretaker could mislabel issues or lack knowledge of
|
||||||
|
duplicate issues.
|
||||||
|
|
||||||
|
|
||||||
|
## Component's owner Triage Process
|
||||||
|
|
||||||
|
At this point we are leaving each component owner to determine their own
|
||||||
|
process for their component.
|
||||||
|
|
||||||
|
It will be up to the component owner to determine the order in which the
|
||||||
|
issues within the component will be resolved.
|
||||||
|
|
||||||
|
Several owners have adopted the issue categorization based on
|
||||||
|
[user pain](http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html)
|
||||||
|
used by Angular 1. In this system every issue is assigned frequency and
|
||||||
|
severity based on which the total user pain score is calculated.
|
||||||
|
|
||||||
|
Following is the definition of various frequency and severity levels:
|
||||||
|
|
||||||
|
1. `freq(score): *` – How often does this issue come up? How many developers does this affect?
|
||||||
|
* low (1) - obscure issue affecting a handful of developers
|
||||||
|
* moderate (2) - impacts auxiliary usage patterns, only small number of applications are affected
|
||||||
|
* high (3) - impacts primary usage patterns, affecting most Angular apps
|
||||||
|
* critical (4) - impacts all Angular apps
|
||||||
|
1. `severity(score): *` - How bad is the issue?
|
||||||
|
* inconvenience (1) - causes ugly/boilerplate code in apps
|
||||||
|
* confusing (2) - unexpected or inconsistent behavior; hard-to-debug
|
||||||
|
* broken expected use (3) - it's hard or impossible for a developer using Angular to accomplish something that Angular should be able to do
|
||||||
|
* memory leak (4)
|
||||||
|
* regression (5) - functionality that used to work no longer works in a new release due to an unintentional change
|
||||||
|
* security issue (6)
|
||||||
|
|
||||||
|
|
||||||
|
These criteria are then used to calculate a "user pain" score as follows:
|
||||||
|
|
||||||
|
`pain = severity × frequency`
|
||||||
|
|
||||||
|
|
||||||
|
### Assigning Issues to Milestones
|
||||||
|
|
||||||
|
Any issue that is being worked on must have:
|
||||||
|
|
||||||
|
* An `Assignee`: The person doing the work.
|
||||||
|
* A `Milestone`: When we expect to complete this work.
|
||||||
|
|
||||||
|
We aim to only have at most three milestones open at a time:
|
||||||
|
|
||||||
|
* Closing Milestone: A milestone with a very small number of issues, about to release.
|
||||||
|
* Current Milestone: Work that we plan to complete within one week.
|
||||||
|
* Next Milestone: Work that is > 1 week but current for the team.
|
||||||
|
|
||||||
|
The [backlog](https://github.com/angular/angular/issues?q=is%3Aopen+is%3Aissue+no%3Amilestone)
|
||||||
|
consists of all issues that have been triaged but do not have an assignee or milestone.
|
||||||
|
|
||||||
|
## Triaged vs Untrained PRs
|
||||||
|
|
||||||
|
PRs should also be label with a `comp: *` so that it is clear which
|
||||||
|
primary area the PR effects.
|
||||||
|
|
||||||
|
Because of the cumulative pain associated with rebasing PRs, we triage PRs daily, and
|
||||||
|
closing or reviewing PRs is a top priority ahead of other ongoing work.
|
||||||
|
|
||||||
|
Every triaged PR must have a `pr_action` label assigned to it and an assignee:
|
||||||
|
|
||||||
|
* `pr_action: review` -- work is complete and comment is needed from the assignee.
|
||||||
|
* `pr_action: cleanup` -- more work is needed from the current assignee.
|
||||||
|
* `pr_action: discuss` -- discussion is needed, to be led by the current assignee.
|
||||||
|
* `pr_action: merge` -- the PR should be merged. Add this to a PR when you would like to
|
||||||
|
trigger automatic merging following a successful build. This is described in [COMMITTER.md](COMMITTER.md).
|
||||||
|
|
||||||
|
In addition, PRs can have the following states:
|
||||||
|
|
||||||
|
* `pr_state: LGTM` -- PR may have outstanding changes but does not require further review.
|
||||||
|
* `pr_state: WIP` -- PR is experimental or rapidly changing. Not ready for review or triage.
|
||||||
|
* `pr_state: blocked` -- PR is blocked on an issue or other PR. Not ready for review or triage.
|
||||||
|
|
||||||
|
Note that an LGTM state does not mean a PR is ready to merge: for example, a reviewer might set the
|
||||||
|
LGTM state but request a minor tweak that doesn't need further review, e.g., a rebase or small
|
||||||
|
uncontroversial change.
|
||||||
|
|
||||||
|
PRs do not need to be assigned to milestones, unless a milestone release should be held for that
|
||||||
|
PR to land.
|
||||||
|
|
||||||
|
|
||||||
|
## Special Labels
|
||||||
|
|
||||||
|
### action:design
|
||||||
|
More active discussion is needed before the issue can be worked on further. Typically used for
|
||||||
|
`type: feature` or `type: RFC/discussion/question`
|
||||||
|
|
||||||
|
[See all issues that need discussion](https://github.com/angular/angular/labels/action:%20Design)
|
||||||
|
|
||||||
|
### cla
|
||||||
|
Managed by googlebot. Indicates whether a PR has a CLA on file for its author(s). Only issues with
|
||||||
|
`cla:yes` should be merged into master.
|
||||||
|
|
||||||
|
### WORKS_AS_INTENDED
|
||||||
|
|
||||||
|
Only used on closed issues, to indicate to the reporter why we closed it.
|
@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "angular2",
|
"name": "angular2",
|
||||||
"version": "0.0.0",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"polymer": "dart-lang/polymer_js#0.8.0-preview"
|
"polymer": "Polymer/polymer#^1.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
177
browser-providers.conf.js
Normal file
177
browser-providers.conf.js
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Unique place to configure the browsers which are used in the different CI jobs in Sauce Labs (SL)
|
||||||
|
// and BrowserStack (BS).
|
||||||
|
// If the target is set to null, then the browser is not run anywhere during CI.
|
||||||
|
// If a category becomes empty (e.g. BS and required), then the corresponding job must be commented
|
||||||
|
// out in Travis configuration.
|
||||||
|
var CIconfiguration = {
|
||||||
|
'Chrome': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
|
'Firefox': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
|
// FirefoxBeta and ChromeBeta should be target:'BS' or target:'SL', and required:true
|
||||||
|
// Currently deactivated due to https://github.com/angular/angular/issues/7560
|
||||||
|
'ChromeBeta': {unitTest: {target: null, required: true}, e2e: {target: null, required: false}},
|
||||||
|
'FirefoxBeta': {unitTest: {target: null, required: false}, e2e: {target: null, required: false}},
|
||||||
|
'ChromeDev': {unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
|
||||||
|
'FirefoxDev': {unitTest: {target: null, required: true}, e2e: {target: null, required: true}},
|
||||||
|
'IE9': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'IE10': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
|
'IE11': {unitTest: {target: 'SL', required: true}, e2e: {target: null, required: true}},
|
||||||
|
'Edge': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Android4.1': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Android4.2': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Android4.3': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Android4.4': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Android5': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Safari7': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Safari8': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Safari9': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'Safari10': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'iOS7': {unitTest: {target: 'BS', required: true}, e2e: {target: null, required: true}},
|
||||||
|
'iOS8': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'iOS9': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'iOS10': {unitTest: {target: 'SL', required: false}, e2e: {target: null, required: true}},
|
||||||
|
'WindowsPhone': {unitTest: {target: 'BS', required: false}, e2e: {target: null, required: true}}
|
||||||
|
};
|
||||||
|
|
||||||
|
var customLaunchers = {
|
||||||
|
'DartiumWithWebPlatform':
|
||||||
|
{base: 'Dartium', flags: ['--enable-experimental-web-platform-features']},
|
||||||
|
'ChromeNoSandbox': {base: 'Chrome', flags: ['--no-sandbox']},
|
||||||
|
'SL_CHROME': {base: 'SauceLabs', browserName: 'chrome', version: '54'},
|
||||||
|
'SL_CHROMEBETA': {base: 'SauceLabs', browserName: 'chrome', version: 'beta'},
|
||||||
|
'SL_CHROMEDEV': {base: 'SauceLabs', browserName: 'chrome', version: 'dev'},
|
||||||
|
'SL_FIREFOX': {base: 'SauceLabs', browserName: 'firefox', version: '50'},
|
||||||
|
'SL_FIREFOXBETA': {base: 'SauceLabs', browserName: 'firefox', version: 'beta'},
|
||||||
|
'SL_FIREFOXDEV': {base: 'SauceLabs', browserName: 'firefox', version: 'dev'},
|
||||||
|
'SL_SAFARI7': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.9', version: '7.0'},
|
||||||
|
'SL_SAFARI8': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.10', version: '8.0'},
|
||||||
|
'SL_SAFARI9': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.11', version: '9.0'},
|
||||||
|
'SL_SAFARI10':
|
||||||
|
{base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.12', version: '10.0'},
|
||||||
|
'SL_IOS7': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '7.1'},
|
||||||
|
'SL_IOS8': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '8.4'},
|
||||||
|
'SL_IOS9': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '9.3'},
|
||||||
|
'SL_IOS10': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '10.0'},
|
||||||
|
'SL_IE9':
|
||||||
|
{base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 2008', version: '9'},
|
||||||
|
'SL_IE10': {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'internet explorer',
|
||||||
|
platform: 'Windows 2012',
|
||||||
|
version: '10'
|
||||||
|
},
|
||||||
|
'SL_IE11':
|
||||||
|
{base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 8.1', version: '11'},
|
||||||
|
'SL_EDGE': {
|
||||||
|
base: 'SauceLabs',
|
||||||
|
browserName: 'MicrosoftEdge',
|
||||||
|
platform: 'Windows 10',
|
||||||
|
version: '13.10586'
|
||||||
|
},
|
||||||
|
'SL_ANDROID4.1': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.1'},
|
||||||
|
'SL_ANDROID4.2': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.2'},
|
||||||
|
'SL_ANDROID4.3': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.3'},
|
||||||
|
'SL_ANDROID4.4': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.4'},
|
||||||
|
'SL_ANDROID5': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '5.1'},
|
||||||
|
|
||||||
|
'BS_CHROME': {base: 'BrowserStack', browser: 'chrome', os: 'OS X', os_version: 'Yosemite'},
|
||||||
|
'BS_FIREFOX': {base: 'BrowserStack', browser: 'firefox', os: 'Windows', os_version: '10'},
|
||||||
|
'BS_SAFARI7': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'Mavericks'},
|
||||||
|
'BS_SAFARI8': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'Yosemite'},
|
||||||
|
'BS_SAFARI9': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'El Capitan'},
|
||||||
|
'BS_SAFARI10': {base: 'BrowserStack', browser: 'safari', os: 'OS X', os_version: 'Sierra'},
|
||||||
|
'BS_IOS7': {base: 'BrowserStack', device: 'iPhone 5S', os: 'ios', os_version: '7.0'},
|
||||||
|
'BS_IOS8': {base: 'BrowserStack', device: 'iPhone 6', os: 'ios', os_version: '8.3'},
|
||||||
|
'BS_IOS9': {base: 'BrowserStack', device: 'iPhone 6S', os: 'ios', os_version: '9.1'},
|
||||||
|
'BS_IOS10': {base: 'BrowserStack', device: 'iPhone SE', os: 'ios', os_version: '10.0'},
|
||||||
|
'BS_IE9':
|
||||||
|
{base: 'BrowserStack', browser: 'ie', browser_version: '9.0', os: 'Windows', os_version: '7'},
|
||||||
|
'BS_IE10': {
|
||||||
|
base: 'BrowserStack',
|
||||||
|
browser: 'ie',
|
||||||
|
browser_version: '10.1',
|
||||||
|
os: 'Windows',
|
||||||
|
os_version: '8'
|
||||||
|
},
|
||||||
|
'BS_IE11': {
|
||||||
|
base: 'BrowserStack',
|
||||||
|
browser: 'ie',
|
||||||
|
browser_version: '11.0',
|
||||||
|
os: 'Windows',
|
||||||
|
os_version: '10'
|
||||||
|
},
|
||||||
|
'BS_EDGE': {base: 'BrowserStack', browser: 'edge', os: 'Windows', os_version: '10'},
|
||||||
|
'BS_WINDOWSPHONE':
|
||||||
|
{base: 'BrowserStack', device: 'Nokia Lumia 930', os: 'winphone', os_version: '8.1'},
|
||||||
|
'BS_ANDROID5': {base: 'BrowserStack', device: 'Google Nexus 5', os: 'android', os_version: '5.0'},
|
||||||
|
'BS_ANDROID4.4': {base: 'BrowserStack', device: 'HTC One M8', os: 'android', os_version: '4.4'},
|
||||||
|
'BS_ANDROID4.3':
|
||||||
|
{base: 'BrowserStack', device: 'Samsung Galaxy S4', os: 'android', os_version: '4.3'},
|
||||||
|
'BS_ANDROID4.2':
|
||||||
|
{base: 'BrowserStack', device: 'Google Nexus 4', os: 'android', os_version: '4.2'},
|
||||||
|
'BS_ANDROID4.1':
|
||||||
|
{base: 'BrowserStack', device: 'Google Nexus 7', os: 'android', os_version: '4.1'}
|
||||||
|
};
|
||||||
|
|
||||||
|
var sauceAliases = {
|
||||||
|
'ALL': Object.keys(customLaunchers).filter(function(item) {
|
||||||
|
return customLaunchers[item].base == 'SauceLabs';
|
||||||
|
}),
|
||||||
|
'DESKTOP': [
|
||||||
|
'SL_CHROME', 'SL_FIREFOX', 'SL_IE9', 'SL_IE10', 'SL_IE11', 'SL_EDGE', 'SL_SAFARI7',
|
||||||
|
'SL_SAFARI8', 'SL_SAFARI9', 'SL_SAFARI10'
|
||||||
|
],
|
||||||
|
'MOBILE': [
|
||||||
|
'SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5', 'SL_IOS7',
|
||||||
|
'SL_IOS8', 'SL_IOS9', 'SL_IOS10'
|
||||||
|
],
|
||||||
|
'ANDROID': ['SL_ANDROID4.1', 'SL_ANDROID4.2', 'SL_ANDROID4.3', 'SL_ANDROID4.4', 'SL_ANDROID5'],
|
||||||
|
'IE': ['SL_IE9', 'SL_IE10', 'SL_IE11'],
|
||||||
|
'IOS': ['SL_IOS7', 'SL_IOS8', 'SL_IOS9', 'SL_IOS10'],
|
||||||
|
'SAFARI': ['SL_SAFARI7', 'SL_SAFARI8', 'SL_SAFARI9', 'SL_SAFARI10'],
|
||||||
|
'BETA': ['SL_CHROMEBETA', 'SL_FIREFOXBETA'],
|
||||||
|
'DEV': ['SL_CHROMEDEV', 'SL_FIREFOXDEV'],
|
||||||
|
'CI_REQUIRED': buildConfiguration('unitTest', 'SL', true),
|
||||||
|
'CI_OPTIONAL': buildConfiguration('unitTest', 'SL', false)
|
||||||
|
};
|
||||||
|
|
||||||
|
var browserstackAliases = {
|
||||||
|
'ALL': Object.keys(customLaunchers).filter(function(item) {
|
||||||
|
return customLaunchers[item].base == 'BrowserStack';
|
||||||
|
}),
|
||||||
|
'DESKTOP': [
|
||||||
|
'BS_CHROME', 'BS_FIREFOX', 'BS_IE9', 'BS_IE10', 'BS_IE11', 'BS_EDGE', 'BS_SAFARI7',
|
||||||
|
'BS_SAFARI8', 'BS_SAFARI9', 'BS_SAFARI10'
|
||||||
|
],
|
||||||
|
'MOBILE': [
|
||||||
|
'BS_ANDROID4.3', 'BS_ANDROID4.4', 'BS_IOS7', 'BS_IOS8', 'BS_IOS9', 'BS_IOS10', 'BS_WINDOWSPHONE'
|
||||||
|
],
|
||||||
|
'ANDROID': ['BS_ANDROID4.3', 'BS_ANDROID4.4'],
|
||||||
|
'IE': ['BS_IE9', 'BS_IE10', 'BS_IE11'],
|
||||||
|
'IOS': ['BS_IOS7', 'BS_IOS8', 'BS_IOS9', 'BS_IOS10'],
|
||||||
|
'SAFARI': ['BS_SAFARI7', 'BS_SAFARI8', 'BS_SAFARI9', 'BS_SAFARI10'],
|
||||||
|
'CI_REQUIRED': buildConfiguration('unitTest', 'BS', true),
|
||||||
|
'CI_OPTIONAL': buildConfiguration('unitTest', 'BS', false)
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
customLaunchers: customLaunchers,
|
||||||
|
sauceAliases: sauceAliases,
|
||||||
|
browserstackAliases: browserstackAliases
|
||||||
|
};
|
||||||
|
|
||||||
|
function buildConfiguration(type, target, required) {
|
||||||
|
return Object.keys(CIconfiguration)
|
||||||
|
.filter((item) => {
|
||||||
|
var conf = CIconfiguration[item][type];
|
||||||
|
return conf.required === required && conf.target === target;
|
||||||
|
})
|
||||||
|
.map((item) => target + '_' + item.toUpperCase());
|
||||||
|
}
|
249
build.sh
Executable file
249
build.sh
Executable file
@ -0,0 +1,249 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e -o pipefail
|
||||||
|
|
||||||
|
cd `dirname $0`
|
||||||
|
|
||||||
|
PACKAGES=(core
|
||||||
|
compiler
|
||||||
|
common
|
||||||
|
forms
|
||||||
|
platform-browser
|
||||||
|
platform-browser-dynamic
|
||||||
|
platform-server
|
||||||
|
platform-webworker
|
||||||
|
platform-webworker-dynamic
|
||||||
|
http
|
||||||
|
upgrade
|
||||||
|
router
|
||||||
|
compiler-cli
|
||||||
|
language-service
|
||||||
|
benchpress)
|
||||||
|
BUILD_ALL=true
|
||||||
|
BUNDLE=true
|
||||||
|
VERSION_PREFIX=$(node -p "require('./package.json').version")
|
||||||
|
VERSION_SUFFIX="-$(git log --oneline -1 | awk '{print $1}')"
|
||||||
|
ROUTER_VERSION_PREFIX=$(node -p "require('./package.json').version.replace(/^2/, '3')")
|
||||||
|
REMOVE_BENCHPRESS=false
|
||||||
|
|
||||||
|
for ARG in "$@"; do
|
||||||
|
case "$ARG" in
|
||||||
|
--packages=*)
|
||||||
|
PACKAGES_STR=${ARG#--packages=}
|
||||||
|
PACKAGES=( ${PACKAGES_STR//,/ } )
|
||||||
|
BUILD_ALL=false
|
||||||
|
;;
|
||||||
|
--bundle=*)
|
||||||
|
BUNDLE=( "${ARG#--bundle=}" )
|
||||||
|
;;
|
||||||
|
--publish)
|
||||||
|
VERSION_SUFFIX=""
|
||||||
|
REMOVE_BENCHPRESS=true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option $ARG."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
VERSION="${VERSION_PREFIX}${VERSION_SUFFIX}"
|
||||||
|
ROUTER_VERSION="${ROUTER_VERSION_PREFIX}${VERSION_SUFFIX}"
|
||||||
|
echo "====== BUILDING: Version ${VERSION} (Router ${ROUTER_VERSION})"
|
||||||
|
|
||||||
|
export NODE_PATH=${NODE_PATH}:$(pwd)/dist/all:$(pwd)/dist/tools
|
||||||
|
TSC="node --max-old-space-size=3000 dist/tools/@angular/tsc-wrapped/src/main"
|
||||||
|
UGLIFYJS=`pwd`/node_modules/.bin/uglifyjs
|
||||||
|
TSCONFIG=./tools/tsconfig.json
|
||||||
|
echo "====== (tools)COMPILING: \$(npm bin)/tsc -p ${TSCONFIG} ====="
|
||||||
|
rm -rf ./dist/tools/
|
||||||
|
mkdir -p ./dist/tools/
|
||||||
|
$(npm bin)/tsc -p ${TSCONFIG}
|
||||||
|
|
||||||
|
cp ./tools/@angular/tsc-wrapped/package.json ./dist/tools/@angular/tsc-wrapped
|
||||||
|
|
||||||
|
if [[ ${BUILD_ALL} == true ]]; then
|
||||||
|
rm -rf ./dist/all/
|
||||||
|
mkdir -p ./dist/all/
|
||||||
|
|
||||||
|
echo "====== Copying files needed for e2e tests ====="
|
||||||
|
cp -r ./modules/playground ./dist/all/
|
||||||
|
cp -r ./modules/playground/favicon.ico ./dist/
|
||||||
|
#rsync -aP ./modules/playground/* ./dist/all/playground/
|
||||||
|
mkdir ./dist/all/playground/vendor
|
||||||
|
cd ./dist/all/playground/vendor
|
||||||
|
ln -s ../../../../node_modules/core-js/client/core.js .
|
||||||
|
ln -s ../../../../node_modules/zone.js/dist/zone.js .
|
||||||
|
ln -s ../../../../node_modules/zone.js/dist/long-stack-trace-zone.js .
|
||||||
|
ln -s ../../../../node_modules/systemjs/dist/system.src.js .
|
||||||
|
ln -s ../../../../node_modules/base64-js .
|
||||||
|
ln -s ../../../../node_modules/reflect-metadata/Reflect.js .
|
||||||
|
ln -s ../../../../node_modules/rxjs .
|
||||||
|
ln -s ../../../../node_modules/angular/angular.js .
|
||||||
|
ln -s ../../../../node_modules/hammerjs/hammer.js .
|
||||||
|
cd -
|
||||||
|
|
||||||
|
echo "====== Copying files needed for benchmarks ====="
|
||||||
|
cp -r ./modules/benchmarks ./dist/all/
|
||||||
|
cp -r ./modules/benchmarks/favicon.ico ./dist/
|
||||||
|
mkdir ./dist/all/benchmarks/vendor
|
||||||
|
cd ./dist/all/benchmarks/vendor
|
||||||
|
ln -s ../../../../node_modules/core-js/client/core.js .
|
||||||
|
ln -s ../../../../node_modules/zone.js/dist/zone.js .
|
||||||
|
ln -s ../../../../node_modules/zone.js/dist/long-stack-trace-zone.js .
|
||||||
|
ln -s ../../../../node_modules/systemjs/dist/system.src.js .
|
||||||
|
ln -s ../../../../node_modules/reflect-metadata/Reflect.js .
|
||||||
|
ln -s ../../../../node_modules/rxjs .
|
||||||
|
ln -s ../../../../node_modules/angular/angular.js .
|
||||||
|
ln -s ../../../../bower_components/polymer .
|
||||||
|
ln -s ../../../../node_modules/incremental-dom/dist/incremental-dom-cjs.js
|
||||||
|
cd -
|
||||||
|
|
||||||
|
TSCONFIG=./modules/tsconfig.json
|
||||||
|
echo "====== (all)COMPILING: \$(npm bin)/tsc -p ${TSCONFIG} ====="
|
||||||
|
# compile ts code
|
||||||
|
$TSC -p modules/tsconfig.json
|
||||||
|
|
||||||
|
rm -rf ./dist/packages-dist
|
||||||
|
fi
|
||||||
|
|
||||||
|
for PACKAGE in ${PACKAGES[@]}
|
||||||
|
do
|
||||||
|
PWD=`pwd`
|
||||||
|
SRCDIR=${PWD}/modules/@angular/${PACKAGE}
|
||||||
|
DESTDIR=${PWD}/dist/packages-dist/${PACKAGE}
|
||||||
|
ES2015_DESTDIR=${PWD}/dist/packages-dist-es2015/${PACKAGE}
|
||||||
|
UMD_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}.umd.js
|
||||||
|
UMD_TESTING_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-testing.umd.js
|
||||||
|
UMD_STATIC_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-static.umd.js
|
||||||
|
UMD_UPGRADE_ES5_PATH=${DESTDIR}/bundles/${PACKAGE}-upgrade.umd.js
|
||||||
|
UMD_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}.umd.min.js
|
||||||
|
UMD_STATIC_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}-static.umd.min.js
|
||||||
|
UMD_UPGRADE_ES5_MIN_PATH=${DESTDIR}/bundles/${PACKAGE}-upgrade.umd.min.js
|
||||||
|
|
||||||
|
if [[ ${PACKAGE} != router ]]; then
|
||||||
|
LICENSE_BANNER=${PWD}/modules/@angular/license-banner.txt
|
||||||
|
fi
|
||||||
|
if [[ ${PACKAGE} == router ]]; then
|
||||||
|
LICENSE_BANNER=${PWD}/modules/@angular/router-license-banner.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf ${DESTDIR}
|
||||||
|
|
||||||
|
echo "====== COMPILING: ${TSC} -p ${SRCDIR}/tsconfig-build.json ====="
|
||||||
|
$TSC -p ${SRCDIR}/tsconfig-build.json
|
||||||
|
# ES2015 distro is not ready yet; don't slow down all builds for it
|
||||||
|
# TODO(alexeagle,igorminar): figure out ES2015 story and enable
|
||||||
|
if [[ -n "${EXPERIMENTAL_ES2015_DISTRO}" ]]; then
|
||||||
|
$TSC -p ${SRCDIR}/tsconfig-build.json --target es2015 --outDir ${ES2015_DESTDIR}
|
||||||
|
cp ${SRCDIR}/package.json ${ES2015_DESTDIR}/
|
||||||
|
cp ${PWD}/modules/@angular/README.md ${ES2015_DESTDIR}/
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e ${SRCDIR}/tsconfig-upgrade.json ]]; then
|
||||||
|
echo "====== COMPILING: ${TSC} -p ${SRCDIR}/tsconfig-upgrade.json ====="
|
||||||
|
$TSC -p ${SRCDIR}/tsconfig-upgrade.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
cp ${SRCDIR}/package.json ${DESTDIR}/
|
||||||
|
cp ${PWD}/modules/@angular/README.md ${DESTDIR}/
|
||||||
|
|
||||||
|
if [[ -e ${SRCDIR}/tsconfig-testing.json ]]; then
|
||||||
|
echo "====== COMPILING TESTING: ${TSC} -p ${SRCDIR}/tsconfig-testing.json"
|
||||||
|
$TSC -p ${SRCDIR}/tsconfig-testing.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e ${SRCDIR}/tsconfig-2015.json ]]; then
|
||||||
|
echo "====== COMPILING ESM: ${TSC} -p ${SRCDIR}/tsconfig-2015.json"
|
||||||
|
${TSC} -p ${SRCDIR}/tsconfig-2015.json
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "====== TSC 1.8 d.ts compat for ${DESTDIR} ====="
|
||||||
|
# safely strips 'readonly' specifier from d.ts files to make them compatible with tsc 1.8
|
||||||
|
if [ "$(uname)" == "Darwin" ]; then
|
||||||
|
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i '' -e 's/\(^ *(static |private )*\)*readonly */\1/g'
|
||||||
|
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i '' -e 's/\/\/\/ <reference types="node" \/>//g'
|
||||||
|
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i '' -E 's/^( +)abstract ([[:alnum:]]+\:)/\1\2/g'
|
||||||
|
else
|
||||||
|
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -e 's/\(^ *(static |private )*\)*readonly */\1/g'
|
||||||
|
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -e 's/\/\/\/ <reference types="node" \/>//g'
|
||||||
|
find ${DESTDIR} -type f -name '*.d.ts' -print0 | xargs -0 sed -i -E 's/^( +)abstract ([[:alnum:]]+\:)/\1\2/g'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${PACKAGE} == benchpress ]]; then
|
||||||
|
cp ${SRCDIR}/*.md ${DESTDIR}
|
||||||
|
cp -r ${SRCDIR}/docs ${DESTDIR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${BUNDLE} == true && ${PACKAGE} != compiler-cli && ${PACKAGE} != benchpress ]]; then
|
||||||
|
|
||||||
|
echo "====== BUNDLING: ${SRCDIR} ====="
|
||||||
|
mkdir ${DESTDIR}/bundles
|
||||||
|
|
||||||
|
(
|
||||||
|
cd ${SRCDIR}
|
||||||
|
echo "====== Rollup ${PACKAGE} index"
|
||||||
|
../../../node_modules/.bin/rollup -c rollup.config.js
|
||||||
|
cat ${LICENSE_BANNER} > ${UMD_ES5_PATH}.tmp
|
||||||
|
cat ${UMD_ES5_PATH} >> ${UMD_ES5_PATH}.tmp
|
||||||
|
mv ${UMD_ES5_PATH}.tmp ${UMD_ES5_PATH}
|
||||||
|
$UGLIFYJS -c --screw-ie8 --comments -o ${UMD_ES5_MIN_PATH} ${UMD_ES5_PATH}
|
||||||
|
|
||||||
|
if [[ -e rollup-testing.config.js ]]; then
|
||||||
|
echo "====== Rollup ${PACKAGE} testing"
|
||||||
|
../../../node_modules/.bin/rollup -c rollup-testing.config.js
|
||||||
|
echo "{\"main\": \"../bundles/${PACKAGE}-testing.umd.js\"}" > ${DESTDIR}/testing/package.json
|
||||||
|
cat ${LICENSE_BANNER} > ${UMD_TESTING_ES5_PATH}.tmp
|
||||||
|
cat ${UMD_TESTING_ES5_PATH} >> ${UMD_TESTING_ES5_PATH}.tmp
|
||||||
|
mv ${UMD_TESTING_ES5_PATH}.tmp ${UMD_TESTING_ES5_PATH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e rollup-static.config.js ]]; then
|
||||||
|
echo "====== Rollup ${PACKAGE} static"
|
||||||
|
../../../node_modules/.bin/rollup -c rollup-static.config.js
|
||||||
|
# create dir because it doesn't exist yet, we should move the src code here and remove this line
|
||||||
|
mkdir ${DESTDIR}/static
|
||||||
|
echo "{\"main\": \"../bundles/${PACKAGE}-static.umd.js\"}" > ${DESTDIR}/static/package.json
|
||||||
|
cat ${LICENSE_BANNER} > ${UMD_STATIC_ES5_PATH}.tmp
|
||||||
|
cat ${UMD_STATIC_ES5_PATH} >> ${UMD_STATIC_ES5_PATH}.tmp
|
||||||
|
mv ${UMD_STATIC_ES5_PATH}.tmp ${UMD_STATIC_ES5_PATH}
|
||||||
|
$UGLIFYJS -c --screw-ie8 --comments -o ${UMD_STATIC_ES5_MIN_PATH} ${UMD_STATIC_ES5_PATH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -e rollup-upgrade.config.js ]]; then
|
||||||
|
echo "====== Rollup ${PACKAGE} upgrade"
|
||||||
|
../../../node_modules/.bin/rollup -c rollup-upgrade.config.js
|
||||||
|
# create dir because it doesn't exist yet, we should move the src code here and remove this line
|
||||||
|
mkdir ${DESTDIR}/upgrade
|
||||||
|
echo "{\"main\": \"../bundles/${PACKAGE}-upgrade.umd.js\"}" > ${DESTDIR}/upgrade/package.json
|
||||||
|
cat ${LICENSE_BANNER} > ${UMD_UPGRADE_ES5_PATH}.tmp
|
||||||
|
cat ${UMD_UPGRADE_ES5_PATH} >> ${UMD_UPGRADE_ES5_PATH}.tmp
|
||||||
|
mv ${UMD_UPGRADE_ES5_PATH}.tmp ${UMD_UPGRADE_ES5_PATH}
|
||||||
|
$UGLIFYJS -c --screw-ie8 --comments -o ${UMD_UPGRADE_ES5_MIN_PATH} ${UMD_UPGRADE_ES5_PATH}
|
||||||
|
fi
|
||||||
|
) 2>&1 | grep -v "as external dependency"
|
||||||
|
|
||||||
|
if [[ -n "${EXPERIMENTAL_ES2015_DISTRO}" ]]; then
|
||||||
|
cp -prv ${DESTDIR}/bundles ${ES2015_DESTDIR}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
(
|
||||||
|
echo "====== VERSION: Updating version references"
|
||||||
|
cd ${DESTDIR}
|
||||||
|
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-PLACEHOLDER/${VERSION}/g\" $""(grep -ril 0\.0\.0\-PLACEHOLDER .)"
|
||||||
|
perl -p -i -e "s/0\.0\.0\-PLACEHOLDER/${VERSION}/g" $(grep -ril 0\.0\.0\-PLACEHOLDER .) < /dev/null 2> /dev/null
|
||||||
|
echo "====== EXECUTE: perl -p -i -e \"s/0\.0\.0\-ROUTERPLACEHOLDER/${ROUTER_VERSION}/g\" $""(grep -ril 0\.0\.0\-ROUTERPLACEHOLDER .)"
|
||||||
|
perl -p -i -e "s/0\.0\.0\-ROUTERPLACEHOLDER/${ROUTER_VERSION}/g" $(grep -ril 0\.0\.0\-ROUTERPLACEHOLDER .) < /dev/null 2> /dev/null
|
||||||
|
)
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "====== Building examples: ./modules/@angular/examples/build.sh ====="
|
||||||
|
./modules/@angular/examples/build.sh
|
||||||
|
|
||||||
|
if [[ ${REMOVE_BENCHPRESS} == true ]]; then
|
||||||
|
echo ""
|
||||||
|
echo "==== Removing benchpress from publication"
|
||||||
|
rm -r dist/packages-dist/benchpress
|
||||||
|
fi
|
11
circle.yml
Normal file
11
circle.yml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
machine:
|
||||||
|
node:
|
||||||
|
version: 5.4.1
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
pre:
|
||||||
|
- npm install -g npm@3.6.0
|
||||||
|
|
||||||
|
test:
|
||||||
|
override:
|
||||||
|
- gulp lint
|
40
docs/PUBLIC_API.md
Normal file
40
docs/PUBLIC_API.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Supported Public API Surface of Angular
|
||||||
|
|
||||||
|
Our SemVer, timed-release cycle and deprecation policy currently applies to these npm packages:
|
||||||
|
|
||||||
|
- `@angular/core`
|
||||||
|
- `@angular/common`
|
||||||
|
- `@angular/platform-browser`
|
||||||
|
- `@angular/platform-browser-dynamic`
|
||||||
|
- `@angular/platform-server`
|
||||||
|
- `@angular/platform-webworker`
|
||||||
|
- `@angular/platform-webworker-dynamic`
|
||||||
|
- `@angular/upgrade`
|
||||||
|
- `@angular/router`
|
||||||
|
- `@angular/forms`
|
||||||
|
- `@angular/http`
|
||||||
|
|
||||||
|
|
||||||
|
One intentional omission from this list is `@angular/compiler`, which is currently considered a low level api and is subject to internal changes. These changes will not affect any applications or libraries using the higher-level apis (the command line interface or JIT compilation via `@angular/platform-browser-dynamic`). Only very specific use-cases require direct access to the compiler API (mostly tooling integration for IDEs, linters, etc). If you are working on this kind of integration, please reach out to us first.
|
||||||
|
|
||||||
|
Additionally only the command line usage (not direct use of APIs) of `@angular/compiler-cli` is covered.
|
||||||
|
|
||||||
|
Other projects developed by the Angular team like angular-cli, Angular Material, benchpress, will be covered by these or similar guarantees in the future as they mature.
|
||||||
|
|
||||||
|
Within the supported packages, we provide guarantees for:
|
||||||
|
|
||||||
|
- symbols exported via the main entry point (e.g. `@angular/core`) and testing entry point (e.g. `@angular/core/testing`). This applies to both runtime/JavaScript values and TypeScript types.
|
||||||
|
- symbols exported via global namespace `ng` (e.g. `ng.core`)
|
||||||
|
- bundles located in the `bundles/` directory of our npm packages (e.g. `@angular/core/bundles/core.umd.js`)
|
||||||
|
|
||||||
|
|
||||||
|
We explicitly don't consider the following to be our public API surface:
|
||||||
|
|
||||||
|
- any file/import paths within our package except for the `/`, `/testing` and `/bundles/*`
|
||||||
|
- constructors of injectable classes (services and directives) - please use DI to obtain instances of these classes
|
||||||
|
- any class members or symbols marked as `private` or prefixed with underscore
|
||||||
|
- extending any of our classes unless the support for this is specifically documented in the API docs
|
||||||
|
- the contents and API surface of the code generated by Angular's compiler (with one notable exception: the existence and name of `NgModuleFactory` instances exported from generated code is guaranteed)
|
||||||
|
|
||||||
|
|
||||||
|
Our peer dependencies (e.g. typescript, zone.js, or rxjs) are not considered part of our API surface, but they are included in our SemVer policies. We might update the required version of any of these dependencies in minor releases if the update doesn't cause breaking changes for Angular applications. Peer dependency updates that result in non-trivial breaking changes must be deferred to major Angular releases.
|
82
docs/RELEASE_SCHEDULE.md
Normal file
82
docs/RELEASE_SCHEDULE.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
# Angular Release Schedule
|
||||||
|
|
||||||
|
This document contains historic record of past Angular releases and future release schedule.
|
||||||
|
|
||||||
|
The purpose of this document is to assist coordination among the Angular team, Angular contributors, Angular application teams, and Angular community projects.
|
||||||
|
|
||||||
|
We'll keep this doc up to date when unplanned releases or other schedule changes occur.
|
||||||
|
|
||||||
|
|
||||||
|
## Schedule Caveats and Exceptions
|
||||||
|
|
||||||
|
The dates listed here are approximate – last minute issues, team or community events, etc. can cause us to release a few days sooner or later.
|
||||||
|
|
||||||
|
This page contains only planned and past unplanned releases.
|
||||||
|
Due to serious regressions or other important reasons we reserve the right to release an unplanned patch or minor release.
|
||||||
|
In such case, we'll update this document accordingly.
|
||||||
|
|
||||||
|
The dates past March 2017 are just a guidance and might be adjusted slightly if necessary.
|
||||||
|
|
||||||
|
|
||||||
|
## Tentative Schedule Until March 2017
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The table below is formatted so that it's easy to read and edit in both markdown and rendered html form.
|
||||||
|
|
||||||
|
In order to deal with undesirable line breaks, two special characters are occasionally used:
|
||||||
|
|
||||||
|
- non-breaking hyphen: "‑" http://www.fileformat.info/info/unicode/char/2011/index.htm
|
||||||
|
- non-breaking space: " " http://www.fileformat.info/info/unicode/char/00a0/index.htm
|
||||||
|
|
||||||
|
If you see undesirable wrapping issues in the rendered form, please copy&paste the quoted characters and use them in the table below where needed.
|
||||||
|
-->
|
||||||
|
|
||||||
|
Week Of | Stable Release<br>(@latest npm tag) | Beta/RC Release<br>(@next npm tag) | Note
|
||||||
|
------------- | ----------------------------------- | ---------------------------------- | ---------------------
|
||||||
|
2016-09-14 | 2.0.0 | - | Major Version Release
|
||||||
|
2016-09-21 | 2.0.1 | 2.1.0-beta.0 |
|
||||||
|
2016‑09‑28 | - | - | Angular Connect
|
||||||
|
2016-10-05 | 2.0.2 | 2.1.0-rc.0 |
|
||||||
|
2016-10-12 | 2.1.0 | - | Minor Version Release
|
||||||
|
2016-10-19 | 2.1.1 | 2.2.0-beta.0 |
|
||||||
|
2016-10-26 | 2.1.2 | 2.2.0-beta.1 |
|
||||||
|
2016-11-02 | 2.1.3 | 2.2.0-rc.0 |
|
||||||
|
2016-11-09 | 2.2.0 | - | Minor Version Release
|
||||||
|
2016-11-16 | 2.2.1 | 2.3.0-beta.0 |
|
||||||
|
2016-11-23 | 2.2.2 | 2.3.0-beta.1 |
|
||||||
|
*2016-11-23* | *2.2.3* | - | *Unplanned Patch Release to fix regressions*
|
||||||
|
2016-11-30 | 2.2.4 | 2.3.0-rc.0 |
|
||||||
|
2016-12-07 | 2.3.0 | - | Minor Version Release
|
||||||
|
2016-12-14 | 2.3.1 | 4.0.0-beta.0 |
|
||||||
|
*2016-12-21* | *2.4.0* | - | *Unplanned Minor Release due to release of RxJS 5.0.0*
|
||||||
|
2016-12-21 | 2.4.1 | 4.0.0-beta.1 |
|
||||||
|
2016-12-28 | - | - | Holiday Break
|
||||||
|
2017-01-04 | 2.4.2 | 4.0.0-beta.2 |
|
||||||
|
2017-01-11 | 2.4.3 | 4.0.0-beta.3 |
|
||||||
|
2017-01-18 | 2.4.4 | 4.0.0-beta.4 |
|
||||||
|
2017-01-25 | 2.4.5 | 4.0.0-beta.5 |
|
||||||
|
2017-02-01 | 2.4.6 | 4.0.0-beta.6 |
|
||||||
|
2017-02-08 | 2.4.7 | 4.0.0-rc.0 |
|
||||||
|
2017-02-15 | 2.4.8 | 4.0.0-rc.1 |
|
||||||
|
2017-02-22 | 2.4.9 | 4.0.0-rc.2 |
|
||||||
|
2017-03-01 | 2.4.10 | 4.0.0-rc.3 |
|
||||||
|
2017-03-08 | 4.0.0 + 2.4.11 | - | Major Version Release
|
||||||
|
|
||||||
|
|
||||||
|
## Tentative Schedule After March 2017
|
||||||
|
|
||||||
|
Date | Stable Release | Compatibility`*`
|
||||||
|
---------------------- | -------------- | ----------------
|
||||||
|
September/October 2017 | 5.0.0 | ^4.0.0
|
||||||
|
March 2018 | 6.0.0 | ^5.0.0
|
||||||
|
September/October 2018 | 7.0.0 | ^6.0.0
|
||||||
|
|
||||||
|
`*` The goal of the backwards compatibility promise, is to ensure that changes in the core framework and tooling don't break the existing ecosystem of components and applications and don't put undue upgrade/migration burden on Angular application and component authors.
|
||||||
|
|
||||||
|
|
||||||
|
## More Info & Resources
|
||||||
|
|
||||||
|
In [September 2016 we announced](http://angularjs.blogspot.com/2016/10/versioning-and-releasing-angular.html) that Angular is fully adopting [semantic versioning](http://semver.org/) and that we'll be releasing patch versions on a weekly basis (~50 per year), minor versions monthly for 3 months following a major version release, and every 6 months we'll release a major version that will be backwards compatible with the previous release for most developers, but might remove APIs that have been deprecated two major versions ago (6 or more months ago).
|
||||||
|
|
||||||
|
In [December 2016 we clarified this message](http://angularjs.blogspot.com/2016/12/ok-let-me-explain-its-going-to-be.html), and provided additional details about the plans to release Angular 4.0.0 in March 2017.
|
||||||
|
This document contains updates to the schedule that happened since then.
|
@ -1,366 +0,0 @@
|
|||||||
|
|
||||||
.hide { display: none !important; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
overflow: hidden;
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #3f51b5;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
max-width: 100%;
|
|
||||||
width: 100%;
|
|
||||||
border-spacing: 0;
|
|
||||||
border-collapse: collapse;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
padding: $baseline-grid ($baseline-grid * 2);
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
border-bottom: 2px solid #ddd;
|
|
||||||
vertical-align: bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
white-space: pre;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md-sidenav-inner {
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-content,
|
|
||||||
.doc-content {
|
|
||||||
max-width: 864px;
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
.layout-label {
|
|
||||||
width: 120px;
|
|
||||||
}
|
|
||||||
.layout-content code.highlight {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-item {
|
|
||||||
background: none;
|
|
||||||
border-width: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
display: block;
|
|
||||||
color: #333;
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: 40px;
|
|
||||||
max-height: 40px;
|
|
||||||
opacity: 1;
|
|
||||||
margin: 0;
|
|
||||||
outline: none;
|
|
||||||
padding: 0px 28px;
|
|
||||||
position: relative;
|
|
||||||
text-align: left;
|
|
||||||
text-decoration: none;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 1;
|
|
||||||
-webkit-transition: 0.45s cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
-webkit-transition-property: max-height, background-color, opacity;
|
|
||||||
-moz-transition: 0.45s cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
-moz-transition-property: max-height, background-color, opacity;
|
|
||||||
transition: 0.45s cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
transition-property: max-height, background-color, opacity;
|
|
||||||
}
|
|
||||||
.menu-item.ng-hide {
|
|
||||||
max-height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.menu-item:hover {
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
.menu-item:focus {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.menu-item.menu-title {
|
|
||||||
color: #888;
|
|
||||||
font-size: 14px;
|
|
||||||
padding-left: 16px;
|
|
||||||
text-align: left;
|
|
||||||
text-transform: uppercase;
|
|
||||||
transition: color 0.35s cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
}
|
|
||||||
.menu-item.menu-title:hover,
|
|
||||||
.menu-item.menu-title.active {
|
|
||||||
color: #1976d2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-icon {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
.app-toolbar .md-toolbar-tools h3 {
|
|
||||||
-webkit-margin-before: 0;
|
|
||||||
-webkit-margin-after: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-container {
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-top: 16px;
|
|
||||||
-webkit-transition: 0.02s padding cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
transition: 0.02s padding cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
position: relative;
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
.demo-source-tabs {
|
|
||||||
z-index: 1;
|
|
||||||
-webkit-transition: all 0.45s cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
transition: all 0.45s cubic-bezier(0.35, 0, 0.25, 1);
|
|
||||||
max-height: 448px;
|
|
||||||
min-height: 448px;
|
|
||||||
background: #fff;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
md-tabs.demo-source-tabs md-tab,
|
|
||||||
md-tabs.demo-source-tabs .md-header {
|
|
||||||
background-color: #444444 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
md-tabs.demo-source-tabs md-tab-label {
|
|
||||||
color: #ccc !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
md-tabs.demo-source-tabs .active md-tab-label {
|
|
||||||
color: #fff !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-source-tabs.ng-hide {
|
|
||||||
max-height: 0px;
|
|
||||||
min-height: 0px;
|
|
||||||
}
|
|
||||||
.demo-source-tabs {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
.demo-content {
|
|
||||||
position: relative;
|
|
||||||
overflow:hidden;
|
|
||||||
min-height: 448px;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -moz-box;
|
|
||||||
display: -moz-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.small-demo .demo-source-tabs:not(.ng-hide) {
|
|
||||||
min-height: 224px;
|
|
||||||
max-height: 224px;
|
|
||||||
}
|
|
||||||
.small-demo .demo-content {
|
|
||||||
min-height: 128px;
|
|
||||||
}
|
|
||||||
.demo-content > * {
|
|
||||||
-webkit-box-flex: 1;
|
|
||||||
-webkit-flex: 1;
|
|
||||||
-moz-box-flex: 1;
|
|
||||||
-moz-flex: 1;
|
|
||||||
-ms-flex: 1;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-content > div[layout-fill] {
|
|
||||||
min-height: 448px;
|
|
||||||
}
|
|
||||||
.small-demo .demo-content > div[layout-fill] {
|
|
||||||
min-height: 224px;
|
|
||||||
}
|
|
||||||
.small-demo .demo-toolbar,
|
|
||||||
.small-demo .md-toolbar-tools {
|
|
||||||
min-height: 48px;
|
|
||||||
max-height: 48px;
|
|
||||||
font-size: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-source md-toolbar.demo-toolbar {
|
|
||||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.36);
|
|
||||||
}
|
|
||||||
.demo-toolbar .md-button {
|
|
||||||
color: #616161;
|
|
||||||
}
|
|
||||||
|
|
||||||
md-toolbar.demo-toolbar,
|
|
||||||
.demo-source-tabs md-tab,
|
|
||||||
.demo-source-tabs .tabs-header {
|
|
||||||
background: #E0E0E0 !important;
|
|
||||||
color: #616161;
|
|
||||||
}
|
|
||||||
md-toolbar.demo-toolbar md-tab-label {
|
|
||||||
color: #99E4EE
|
|
||||||
}
|
|
||||||
md-toolbar.demo-toolbar .md-button:hover,
|
|
||||||
md-toolbar.demo-toolbar .md-button:focus,
|
|
||||||
md-toolbar.demo-toolbar .md-button.active {
|
|
||||||
background: rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
md-toolbar.demo-toolbar .md-button {
|
|
||||||
-webkit-transition: all 0.3s linear;
|
|
||||||
-moz-transition: all 0.3s linear;
|
|
||||||
transition: all 0.3s linear;
|
|
||||||
}
|
|
||||||
.demo-source-container {
|
|
||||||
display: block;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
background-color: #f6f6f6;
|
|
||||||
height: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-source-content {
|
|
||||||
height: 400px;
|
|
||||||
}
|
|
||||||
.demo-source-content,
|
|
||||||
.demo-source-content pre,
|
|
||||||
.demo-source-content code {
|
|
||||||
background: #f6f6f6;
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
.demo-source-content pre {
|
|
||||||
max-width: 100%;
|
|
||||||
overflow-wrap: break-word;
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-source div[demo-include] {
|
|
||||||
border-top: #ddd solid 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.menu-separator-icon {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.menu-module-name {
|
|
||||||
opacity: 0.6;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************
|
|
||||||
* DOCS
|
|
||||||
************/
|
|
||||||
.api-options-bar .md-button {
|
|
||||||
margin: 4px;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
.api-options-bar .md-button:hover,
|
|
||||||
.api-options-bar .md-button:focus {
|
|
||||||
background: rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
.api-options-bar.with-icon md-icon {
|
|
||||||
position: absolute;
|
|
||||||
top: -3px;
|
|
||||||
left: 2px;
|
|
||||||
}
|
|
||||||
.api-options-bar.with-icon .md-button span {
|
|
||||||
margin-left: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.api-params-item {
|
|
||||||
min-height: 72px;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
.api-params-label {
|
|
||||||
margin-right: 8px;
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 14px;
|
|
||||||
-webkit-align-self: flex-start;
|
|
||||||
-moz-align-self: flex-start;
|
|
||||||
-ms-flex-item-align: start;
|
|
||||||
align-self: flex-start;
|
|
||||||
}
|
|
||||||
.api-params-title {
|
|
||||||
color: #888;
|
|
||||||
}
|
|
||||||
code.api-type {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
ul li {
|
|
||||||
margin-top: 3px;
|
|
||||||
list-style-position: inside;
|
|
||||||
}
|
|
||||||
ul li:first-child {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.layout-title {
|
|
||||||
color: #999999;
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.api-params-content ul {
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
ul.methods > li {
|
|
||||||
margin-bottom: 48px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.methods .method-function-syntax {
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 20px;
|
|
||||||
margin: 0;
|
|
||||||
-webkit-margin-before: 0;
|
|
||||||
-webkit-margin-after: 0;
|
|
||||||
}
|
|
||||||
ul.methods li h3 {
|
|
||||||
/* border-bottom: 1px solid #eee; */
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
ul.methods > li {
|
|
||||||
padding-left: 0;
|
|
||||||
border-left: none;
|
|
||||||
list-style: default;
|
|
||||||
}
|
|
||||||
ul.methods .method-function-syntax {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.version {
|
|
||||||
padding-left: 10px;
|
|
||||||
text-decoration: underline;
|
|
||||||
font-size: 0.95em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.demo-source-container pre,
|
|
||||||
.demo-source-container code {
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
md-content.demo-source-container > hljs > pre > code.highlight {
|
|
||||||
position : absolute;
|
|
||||||
top : 0px;
|
|
||||||
left: 0px;
|
|
||||||
right: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.extraPad {
|
|
||||||
padding-left:32px !important;
|
|
||||||
padding-right:32px !important;
|
|
||||||
}
|
|
@ -1,142 +0,0 @@
|
|||||||
/* GitHub Theme */
|
|
||||||
.prettyprint {
|
|
||||||
background: white;
|
|
||||||
font-family: Menlo, 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Consolas, monospace;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lang-text * {
|
|
||||||
color: #333333!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pln {
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen {
|
|
||||||
.str {
|
|
||||||
color: #dd1144;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kwd {
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.com {
|
|
||||||
color: #999988;
|
|
||||||
}
|
|
||||||
|
|
||||||
.typ {
|
|
||||||
color: #445588;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lit {
|
|
||||||
color: #445588;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pun {
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.opn {
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.clo {
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag {
|
|
||||||
color: navy;
|
|
||||||
}
|
|
||||||
|
|
||||||
.atn {
|
|
||||||
color: teal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.atv {
|
|
||||||
color: #dd1144;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dec {
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.var {
|
|
||||||
color: teal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fun {
|
|
||||||
color: #990000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media print, projection {
|
|
||||||
.str {
|
|
||||||
color: #006600;
|
|
||||||
}
|
|
||||||
|
|
||||||
.kwd {
|
|
||||||
color: #006;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.com {
|
|
||||||
color: #600;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.typ {
|
|
||||||
color: #404;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lit {
|
|
||||||
color: #004444;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pun, .opn, .clo {
|
|
||||||
color: #444400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tag {
|
|
||||||
color: #006;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.atn {
|
|
||||||
color: #440044;
|
|
||||||
}
|
|
||||||
|
|
||||||
.atv {
|
|
||||||
color: #006600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Specify class=linenums on a pre to get line numbering */
|
|
||||||
ol.linenums {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* IE indents via margin-left */
|
|
||||||
li.L0,
|
|
||||||
li.L1,
|
|
||||||
li.L2,
|
|
||||||
li.L3,
|
|
||||||
li.L4,
|
|
||||||
li.L5,
|
|
||||||
li.L6,
|
|
||||||
li.L7,
|
|
||||||
li.L8,
|
|
||||||
li.L9 {
|
|
||||||
/* */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Alternate shading for lines */
|
|
||||||
li.L1,
|
|
||||||
li.L3,
|
|
||||||
li.L5,
|
|
||||||
li.L7,
|
|
||||||
li.L9 {
|
|
||||||
/* */
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Angular 2 Docs</title>
|
|
||||||
<base href="/">
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/lib/angular-material/angular-material.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/prettify-theme.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="/css/app.css">
|
|
||||||
|
|
||||||
<script src="/lib/hammerjs/hammer.js"></script>
|
|
||||||
<script src="/lib/google-code-prettify/src/prettify.js"></script>
|
|
||||||
<script src="/lib/google-code-prettify/src/lang-css.js"></script>
|
|
||||||
<script src="/lib/angular/angular.js"></script>
|
|
||||||
<script src="/lib/angular-animate/angular-animate.js"></script>
|
|
||||||
<script src="/lib/angular-aria/angular-aria.js"></script>
|
|
||||||
<script src="/lib/angular-material/angular-material.js"></script>
|
|
||||||
<script src="/js/navigation-modules.js"></script>
|
|
||||||
<script src="/js/navigation-guides.js"></script>
|
|
||||||
<script src="/js/app.js"></script>
|
|
||||||
<script src="/js/code.js"></script>
|
|
||||||
</head>
|
|
||||||
<body ng-app="app" ng-controller="NavController as nav" layout="column">
|
|
||||||
|
|
||||||
<md-toolbar md-scroll-shrink>
|
|
||||||
<h1 class="md-toolbar-tools">Angular V2</h1>
|
|
||||||
</md-toolbar>
|
|
||||||
|
|
||||||
<section layout="row">
|
|
||||||
|
|
||||||
<md-content>
|
|
||||||
<h2>Navigation</h2>
|
|
||||||
<section ng-repeat="area in nav.areas">
|
|
||||||
<h3>{{ area.name }}</h3>
|
|
||||||
<md-list>
|
|
||||||
<md-item ng-repeat="section in area.sections">
|
|
||||||
<h3><a href="{{section.path}}">{{section.name}}</a></h3>
|
|
||||||
<ul>
|
|
||||||
<li ng-repeat="page in section.pages">
|
|
||||||
<a href="{{page.path}}">{{ page.name }}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</md-item>
|
|
||||||
</md-list>
|
|
||||||
</section>
|
|
||||||
</md-content>
|
|
||||||
|
|
||||||
|
|
||||||
<md-content class="md-padding">
|
|
||||||
<ng-include src="nav.currentPage.partial"></ng-include>
|
|
||||||
</md-content>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,47 +0,0 @@
|
|||||||
angular.module('app', ['ngMaterial', 'navigation-modules', 'navigation-guides', 'code'])
|
|
||||||
|
|
||||||
.config(function($locationProvider) {
|
|
||||||
$locationProvider.html5Mode(true);
|
|
||||||
})
|
|
||||||
|
|
||||||
.controller('NavController', ['$scope', '$location', 'MODULES', 'GUIDES',
|
|
||||||
function($scope, $location, MODULES, GUIDES) {
|
|
||||||
var that = this;
|
|
||||||
|
|
||||||
this.areas = [
|
|
||||||
{ name: 'Guides', sections: [ { pages: GUIDES.pages } ] },
|
|
||||||
{ name: 'Modules', sections: MODULES.sections }
|
|
||||||
];
|
|
||||||
|
|
||||||
this.updateCurrentPage = function(path) {
|
|
||||||
path = path.replace(/^\//, '');
|
|
||||||
console.log('path', path);
|
|
||||||
this.currentPage = null;
|
|
||||||
|
|
||||||
this.areas.forEach(function(area) {
|
|
||||||
area.sections.forEach(function(section) {
|
|
||||||
|
|
||||||
// Short-circuit out if the page has been found
|
|
||||||
if ( that.currentPage ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (section.path === path) {
|
|
||||||
console.log('found!');
|
|
||||||
that.currentPage = section;
|
|
||||||
} else {
|
|
||||||
section.pages.forEach(function(page) {
|
|
||||||
if (page.path === path) {
|
|
||||||
that.currentPage = page;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.$watch(
|
|
||||||
function getLocationPath() { return $location.path(); },
|
|
||||||
function handleLocationPathChange(path) { that.updateCurrentPage(path); }
|
|
||||||
);
|
|
||||||
}]);
|
|
@ -1,15 +0,0 @@
|
|||||||
angular.module('code', [])
|
|
||||||
|
|
||||||
.directive('code', function() {
|
|
||||||
return {
|
|
||||||
restrict: 'E',
|
|
||||||
terminal: true,
|
|
||||||
compile: function(element) {
|
|
||||||
var linenums = element.hasClass('linenum');
|
|
||||||
var match = /lang-(\S+)/.exec(element[0].className);
|
|
||||||
var lang = match && match[1];
|
|
||||||
var html = element.html();
|
|
||||||
element.html(window.prettyPrintOne(html, lang, linenums));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "angular-docs",
|
|
||||||
"main": "index.js",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"homepage": "https://github.com/angular/angular",
|
|
||||||
"authors": [],
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"private": true,
|
|
||||||
"ignore": [
|
|
||||||
"**/.*",
|
|
||||||
"node_modules",
|
|
||||||
"bower_components",
|
|
||||||
"test",
|
|
||||||
"tests"
|
|
||||||
],
|
|
||||||
"dependencies": {
|
|
||||||
"angular-material": "~0.6.0",
|
|
||||||
"google-code-prettify": "~1.0.3"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
require('../../tools/transpiler/index.js').init();
|
|
||||||
|
|
||||||
var Package = require('dgeni').Package;
|
|
||||||
var jsdocPackage = require('dgeni-packages/jsdoc');
|
|
||||||
var nunjucksPackage = require('dgeni-packages/nunjucks');
|
|
||||||
var path = require('canonical-path');
|
|
||||||
|
|
||||||
var PARTIAL_PATH = 'partials';
|
|
||||||
var MODULES_DOCS_PATH = PARTIAL_PATH + '/modules';
|
|
||||||
var GUIDES_PATH = PARTIAL_PATH + '/guides';
|
|
||||||
|
|
||||||
// Define the dgeni package for generating the docs
|
|
||||||
module.exports = new Package('angular', [jsdocPackage, nunjucksPackage])
|
|
||||||
|
|
||||||
// Register the services and file readers
|
|
||||||
.factory(require('./services/modules'))
|
|
||||||
.factory(require('./services/atParser'))
|
|
||||||
.factory(require('./services/getJSDocComment'))
|
|
||||||
.factory(require('./services/SourceFile'))
|
|
||||||
.factory(require('./services/TraceurParser'))
|
|
||||||
.factory(require('./services/traceurOptions'))
|
|
||||||
.factory(require('./services/ParseTreeVisitor'))
|
|
||||||
.factory(require('./services/AttachCommentTreeVisitor'))
|
|
||||||
.factory(require('./services/ExportTreeVisitor'))
|
|
||||||
|
|
||||||
.factory(require('./readers/atScript'))
|
|
||||||
.factory(require('./readers/ngdoc'))
|
|
||||||
|
|
||||||
.factory('EXPORT_DOC_TYPES', function() {
|
|
||||||
return [
|
|
||||||
'class',
|
|
||||||
'function',
|
|
||||||
'var',
|
|
||||||
'const'
|
|
||||||
];
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Register the processors
|
|
||||||
.processor(require('./processors/generateDocsFromComments'))
|
|
||||||
.processor(require('./processors/processModuleDocs'))
|
|
||||||
.processor(require('./processors/processClassDocs'))
|
|
||||||
.processor(require('./processors/generateNavigationDoc'))
|
|
||||||
.processor(require('./processors/extractTitleFromGuides'))
|
|
||||||
|
|
||||||
// Configure the log service
|
|
||||||
.config(function(log) {
|
|
||||||
log.level = 'info';
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Configure file reading
|
|
||||||
.config(function(readFilesProcessor, atScriptFileReader, ngdocFileReader) {
|
|
||||||
readFilesProcessor.fileReaders = [atScriptFileReader, ngdocFileReader];
|
|
||||||
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
|
|
||||||
readFilesProcessor.sourceFiles = [
|
|
||||||
{ include: 'modules/*/*.js', basePath: 'modules' },
|
|
||||||
{ include: 'modules/*/src/**/*.js', basePath: 'modules' },
|
|
||||||
{ include: 'modules/*/docs/**/*.md', basePath: 'modules' },
|
|
||||||
{ include: 'docs/content/**/*.md', basePath: 'docs/content' }
|
|
||||||
];
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Configure file writing
|
|
||||||
.config(function(writeFilesProcessor) {
|
|
||||||
writeFilesProcessor.outputFolder = 'dist/docs';
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Configure rendering
|
|
||||||
.config(function(templateFinder, templateEngine) {
|
|
||||||
|
|
||||||
// Nunjucks and Angular conflict in their template bindings so change Nunjucks
|
|
||||||
templateEngine.config.tags = {
|
|
||||||
variableStart: '{$',
|
|
||||||
variableEnd: '$}'
|
|
||||||
};
|
|
||||||
|
|
||||||
templateFinder.templateFolders
|
|
||||||
.unshift(path.resolve(__dirname, 'templates'));
|
|
||||||
|
|
||||||
templateFinder.templatePatterns = [
|
|
||||||
'${ doc.template }',
|
|
||||||
'${ doc.id }.${ doc.docType }.template.html',
|
|
||||||
'${ doc.id }.template.html',
|
|
||||||
'${ doc.docType }.template.html',
|
|
||||||
'common.template.html'
|
|
||||||
];
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Configure ids and paths
|
|
||||||
.config(function(computeIdsProcessor, computePathsProcessor, EXPORT_DOC_TYPES) {
|
|
||||||
|
|
||||||
computeIdsProcessor.idTemplates.push({
|
|
||||||
docTypes: EXPORT_DOC_TYPES,
|
|
||||||
idTemplate: '${moduleDoc.id}.${name}',
|
|
||||||
getAliases: function(doc) { return [doc.id]; }
|
|
||||||
});
|
|
||||||
|
|
||||||
computeIdsProcessor.idTemplates.push({
|
|
||||||
docTypes: ['member'],
|
|
||||||
idTemplate: '${classDoc.id}.${name}',
|
|
||||||
getAliases: function(doc) { return [doc.id]; }
|
|
||||||
});
|
|
||||||
|
|
||||||
computeIdsProcessor.idTemplates.push({
|
|
||||||
docTypes: ['guide'],
|
|
||||||
getId: function(doc) {
|
|
||||||
return doc.fileInfo.relativePath
|
|
||||||
// path should be relative to `modules` folder
|
|
||||||
.replace(/.*\/?modules\//, '')
|
|
||||||
// path should not include `/docs/`
|
|
||||||
.replace(/\/docs\//, '/')
|
|
||||||
// path should not have a suffix
|
|
||||||
.replace(/\.\w*$/, '');
|
|
||||||
},
|
|
||||||
getAliases: function(doc) { return [doc.id]; }
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
computePathsProcessor.pathTemplates.push({
|
|
||||||
docTypes: ['module'],
|
|
||||||
pathTemplate: '${id}',
|
|
||||||
outputPathTemplate: MODULES_DOCS_PATH + '/${id}/index.html'
|
|
||||||
});
|
|
||||||
|
|
||||||
computePathsProcessor.pathTemplates.push({
|
|
||||||
docTypes: EXPORT_DOC_TYPES,
|
|
||||||
pathTemplate: '${moduleDoc.path}/${name}',
|
|
||||||
outputPathTemplate: MODULES_DOCS_PATH + '/${path}/index.html'
|
|
||||||
});
|
|
||||||
|
|
||||||
computePathsProcessor.pathTemplates.push({
|
|
||||||
docTypes: ['member'],
|
|
||||||
pathTemplate: '${classDoc.path}/${name}',
|
|
||||||
getOutputPath: function() {} // These docs are not written to their own file, instead they are part of their class doc
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
computePathsProcessor.pathTemplates.push({
|
|
||||||
docTypes: ['guide'],
|
|
||||||
pathTemplate: '${id}',
|
|
||||||
outputPathTemplate: GUIDES_PATH + '/${id}.html'
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,10 +0,0 @@
|
|||||||
var Package = require('dgeni').Package;
|
|
||||||
|
|
||||||
module.exports = function mockPackage() {
|
|
||||||
|
|
||||||
return new Package('mockPackage', [require('../')])
|
|
||||||
|
|
||||||
// provide a mock log service
|
|
||||||
.factory('log', function() { return require('dgeni/lib/mocks/log')(false); });
|
|
||||||
|
|
||||||
};
|
|
@ -1,24 +0,0 @@
|
|||||||
var _ = require('lodash');
|
|
||||||
|
|
||||||
module.exports = function extractTitleFromGuides() {
|
|
||||||
|
|
||||||
return {
|
|
||||||
$runAfter: ['processing-docs'],
|
|
||||||
$runBefore: ['docs-processed'],
|
|
||||||
$process: function(docs) {
|
|
||||||
_(docs).forEach(function(doc) {
|
|
||||||
if (doc.docType === 'guide') {
|
|
||||||
doc.name = doc.name || getNameFromHeading(doc.description);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function getNameFromHeading(text) {
|
|
||||||
var match = /^\s*#\s*(.*)/.exec(text);
|
|
||||||
if (match) {
|
|
||||||
return match[1];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
var _ = require('lodash');
|
|
||||||
|
|
||||||
module.exports = function generateDocsFromComments(log) {
|
|
||||||
return {
|
|
||||||
$runAfter: ['files-read'],
|
|
||||||
$runBefore: ['parsing-tags'],
|
|
||||||
$process: function(docs) {
|
|
||||||
var commentDocs = [];
|
|
||||||
docs = _.filter(docs, function(doc) {
|
|
||||||
if (doc.docType !== 'atScriptFile') {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
_.forEach(doc.fileInfo.comments, function(comment) {
|
|
||||||
|
|
||||||
// we need to check for `/**` at the start of the comment to find all the jsdoc style comments
|
|
||||||
comment.range.toString().replace(/^\/\*\*([\w\W]*)\*\/$/g, function(match, commentBody) {
|
|
||||||
|
|
||||||
// Create a doc from this comment
|
|
||||||
commentDocs.push({
|
|
||||||
fileInfo: doc.fileInfo,
|
|
||||||
startingLine: comment.range.start.line,
|
|
||||||
endingLine: comment.range.end.line,
|
|
||||||
content: commentBody,
|
|
||||||
codeTree: comment.treeAfter,
|
|
||||||
docType: 'atScriptDoc'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return docs.concat(commentDocs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,66 +0,0 @@
|
|||||||
var _ = require('lodash');
|
|
||||||
|
|
||||||
module.exports = function generateNavigationDoc() {
|
|
||||||
|
|
||||||
return {
|
|
||||||
$runAfter: ['docs-processed'],
|
|
||||||
$runBefore: ['rendering-docs'],
|
|
||||||
$process: function(docs) {
|
|
||||||
var modulesDoc = {
|
|
||||||
value: { sections: [] },
|
|
||||||
moduleName: 'navigation-modules',
|
|
||||||
serviceName: 'MODULES',
|
|
||||||
template: 'data-module.template.js',
|
|
||||||
outputPath: 'js/navigation-modules.js'
|
|
||||||
};
|
|
||||||
|
|
||||||
_.forEach(docs, function(doc) {
|
|
||||||
if ( doc.docType === 'module' ) {
|
|
||||||
var moduleNavItem = {
|
|
||||||
path: doc.path,
|
|
||||||
partial: doc.outputPath,
|
|
||||||
name: doc.id,
|
|
||||||
type: 'module',
|
|
||||||
pages: []
|
|
||||||
};
|
|
||||||
|
|
||||||
modulesDoc.value.sections.push(moduleNavItem);
|
|
||||||
|
|
||||||
_.forEach(doc.exports, function(exportDoc) {
|
|
||||||
var exportNavItem = {
|
|
||||||
path: exportDoc.path,
|
|
||||||
partial: exportDoc.outputPath,
|
|
||||||
name: exportDoc.name,
|
|
||||||
type: exportDoc.docType
|
|
||||||
};
|
|
||||||
moduleNavItem.pages.push(exportNavItem);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
docs.push(modulesDoc);
|
|
||||||
|
|
||||||
|
|
||||||
var guidesDoc = {
|
|
||||||
value: { pages: [] },
|
|
||||||
moduleName: 'navigation-guides',
|
|
||||||
serviceName: 'GUIDES',
|
|
||||||
template: 'data-module.template.js',
|
|
||||||
outputPath: 'js/navigation-guides.js'
|
|
||||||
};
|
|
||||||
|
|
||||||
_.forEach(docs, function(doc) {
|
|
||||||
if ( doc.docType === 'guide' ) {
|
|
||||||
var guideDoc = {
|
|
||||||
path: doc.path,
|
|
||||||
partial: doc.outputPath,
|
|
||||||
name: doc.name,
|
|
||||||
type: 'guide'
|
|
||||||
};
|
|
||||||
guidesDoc.value.pages.push(guideDoc);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
docs.push(guidesDoc);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,47 +0,0 @@
|
|||||||
var _ = require('lodash');
|
|
||||||
|
|
||||||
module.exports = function processClassDocs(log, getJSDocComment) {
|
|
||||||
|
|
||||||
return {
|
|
||||||
$runAfter: ['processModuleDocs'],
|
|
||||||
$runBefore: ['parsing-tags', 'generateDocsFromComments'],
|
|
||||||
ignorePrivateMembers: false,
|
|
||||||
$process: function(docs) {
|
|
||||||
var memberDocs = [];
|
|
||||||
var ignorePrivateMembers = this.ignorePrivateMembers;
|
|
||||||
_.forEach(docs, function(classDoc) {
|
|
||||||
if ( classDoc.docType === 'class' ) {
|
|
||||||
|
|
||||||
classDoc.members = [];
|
|
||||||
|
|
||||||
// Create a new doc for each member of the class
|
|
||||||
_.forEach(classDoc.elements, function(memberDoc) {
|
|
||||||
|
|
||||||
if (ignorePrivateMembers && memberDoc.name.literalToken.value.charAt(0) === '_') return;
|
|
||||||
|
|
||||||
classDoc.members.push(memberDoc);
|
|
||||||
memberDocs.push(memberDoc);
|
|
||||||
|
|
||||||
memberDoc.docType = 'member';
|
|
||||||
memberDoc.classDoc = classDoc;
|
|
||||||
memberDoc.name = memberDoc.name.literalToken.value;
|
|
||||||
|
|
||||||
|
|
||||||
if (memberDoc.commentBefore ) {
|
|
||||||
// If this export has a comment, remove it from the list of
|
|
||||||
// comments collected in the module
|
|
||||||
var index = classDoc.moduleDoc.comments.indexOf(memberDoc.commentBefore);
|
|
||||||
if ( index !== -1 ) {
|
|
||||||
classDoc.moduleDoc.comments.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_.assign(memberDoc, getJSDocComment(memberDoc.commentBefore));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return docs.concat(memberDocs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,46 +0,0 @@
|
|||||||
var _ = require('lodash');
|
|
||||||
|
|
||||||
module.exports = function processModuleDocs(log, ExportTreeVisitor, getJSDocComment) {
|
|
||||||
|
|
||||||
return {
|
|
||||||
$runAfter: ['files-read'],
|
|
||||||
$runBefore: ['parsing-tags', 'generateDocsFromComments'],
|
|
||||||
$process: function(docs) {
|
|
||||||
var exportDocs = [];
|
|
||||||
_.forEach(docs, function(doc) {
|
|
||||||
if ( doc.docType === 'module' ) {
|
|
||||||
|
|
||||||
log.debug('processing', doc.moduleTree.moduleName);
|
|
||||||
|
|
||||||
doc.exports = [];
|
|
||||||
|
|
||||||
if ( doc.moduleTree.visit ) {
|
|
||||||
var visitor = new ExportTreeVisitor();
|
|
||||||
visitor.visit(doc.moduleTree);
|
|
||||||
|
|
||||||
_.forEach(visitor.exports, function(exportDoc) {
|
|
||||||
|
|
||||||
doc.exports.push(exportDoc);
|
|
||||||
exportDocs.push(exportDoc);
|
|
||||||
exportDoc.moduleDoc = doc;
|
|
||||||
|
|
||||||
if (exportDoc.comment) {
|
|
||||||
// If this export has a comment, remove it from the list of
|
|
||||||
// comments collected in the module
|
|
||||||
var index = doc.comments.indexOf(exportDoc.comment);
|
|
||||||
if ( index !== -1 ) {
|
|
||||||
doc.comments.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_.assign(exportDoc, getJSDocComment(exportDoc.comment));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return docs.concat(exportDocs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,32 +0,0 @@
|
|||||||
var path = require('canonical-path');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dgService atScriptFileReader
|
|
||||||
* @description
|
|
||||||
* This file reader will create a simple doc for each
|
|
||||||
* file including a code AST of the AtScript in the file.
|
|
||||||
*/
|
|
||||||
module.exports = function atScriptFileReader(log, atParser, modules) {
|
|
||||||
var reader = {
|
|
||||||
name: 'atScriptFileReader',
|
|
||||||
defaultPattern: /\.js$/,
|
|
||||||
getDocs: function(fileInfo) {
|
|
||||||
|
|
||||||
var moduleDoc = atParser.parseModule(fileInfo);
|
|
||||||
moduleDoc.docType = 'module';
|
|
||||||
moduleDoc.id = moduleDoc.moduleTree.moduleName;
|
|
||||||
moduleDoc.aliases = [moduleDoc.id];
|
|
||||||
|
|
||||||
modules[moduleDoc.id] = moduleDoc;
|
|
||||||
|
|
||||||
// Readers return a collection of docs read from the file
|
|
||||||
// but in this read there is only one document (module) to return
|
|
||||||
return [moduleDoc];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return reader;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
@ -1,55 +0,0 @@
|
|||||||
var mockPackage = require('../mocks/mockPackage');
|
|
||||||
var Dgeni = require('dgeni');
|
|
||||||
|
|
||||||
describe('atScript file reader', function() {
|
|
||||||
|
|
||||||
var dgeni, injector, reader;
|
|
||||||
|
|
||||||
var fileContent =
|
|
||||||
'import {CONST} from "facade/lang";\n' +
|
|
||||||
'\n' +
|
|
||||||
'/**\n' +
|
|
||||||
'* A parameter annotation that creates a synchronous eager dependency.\n' +
|
|
||||||
'*\n' +
|
|
||||||
'* class AComponent {\n' +
|
|
||||||
'* constructor(@Inject("aServiceToken") aService) {}\n' +
|
|
||||||
'* }\n' +
|
|
||||||
'*\n' +
|
|
||||||
'*/\n' +
|
|
||||||
'export class Inject {\n' +
|
|
||||||
'token;\n' +
|
|
||||||
'@CONST()\n' +
|
|
||||||
'constructor(token) {\n' +
|
|
||||||
'this.token = token;\n' +
|
|
||||||
'}\n' +
|
|
||||||
'}';
|
|
||||||
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
dgeni = new Dgeni([mockPackage()]);
|
|
||||||
injector = dgeni.configureInjector();
|
|
||||||
reader = injector.get('atScriptFileReader');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should provide a default pattern', function() {
|
|
||||||
expect(reader.defaultPattern).toEqual(/\.js$/);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should parse the file using the atParser and return a single doc', function() {
|
|
||||||
|
|
||||||
var atParser = injector.get('atParser');
|
|
||||||
spyOn(atParser, 'parseModule').and.callThrough();
|
|
||||||
|
|
||||||
var docs = reader.getDocs({
|
|
||||||
content: fileContent,
|
|
||||||
relativePath: 'di/src/annotations.js'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(atParser.parseModule).toHaveBeenCalled();
|
|
||||||
expect(docs.length).toEqual(1);
|
|
||||||
expect(docs[0].docType).toEqual('module');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
@ -1,32 +0,0 @@
|
|||||||
var path = require('canonical-path');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dgService ngdocFileReader
|
|
||||||
* @description
|
|
||||||
* This file reader will pull the contents from a text file (by default .ngdoc)
|
|
||||||
*
|
|
||||||
* The doc will initially have the form:
|
|
||||||
* ```
|
|
||||||
* {
|
|
||||||
* content: 'the content of the file',
|
|
||||||
* startingLine: 1
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
module.exports = function ngdocFileReader() {
|
|
||||||
var reader = {
|
|
||||||
name: 'ngdocFileReader',
|
|
||||||
defaultPattern: /\.md$/,
|
|
||||||
getDocs: function(fileInfo) {
|
|
||||||
|
|
||||||
// We return a single element array because ngdoc files only contain one document
|
|
||||||
return [{
|
|
||||||
docType: 'guide',
|
|
||||||
content: fileInfo.content,
|
|
||||||
startingLine: 1
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return reader;
|
|
||||||
};
|
|
@ -1,45 +0,0 @@
|
|||||||
var ngdocFileReaderFactory = require('./ngdoc');
|
|
||||||
var path = require('canonical-path');
|
|
||||||
|
|
||||||
describe('ngdocFileReader', function() {
|
|
||||||
|
|
||||||
var fileReader;
|
|
||||||
|
|
||||||
var createFileInfo = function(file, content, basePath) {
|
|
||||||
return {
|
|
||||||
fileReader: fileReader.name,
|
|
||||||
filePath: file,
|
|
||||||
baseName: path.basename(file, path.extname(file)),
|
|
||||||
extension: path.extname(file).replace(/^\./, ''),
|
|
||||||
basePath: basePath,
|
|
||||||
relativePath: path.relative(basePath, file),
|
|
||||||
content: content
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
fileReader = ngdocFileReaderFactory();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('defaultPattern', function() {
|
|
||||||
it('should match .md files', function() {
|
|
||||||
expect(fileReader.defaultPattern.test('abc.md')).toBeTruthy();
|
|
||||||
expect(fileReader.defaultPattern.test('abc.js')).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
describe('getDocs', function() {
|
|
||||||
it('should return an object containing info about the file and its contents', function() {
|
|
||||||
var fileInfo = createFileInfo('project/path/modules/someModule/foo/docs/subfolder/bar.ngdoc', 'A load of content', 'project/path');
|
|
||||||
expect(fileReader.getDocs(fileInfo)).toEqual([{
|
|
||||||
docType: 'guide',
|
|
||||||
content: 'A load of content',
|
|
||||||
startingLine: 1
|
|
||||||
}]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
|||||||
module.exports = function AttachCommentTreeVisitor(ParseTreeVisitor, log) {
|
|
||||||
|
|
||||||
function AttachCommentTreeVisitorImpl() {
|
|
||||||
ParseTreeVisitor.call(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
AttachCommentTreeVisitorImpl.prototype = {
|
|
||||||
|
|
||||||
__proto__: ParseTreeVisitor.prototype,
|
|
||||||
|
|
||||||
|
|
||||||
visit: function(tree, comments) {
|
|
||||||
this.comments = comments;
|
|
||||||
this.index = 0;
|
|
||||||
this.currentComment = this.comments[this.index];
|
|
||||||
|
|
||||||
if (this.currentComment) log.silly('comment: ' +
|
|
||||||
this.currentComment.range.start.line + ' - ' +
|
|
||||||
this.currentComment.range.end.line + ' : ' +
|
|
||||||
this.currentComment.range.toString());
|
|
||||||
|
|
||||||
ParseTreeVisitor.prototype.visit.call(this, tree);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Really we ought to subclass ParseTreeVisitor but this is fiddly in ES5 so
|
|
||||||
// it is easier to simply override the prototype's method on the instance
|
|
||||||
visitAny: function(tree) {
|
|
||||||
if (tree && tree.location && tree.location.start && this.currentComment &&
|
|
||||||
this.currentComment.range.end.offset < tree.location.start.offset) {
|
|
||||||
log.silly('tree: ' + tree.constructor.name + ' - ' + tree.location.start.line);
|
|
||||||
while (this.currentComment &&
|
|
||||||
this.currentComment.range.end.offset < tree.location.start.offset) {
|
|
||||||
log.silly('comment: ' + this.currentComment.range.start.line + ' - ' +
|
|
||||||
this.currentComment.range.end.line + ' : ' +
|
|
||||||
this.currentComment.range.toString());
|
|
||||||
tree.commentBefore = this.currentComment;
|
|
||||||
this.currentComment.treeAfter = tree;
|
|
||||||
this.index++;
|
|
||||||
this.currentComment = this.comments[this.index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ParseTreeVisitor.prototype.visitAny.call(this, tree);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return AttachCommentTreeVisitorImpl;
|
|
||||||
};
|
|
@ -1,103 +0,0 @@
|
|||||||
module.exports = function ExportTreeVisitor(ParseTreeVisitor, log) {
|
|
||||||
|
|
||||||
function ExportTreeVisitorImpl() {
|
|
||||||
ParseTreeVisitor.call(this);
|
|
||||||
}
|
|
||||||
ExportTreeVisitorImpl.prototype = {
|
|
||||||
|
|
||||||
__proto__: ParseTreeVisitor.prototype,
|
|
||||||
|
|
||||||
visitExportDeclaration: function(tree) {
|
|
||||||
// We are entering an export declaration - create an object to track it
|
|
||||||
this.currentExport = {
|
|
||||||
comment: tree.commentBefore,
|
|
||||||
location: tree.location
|
|
||||||
};
|
|
||||||
log.silly('enter', tree.type, tree.commentBefore ? 'has comment' : '');
|
|
||||||
ParseTreeVisitor.prototype.visitExportDeclaration.call(this, tree);
|
|
||||||
log.silly('exit', this.currentExport);
|
|
||||||
|
|
||||||
if(this.currentExport) {
|
|
||||||
// We are exiting the export declaration - store the export object
|
|
||||||
this.exports.push(this.currentExport);
|
|
||||||
}
|
|
||||||
this.currentExport = null;
|
|
||||||
},
|
|
||||||
|
|
||||||
visitVariableDeclaration: function(tree) {
|
|
||||||
if ( this.currentExport ) {
|
|
||||||
this.updateExport(tree);
|
|
||||||
this.currentExport.docType = 'var';
|
|
||||||
this.currentExport.name = tree.lvalue.identifierToken.value;
|
|
||||||
this.currentExport.variableDeclaration = tree;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
visitFunctionDeclaration: function(tree) {
|
|
||||||
if ( this.currentExport ) {
|
|
||||||
this.updateExport(tree);
|
|
||||||
this.currentExport.name = tree.name.identifierToken.value;
|
|
||||||
this.currentExport.functionKind = tree.functionKind;
|
|
||||||
this.currentExport.parameters = tree.parameterList.parameters;
|
|
||||||
this.currentExport.typeAnnotation = tree.typeAnnotation;
|
|
||||||
this.currentExport.annotations = tree.annotations;
|
|
||||||
this.currentExport.docType = 'function';
|
|
||||||
|
|
||||||
log.silly(tree.type, tree.commentBefore ? 'has comment' : '');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
visitClassDeclaration: function(tree) {
|
|
||||||
if ( this.currentExport ) {
|
|
||||||
this.updateExport(tree);
|
|
||||||
this.currentExport.name = tree.name.identifierToken.value;
|
|
||||||
this.currentExport.superClass = tree.superClass;
|
|
||||||
this.currentExport.annotations = tree.annotations;
|
|
||||||
this.currentExport.elements = tree.elements;
|
|
||||||
this.currentExport.docType = 'class';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
visitAsyncFunctionDeclaration: function(tree) {
|
|
||||||
if ( this.currentExport ) {
|
|
||||||
this.updateExport(tree);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
visitExportDefault: function(tree) {
|
|
||||||
if ( this.currentExport ) {
|
|
||||||
this.updateExport(tree);
|
|
||||||
this.currentExport.name = 'DEFAULT';
|
|
||||||
this.currentExport.defaultExport = tree;
|
|
||||||
// Default exports are either classes, functions or expressions
|
|
||||||
// So we let the super class continue down...
|
|
||||||
ParseTreeVisitor.prototype.visitExportDefault.call(this, tree);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
visitNamedExport: function(tree) {
|
|
||||||
this.currentExport = null;
|
|
||||||
// if ( this.currentExport ) {
|
|
||||||
// this.updateExport(tree);
|
|
||||||
|
|
||||||
// this.currentExport.namedExport = tree;
|
|
||||||
// this.currentExport.name = 'NAMED_EXPORT';
|
|
||||||
// // TODO: work out this bit!!
|
|
||||||
// // We need to cope with any export specifiers in the named export
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO - if the export is an expression, find the thing that is being
|
|
||||||
// exported and use it and its comments for docs
|
|
||||||
|
|
||||||
updateExport: function(tree) {
|
|
||||||
this.currentExport.comment = this.currentExport.comment || tree.commentBefore;
|
|
||||||
this.currentExport.docType = tree.type;
|
|
||||||
},
|
|
||||||
|
|
||||||
visit: function(tree) {
|
|
||||||
this.exports = [];
|
|
||||||
ParseTreeVisitor.prototype.visit.call(this, tree);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return ExportTreeVisitorImpl;
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
var traceur = require('traceur/src/node/traceur.js');
|
|
||||||
|
|
||||||
module.exports = function ParseTreeVisitor() {
|
|
||||||
console.log(System.map.traceur);
|
|
||||||
return System.get(System.map.traceur + '/src/syntax/ParseTreeVisitor.js').ParseTreeVisitor;
|
|
||||||
};
|
|
@ -1,5 +0,0 @@
|
|||||||
var traceur = require('traceur/src/node/traceur.js');
|
|
||||||
|
|
||||||
module.exports = function SourceFile() {
|
|
||||||
return System.get(System.map.traceur + '/src/syntax/SourceFile.js').SourceFile;
|
|
||||||
};
|
|
@ -1,3 +0,0 @@
|
|||||||
module.exports = function TraceurParser() {
|
|
||||||
return System.get('transpiler/src/parser').Parser;
|
|
||||||
};
|
|
@ -1,74 +0,0 @@
|
|||||||
var file2modulename = require('../../../tools/build/file2modulename');
|
|
||||||
/**
|
|
||||||
* Wrapper around traceur that can parse the contents of a file
|
|
||||||
*/
|
|
||||||
module.exports = function atParser(AttachCommentTreeVisitor, SourceFile, TraceurParser, traceurOptions, log) {
|
|
||||||
|
|
||||||
var service = {
|
|
||||||
/**
|
|
||||||
* The options to pass to traceur
|
|
||||||
*/
|
|
||||||
traceurOptions: {
|
|
||||||
annotations: true, // parse annotations
|
|
||||||
types: true, // parse types
|
|
||||||
memberVariables: true, // parse class fields
|
|
||||||
commentCallback: true // handle comments
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a module AST from the contents of a file.
|
|
||||||
* @param {Object} fileInfo information about the file to parse
|
|
||||||
* @return { { moduleTree: Object, comments: Array } } An object containing the parsed module
|
|
||||||
* AST and an array of all the comments found in the file
|
|
||||||
*/
|
|
||||||
parseModule: parseModule
|
|
||||||
};
|
|
||||||
|
|
||||||
return service;
|
|
||||||
|
|
||||||
|
|
||||||
// Parse the contents of the file using traceur
|
|
||||||
function parseModule(fileInfo) {
|
|
||||||
|
|
||||||
var moduleName = file2modulename(fileInfo.relativePath);
|
|
||||||
var sourceFile = new SourceFile(moduleName, fileInfo.content);
|
|
||||||
var comments = [];
|
|
||||||
var moduleTree;
|
|
||||||
var parser = new TraceurParser(sourceFile);
|
|
||||||
|
|
||||||
// Configure the parser
|
|
||||||
parser.handleComment = function(range) {
|
|
||||||
comments.push({ range: range });
|
|
||||||
};
|
|
||||||
traceurOptions.setFromObject(service.traceurOptions);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Parse the file as a module, attaching the comments
|
|
||||||
moduleTree = parser.parseModule();
|
|
||||||
attachComments(moduleTree, comments);
|
|
||||||
} catch(ex) {
|
|
||||||
// HACK: sometime traceur crashes for various reasons including
|
|
||||||
// Not Yet Implemented (NYI)!
|
|
||||||
log.error(ex.stack);
|
|
||||||
moduleTree = {};
|
|
||||||
}
|
|
||||||
log.debug(moduleName);
|
|
||||||
moduleTree.moduleName = moduleName;
|
|
||||||
|
|
||||||
// We return the module AST but also a collection of all the comments
|
|
||||||
// since it can be helpful to iterate through them without having to
|
|
||||||
// traverse the AST again
|
|
||||||
return {
|
|
||||||
moduleTree: moduleTree,
|
|
||||||
comments: comments
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// attach the comments to their nearest code tree
|
|
||||||
function attachComments(tree, comments) {
|
|
||||||
|
|
||||||
var visitor = new AttachCommentTreeVisitor();
|
|
||||||
// Visit every node of the tree using our custom method
|
|
||||||
visitor.visit(tree, comments);
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,80 +0,0 @@
|
|||||||
var mockPackage = require('../mocks/mockPackage');
|
|
||||||
var Dgeni = require('dgeni');
|
|
||||||
|
|
||||||
describe('atParser service', function() {
|
|
||||||
|
|
||||||
var dgeni, injector, parser;
|
|
||||||
|
|
||||||
var fileContent =
|
|
||||||
'import {CONST} from "facade/lang";\n' +
|
|
||||||
'\n' +
|
|
||||||
'/**\n' +
|
|
||||||
'* A parameter annotation that creates a synchronous eager dependency.\n' +
|
|
||||||
'*\n' +
|
|
||||||
'* class AComponent {\n' +
|
|
||||||
'* constructor(@Inject("aServiceToken") aService) {}\n' +
|
|
||||||
'* }\n' +
|
|
||||||
'*\n' +
|
|
||||||
'*/\n' +
|
|
||||||
'export class Inject {\n' +
|
|
||||||
'token;\n' +
|
|
||||||
'@CONST()\n' +
|
|
||||||
'constructor({a,b}:{a:string, b:string}) {\n' +
|
|
||||||
'this.token = a;\n' +
|
|
||||||
'}\n' +
|
|
||||||
'}';
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
dgeni = new Dgeni([mockPackage()]);
|
|
||||||
injector = dgeni.configureInjector();
|
|
||||||
parser = injector.get('atParser');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should extract the comments from the file', function() {
|
|
||||||
var result = parser.parseModule({
|
|
||||||
content: fileContent,
|
|
||||||
relativePath: 'di/src/annotations.js'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.comments[0].range.toString()).toEqual(
|
|
||||||
'/**\n' +
|
|
||||||
'* A parameter annotation that creates a synchronous eager dependency.\n' +
|
|
||||||
'*\n' +
|
|
||||||
'* class AComponent {\n' +
|
|
||||||
'* constructor(@Inject("aServiceToken") aService) {}\n' +
|
|
||||||
'* }\n' +
|
|
||||||
'*\n' +
|
|
||||||
'*/'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should extract a module AST from the file', function() {
|
|
||||||
var result = parser.parseModule({
|
|
||||||
content: fileContent,
|
|
||||||
relativePath: 'di/src/annotations.js'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.moduleTree.moduleName).toEqual('di/src/annotations');
|
|
||||||
expect(result.moduleTree.scriptItemList[0].type).toEqual('IMPORT_DECLARATION');
|
|
||||||
|
|
||||||
expect(result.moduleTree.scriptItemList[1].type).toEqual('EXPORT_DECLARATION');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should attach comments to their following AST', function() {
|
|
||||||
var result = parser.parseModule({
|
|
||||||
content: fileContent,
|
|
||||||
relativePath: 'di/src/annotations.js'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(result.moduleTree.scriptItemList[1].commentBefore.range.toString()).toEqual(
|
|
||||||
'/**\n' +
|
|
||||||
'* A parameter annotation that creates a synchronous eager dependency.\n' +
|
|
||||||
'*\n' +
|
|
||||||
'* class AComponent {\n' +
|
|
||||||
'* constructor(@Inject("aServiceToken") aService) {}\n' +
|
|
||||||
'* }\n' +
|
|
||||||
'*\n' +
|
|
||||||
'*/'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,28 +0,0 @@
|
|||||||
var LEADING_STAR = /^[^\S\r\n]*\*[^\S\n\r]?/gm;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extact comment info from a comment object
|
|
||||||
* @param {Object} comment object to process
|
|
||||||
* @return { {startingLine, endingLine, content, codeTree}= } a comment info object
|
|
||||||
* or undefined if the comment is not a jsdoc style comment
|
|
||||||
*/
|
|
||||||
module.exports = function getJSDocComment() {
|
|
||||||
return function(comment) {
|
|
||||||
|
|
||||||
var commentInfo;
|
|
||||||
|
|
||||||
// we need to check for `/**` at the start of the comment to find all the jsdoc style comments
|
|
||||||
comment.range.toString().replace(/^\/\*\*([\w\W]*)\*\/$/g, function(match, commentBody) {
|
|
||||||
commentBody = commentBody.replace(LEADING_STAR, '').trim();
|
|
||||||
|
|
||||||
commentInfo = {
|
|
||||||
startingLine: comment.range.start.line,
|
|
||||||
endingLine: comment.range.end.line,
|
|
||||||
content: commentBody,
|
|
||||||
codeTree: comment.treeAfter
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return commentInfo;
|
|
||||||
};
|
|
||||||
};
|
|
@ -1,67 +0,0 @@
|
|||||||
var mockPackage = require('../mocks/mockPackage');
|
|
||||||
var Dgeni = require('dgeni');
|
|
||||||
|
|
||||||
describe('getJSDocComment service', function() {
|
|
||||||
|
|
||||||
var dgeni, injector, getJSDocComment;
|
|
||||||
|
|
||||||
function createComment(commentString, start, end, codeTree) {
|
|
||||||
return {
|
|
||||||
range: {
|
|
||||||
toString: function() { return commentString; },
|
|
||||||
start: { line: start },
|
|
||||||
end: { line: end },
|
|
||||||
},
|
|
||||||
treeAfter: codeTree
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
dgeni = new Dgeni([mockPackage()]);
|
|
||||||
injector = dgeni.configureInjector();
|
|
||||||
getJSDocComment = injector.get('getJSDocComment');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should only return an object if the comment starts with /** and ends with */', function() {
|
|
||||||
var result = getJSDocComment(createComment('/** this is a jsdoc comment */'));
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
|
|
||||||
result = getJSDocComment(createComment('/* this is a normal comment */'));
|
|
||||||
expect(result).toBeUndefined();
|
|
||||||
|
|
||||||
result = getJSDocComment(createComment('this is not a valid comment */'));
|
|
||||||
expect(result).toBeUndefined();
|
|
||||||
|
|
||||||
result = getJSDocComment(createComment('nor is this'));
|
|
||||||
expect(result).toBeUndefined();
|
|
||||||
|
|
||||||
result = getJSDocComment(createComment('/* or even this'));
|
|
||||||
expect(result).toBeUndefined();
|
|
||||||
|
|
||||||
result = getJSDocComment(createComment('/** and this'));
|
|
||||||
expect(result).toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should return a result that contains info about the comment', function() {
|
|
||||||
var codeTree = {};
|
|
||||||
var result = getJSDocComment(createComment('/** this is a comment */', 10, 20, codeTree));
|
|
||||||
expect(result.startingLine).toEqual(10);
|
|
||||||
expect(result.endingLine).toEqual(20);
|
|
||||||
expect(result.codeTree).toBe(codeTree);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should strip off leading stars from each line', function() {
|
|
||||||
var result = getJSDocComment(createComment(
|
|
||||||
'/** this is a jsdoc comment */\n' +
|
|
||||||
' *\n' +
|
|
||||||
' * some content\n' +
|
|
||||||
' */'
|
|
||||||
));
|
|
||||||
expect(result.content).toEqual(
|
|
||||||
'this is a jsdoc comment */\n' +
|
|
||||||
'\n' +
|
|
||||||
'some content'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,3 +0,0 @@
|
|||||||
module.exports = function modules() {
|
|
||||||
return {};
|
|
||||||
};
|
|
@ -1,3 +0,0 @@
|
|||||||
module.exports = function traceurOptions() {
|
|
||||||
return System.get(System.map.traceur + '/src/Options.js').options;
|
|
||||||
};
|
|
@ -1,14 +0,0 @@
|
|||||||
{% extends 'layout/base.template.html' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>{$ doc.name $} <span class="type">class</span></h1>
|
|
||||||
<p class="module">exported from <a href="/{$ doc.moduleDoc.path $}">{$ doc.moduleDoc.id $}</a></p>
|
|
||||||
<p>{$ doc.description | marked $}</p>
|
|
||||||
|
|
||||||
<h2>Members</h2>
|
|
||||||
{% for member in doc.members %}
|
|
||||||
<h3>{$ member.name $}</h3>
|
|
||||||
<p>{$ member.description | marked $}</p>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -1,9 +0,0 @@
|
|||||||
{% extends 'layout/base.template.html' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1>{$ doc.id $}</h1>
|
|
||||||
<h2>({$ doc.docType $})</h2>
|
|
||||||
<div>
|
|
||||||
{$ doc.description | marked $}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
@ -1,3 +0,0 @@
|
|||||||
angular.module('{$ doc.moduleName $}', [])
|
|
||||||
|
|
||||||
.value('{$ doc.serviceName $}', {$ doc.value | json $});
|
|
@ -1,5 +0,0 @@
|
|||||||
{% extends 'layout/base.template.html' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
{$ doc.description | marked $}
|
|
||||||
{% endblock %}
|
|
@ -1 +0,0 @@
|
|||||||
{% block body %}{% endblock %}
|
|
@ -1,16 +0,0 @@
|
|||||||
{% extends 'layout/base.template.html' %}
|
|
||||||
|
|
||||||
{% block body %}
|
|
||||||
<h1 class="id">{$ doc.id $} <span class="type">module</span></h1>
|
|
||||||
|
|
||||||
<p>{$ doc.description | marked $}</p>
|
|
||||||
|
|
||||||
{% if doc.exports.length %}
|
|
||||||
<h2>Exports</h2>
|
|
||||||
<ul>
|
|
||||||
{%- for exportDoc in doc.exports %}
|
|
||||||
<li><a href="/{$ exportDoc.path $}">{$ exportDoc.name $} {$ exportDoc.docType $}</a></li>
|
|
||||||
{%- endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
@ -1,21 +0,0 @@
|
|||||||
var Package = require('dgeni').Package;
|
|
||||||
var basePackage = require('../dgeni-package');
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = new Package('angular-public', [basePackage])
|
|
||||||
|
|
||||||
.processor(require('./processors/filterPublicDocs'))
|
|
||||||
|
|
||||||
.config(function(parseTagsProcessor) {
|
|
||||||
parseTagsProcessor.tagDefinitions.push({ name: 'publicModule' });
|
|
||||||
})
|
|
||||||
|
|
||||||
.config(function(processClassDocs, filterPublicDocs, EXPORT_DOC_TYPES) {
|
|
||||||
processClassDocs.ignorePrivateMembers = true;
|
|
||||||
filterPublicDocs.docTypes = EXPORT_DOC_TYPES;
|
|
||||||
})
|
|
||||||
|
|
||||||
// Configure file writing
|
|
||||||
.config(function(writeFilesProcessor) {
|
|
||||||
writeFilesProcessor.outputFolder = 'dist/public_docs';
|
|
||||||
});
|
|
@ -1,51 +0,0 @@
|
|||||||
var _ = require('lodash');
|
|
||||||
|
|
||||||
module.exports = function filterPublicDocs(modules) {
|
|
||||||
return {
|
|
||||||
$runAfter: ['tags-parsed'],
|
|
||||||
$runBefore: ['computing-ids'],
|
|
||||||
docTypes: [],
|
|
||||||
$validate: {
|
|
||||||
docTypes: { presence: true }
|
|
||||||
},
|
|
||||||
$process: function(docs) {
|
|
||||||
|
|
||||||
docTypes = this.docTypes;
|
|
||||||
|
|
||||||
|
|
||||||
docs = _.filter(docs, function(doc) {
|
|
||||||
|
|
||||||
if (docTypes.indexOf(doc.docType) === -1) return true;
|
|
||||||
if (!doc.publicModule) return false;
|
|
||||||
|
|
||||||
updateModule(doc);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
docs = _.filter(docs, function(doc) {
|
|
||||||
return doc.docType !== 'module' || doc.isPublic;
|
|
||||||
});
|
|
||||||
return docs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function updateModule(classDoc) {
|
|
||||||
|
|
||||||
var originalModule = classDoc.moduleDoc;
|
|
||||||
var publicModule = modules[classDoc.publicModule];
|
|
||||||
|
|
||||||
if (!publicModule) {
|
|
||||||
throw new Error('Missing module definition: "' + classDoc.publicModule + '"\n' +
|
|
||||||
'Referenced in class: "' + classDoc.moduleDoc.id + '/' + classDoc.name + '"');
|
|
||||||
}
|
|
||||||
|
|
||||||
publicModule.isPublic = true;
|
|
||||||
|
|
||||||
_.remove(classDoc.moduleDoc.exports, function(doc) { return doc === classDoc; });
|
|
||||||
classDoc.moduleDoc = publicModule;
|
|
||||||
publicModule.exports.push(classDoc);
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
873
gulpfile.js
873
gulpfile.js
@ -1,717 +1,234 @@
|
|||||||
var gulp = require('gulp');
|
/**
|
||||||
var gulpPlugins = require('gulp-load-plugins')();
|
* @license
|
||||||
var runSequence = require('run-sequence');
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
var madge = require('madge');
|
*
|
||||||
var merge = require('merge');
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
var path = require('path');
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
var gulpTraceur = require('./tools/transpiler/gulp-traceur');
|
'use strict';
|
||||||
|
|
||||||
var clean = require('./tools/build/clean');
|
// THIS CHECK SHOULD BE THE FIRST THING IN THIS FILE
|
||||||
var transpile = require('./tools/build/transpile');
|
// This is to ensure that we catch env issues before we error while requiring other dependencies.
|
||||||
var html = require('./tools/build/html');
|
require('./tools/check-environment')({
|
||||||
var pubget = require('./tools/build/pubget');
|
requiredNpmVersion: '>=3.5.3 <4.0.0',
|
||||||
var linknodemodules = require('./tools/build/linknodemodules');
|
requiredNodeVersion: '>=5.4.1 <7.0.0',
|
||||||
var pubbuild = require('./tools/build/pubbuild');
|
});
|
||||||
var dartanalyzer = require('./tools/build/dartanalyzer');
|
|
||||||
var jsserve = require('./tools/build/jsserve');
|
|
||||||
var pubserve = require('./tools/build/pubserve');
|
|
||||||
var rundartpackage = require('./tools/build/rundartpackage');
|
|
||||||
var copy = require('./tools/build/copy');
|
|
||||||
var file2moduleName = require('./tools/build/file2modulename');
|
|
||||||
var karma = require('karma').server;
|
|
||||||
var minimist = require('minimist');
|
|
||||||
var es5build = require('./tools/build/es5build');
|
|
||||||
var runServerDartTests = require('./tools/build/run_server_dart_tests');
|
|
||||||
var transformCJSTests = require('./tools/build/transformCJSTests');
|
|
||||||
var util = require('./tools/build/util');
|
|
||||||
|
|
||||||
var DART_SDK = require('./tools/build/dartdetect')(gulp);
|
const gulp = require('gulp');
|
||||||
// -----------------------
|
const path = require('path');
|
||||||
// configuration
|
const os = require('os');
|
||||||
|
|
||||||
var _COMPILER_CONFIG_JS_DEFAULT = {
|
// clang-format entry points
|
||||||
sourceMaps: true,
|
const srcsToFmt = [
|
||||||
annotations: true, // parse annotations
|
'modules/@angular/**/*.{js,ts}',
|
||||||
types: true, // parse types
|
'modules/benchmarks/**/*.{js,ts}',
|
||||||
script: false, // parse as a module
|
'modules/e2e_util/**/*.{js,ts}',
|
||||||
memberVariables: true, // parse class fields
|
'modules/playground/**/*.{js,ts}',
|
||||||
modules: 'instantiate'
|
'tools/**/*.{js,ts}',
|
||||||
};
|
'!tools/public_api_guard/**/*.d.ts',
|
||||||
|
'./*.{js,ts}',
|
||||||
var _HTML_DEFAULT_SCRIPTS_JS = [
|
'!shims_for_IE.js',
|
||||||
{src: gulpTraceur.RUNTIME_PATH, mimeType: 'text/javascript', copy: true},
|
|
||||||
{src: 'node_modules/es6-module-loader/dist/es6-module-loader-sans-promises.src.js',
|
|
||||||
mimeType: 'text/javascript', copy: true},
|
|
||||||
{src: 'node_modules/zone.js/zone.js', mimeType: 'text/javascript', copy: true},
|
|
||||||
{src: 'node_modules/zone.js/long-stack-trace-zone.js', mimeType: 'text/javascript', copy: true},
|
|
||||||
{src: 'node_modules/systemjs/dist/system.src.js', mimeType: 'text/javascript', copy: true},
|
|
||||||
{src: 'node_modules/systemjs/lib/extension-register.js', mimeType: 'text/javascript', copy: true},
|
|
||||||
{src: 'tools/build/snippets/runtime_paths.js', mimeType: 'text/javascript', copy: true},
|
|
||||||
{
|
|
||||||
inline: 'System.import(\'$MODULENAME$\').then(function(m) { m.main(); }, console.error.bind(console))',
|
|
||||||
mimeType: 'text/javascript'
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
var _HTML_DEFAULT_SCRIPTS_DART = [
|
// Check source code for formatting errors (clang-format)
|
||||||
{src: '$MODULENAME_WITHOUT_PATH$.dart', mimeType: 'application/dart'},
|
gulp.task('format:enforce', () => {
|
||||||
{src: 'packages/browser/dart.js', mimeType: 'text/javascript'}
|
const format = require('gulp-clang-format');
|
||||||
|
const clangFormat = require('clang-format');
|
||||||
|
return gulp.src(srcsToFmt).pipe(
|
||||||
|
format.checkFormat('file', clangFormat, {verbose: true, fail: true}));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Format the source code with clang-format (see .clang-format)
|
||||||
|
gulp.task('format', () => {
|
||||||
|
const format = require('gulp-clang-format');
|
||||||
|
const clangFormat = require('clang-format');
|
||||||
|
return gulp.src(srcsToFmt, {base: '.'})
|
||||||
|
.pipe(format.format('file', clangFormat))
|
||||||
|
.pipe(gulp.dest('.'));
|
||||||
|
});
|
||||||
|
|
||||||
|
const entrypoints = [
|
||||||
|
'dist/packages-dist/core/index.d.ts',
|
||||||
|
'dist/packages-dist/core/testing/index.d.ts',
|
||||||
|
'dist/packages-dist/common/index.d.ts',
|
||||||
|
'dist/packages-dist/common/testing/index.d.ts',
|
||||||
|
// The API surface of the compiler is currently unstable - all of the important APIs are exposed
|
||||||
|
// via @angular/core, @angular/platform-browser or @angular/platform-browser-dynamic instead.
|
||||||
|
//'dist/packages-dist/compiler/index.d.ts',
|
||||||
|
//'dist/packages-dist/compiler/testing.d.ts',
|
||||||
|
'dist/packages-dist/upgrade/index.d.ts',
|
||||||
|
'dist/packages-dist/upgrade/static.d.ts',
|
||||||
|
'dist/packages-dist/platform-browser/index.d.ts',
|
||||||
|
'dist/packages-dist/platform-browser/testing/index.d.ts',
|
||||||
|
'dist/packages-dist/platform-browser-dynamic/index.d.ts',
|
||||||
|
'dist/packages-dist/platform-browser-dynamic/testing/index.d.ts',
|
||||||
|
'dist/packages-dist/platform-webworker/index.d.ts',
|
||||||
|
'dist/packages-dist/platform-webworker-dynamic/index.d.ts',
|
||||||
|
'dist/packages-dist/platform-server/index.d.ts',
|
||||||
|
'dist/packages-dist/platform-server/testing/index.d.ts',
|
||||||
|
'dist/packages-dist/http/index.d.ts',
|
||||||
|
'dist/packages-dist/http/testing/index.d.ts',
|
||||||
|
'dist/packages-dist/forms/index.d.ts',
|
||||||
|
'dist/packages-dist/router/index.d.ts',
|
||||||
];
|
];
|
||||||
|
const publicApiDir = path.normalize('tools/public_api_guard');
|
||||||
|
const publicApiArgs = [
|
||||||
|
'--rootDir',
|
||||||
|
'dist/packages-dist',
|
||||||
|
'--stripExportPattern',
|
||||||
|
'^__',
|
||||||
|
'--allowModuleIdentifiers',
|
||||||
|
'jasmine',
|
||||||
|
'--allowModuleIdentifiers',
|
||||||
|
'protractor',
|
||||||
|
'--allowModuleIdentifiers',
|
||||||
|
'angular',
|
||||||
|
'--onStabilityMissing',
|
||||||
|
'error',
|
||||||
|
].concat(entrypoints);
|
||||||
|
|
||||||
var BASE_PACKAGE_JSON = require('./package.json');
|
// Build angular
|
||||||
var COMMON_PACKAGE_JSON = {
|
gulp.task('build.sh', (done) => {
|
||||||
version: BASE_PACKAGE_JSON.version,
|
const childProcess = require('child_process');
|
||||||
homepage: BASE_PACKAGE_JSON.homepage,
|
|
||||||
bugs: BASE_PACKAGE_JSON.bugs,
|
|
||||||
license: BASE_PACKAGE_JSON.license,
|
|
||||||
contributors: BASE_PACKAGE_JSON.contributors,
|
|
||||||
dependencies: BASE_PACKAGE_JSON.dependencies,
|
|
||||||
devDependencies: {
|
|
||||||
"yargs": BASE_PACKAGE_JSON.devDependencies['yargs'],
|
|
||||||
"gulp-sourcemaps": BASE_PACKAGE_JSON.devDependencies['gulp-sourcemaps'],
|
|
||||||
"gulp-traceur": BASE_PACKAGE_JSON.devDependencies['gulp-traceur'],
|
|
||||||
"gulp": BASE_PACKAGE_JSON.devDependencies['gulp'],
|
|
||||||
"gulp-rename": BASE_PACKAGE_JSON.devDependencies['gulp-rename'],
|
|
||||||
"through2": BASE_PACKAGE_JSON.devDependencies['through2']
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var SRC_FOLDER_INSERTION = {
|
childProcess.exec(path.join(__dirname, 'build.sh'), done);
|
||||||
js: {
|
});
|
||||||
'**': ''
|
|
||||||
},
|
|
||||||
dart: {
|
|
||||||
'**': 'lib',
|
|
||||||
'*/test/**': '',
|
|
||||||
'benchmarks/**': 'web',
|
|
||||||
'benchmarks/test/**': '',
|
|
||||||
'benchmarks_external/**': 'web',
|
|
||||||
'benchmarks_external/test/**': '',
|
|
||||||
'example*/**': 'web',
|
|
||||||
'example*/test/**': ''
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var CONFIG = {
|
// Enforce that the public API matches the golden files
|
||||||
dest: {
|
// Note that these two commands work on built d.ts files instead of the source
|
||||||
js: {
|
gulp.task('public-api:enforce', (done) => {
|
||||||
all: 'dist/js',
|
const childProcess = require('child_process');
|
||||||
dev: {
|
|
||||||
es6: 'dist/js/dev/es6',
|
childProcess
|
||||||
es5: 'dist/js/dev/es5'
|
.spawn(
|
||||||
},
|
path.join(__dirname, platformScriptPath(`/node_modules/.bin/ts-api-guardian`)),
|
||||||
prod: {
|
['--verifyDir', publicApiDir].concat(publicApiArgs), {stdio: 'inherit'})
|
||||||
es6: 'dist/js/prod/es6',
|
.on('close', (errorCode) => {
|
||||||
es5: 'dist/js/prod/es5'
|
if (errorCode !== 0) {
|
||||||
},
|
done(new Error(
|
||||||
cjs: 'dist/js/cjs',
|
'Public API differs from golden file. Please run `gulp public-api:update`.'));
|
||||||
dart2js: 'dist/js/dart2js'
|
} else {
|
||||||
},
|
done();
|
||||||
dart: 'dist/dart',
|
|
||||||
docs: 'dist/docs'
|
|
||||||
},
|
|
||||||
srcFolderInsertion: SRC_FOLDER_INSERTION,
|
|
||||||
transpile: {
|
|
||||||
src: {
|
|
||||||
js: ['modules/**/*.js', 'modules/**/*.es6'],
|
|
||||||
dart: ['modules/**/*.js']
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
js: {
|
|
||||||
dev: merge(true, _COMPILER_CONFIG_JS_DEFAULT, {
|
|
||||||
typeAssertionModule: 'rtts_assert/rtts_assert',
|
|
||||||
typeAssertions: true,
|
|
||||||
outputLanguage: 'es6'
|
|
||||||
}),
|
|
||||||
prod: merge(true, _COMPILER_CONFIG_JS_DEFAULT, {
|
|
||||||
typeAssertions: false,
|
|
||||||
outputLanguage: 'es6'
|
|
||||||
}),
|
|
||||||
cjs: merge(true, _COMPILER_CONFIG_JS_DEFAULT, {
|
|
||||||
typeAssertionModule: 'rtts_assert/rtts_assert',
|
|
||||||
typeAssertions: true,
|
|
||||||
modules: 'commonjs'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
dart: {
|
|
||||||
sourceMaps: true,
|
|
||||||
annotations: true, // parse annotations
|
|
||||||
types: true, // parse types
|
|
||||||
script: false, // parse as a module
|
|
||||||
memberVariables: true, // parse class fields
|
|
||||||
outputLanguage: 'dart'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
copy: {
|
|
||||||
js: {
|
|
||||||
cjs: {
|
|
||||||
src: ['modules/**/README.js.md', 'modules/**/package.json', 'modules/**/*.cjs'],
|
|
||||||
pipes: {
|
|
||||||
'**/*.cjs': gulpPlugins.rename({extname: '.js'}),
|
|
||||||
'**/*.js.md': gulpPlugins.rename(function(file) {
|
|
||||||
file.basename = file.basename.substring(0, file.basename.lastIndexOf('.'));
|
|
||||||
}),
|
|
||||||
'**/package.json': gulpPlugins.template({ 'packageJson': COMMON_PACKAGE_JSON })
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
dev: {
|
});
|
||||||
src: ['modules/**/*.css'],
|
|
||||||
pipes: {}
|
|
||||||
},
|
|
||||||
prod: {
|
|
||||||
src: ['modules/**/*.css'],
|
|
||||||
pipes: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dart: {
|
|
||||||
src: ['modules/**/README.dart.md', 'modules/**/*.dart', 'modules/*/pubspec.yaml', 'modules/**/*.css', '!modules/**/e2e_test/**'],
|
|
||||||
pipes: {
|
|
||||||
'**/*.dart': util.insertSrcFolder(gulpPlugins, SRC_FOLDER_INSERTION.dart),
|
|
||||||
'**/*.dart.md': gulpPlugins.rename(function(file) {
|
|
||||||
file.basename = file.basename.substring(0, file.basename.lastIndexOf('.'));
|
|
||||||
}),
|
|
||||||
'**/pubspec.yaml': gulpPlugins.template({ 'packageJson': COMMON_PACKAGE_JSON })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
multicopy: {
|
|
||||||
js: {
|
|
||||||
cjs: {
|
|
||||||
src: [
|
|
||||||
'LICENSE'
|
|
||||||
],
|
|
||||||
pipes: {}
|
|
||||||
},
|
|
||||||
dev: {
|
|
||||||
es6: {
|
|
||||||
src: ['tools/build/es5build.js'],
|
|
||||||
pipes: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
prod: {
|
|
||||||
es6: {
|
|
||||||
src: ['tools/build/es5build.js'],
|
|
||||||
pipes: {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dart: {
|
|
||||||
src: ['LICENSE'],
|
|
||||||
exclude: ['rtts_assert/'],
|
|
||||||
pipes: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
html: {
|
|
||||||
src: {
|
|
||||||
js: ['modules/*/src/**/*.html'],
|
|
||||||
dart: ['modules/*/src/**/*.html']
|
|
||||||
},
|
|
||||||
scriptsPerFolder: {
|
|
||||||
js: {
|
|
||||||
'**': _HTML_DEFAULT_SCRIPTS_JS,
|
|
||||||
'benchmarks/**':
|
|
||||||
[
|
|
||||||
{ src: 'tools/build/snippets/url_params_to_form.js', mimeType: 'text/javascript', copy: true }
|
|
||||||
].concat(_HTML_DEFAULT_SCRIPTS_JS),
|
|
||||||
'benchmarks_external/**':
|
|
||||||
[
|
|
||||||
{ src: 'node_modules/angular/angular.js', mimeType: 'text/javascript', copy: true },
|
|
||||||
{ src: 'tools/build/snippets/url_params_to_form.js', mimeType: 'text/javascript', copy: true }
|
|
||||||
].concat(_HTML_DEFAULT_SCRIPTS_JS),
|
|
||||||
'benchmarks_external/**/*polymer*/**':
|
|
||||||
[
|
|
||||||
{ src: 'bower_components/polymer/lib/polymer.html', copyOnly: true },
|
|
||||||
{ src: 'tools/build/snippets/url_params_to_form.js', mimeType: 'text/javascript', copy: true }
|
|
||||||
]
|
|
||||||
},
|
|
||||||
dart: {
|
|
||||||
'**': _HTML_DEFAULT_SCRIPTS_DART,
|
|
||||||
'benchmarks*/**':
|
|
||||||
[
|
|
||||||
{ src: 'tools/build/snippets/url_params_to_form.js', mimeType: 'text/javascript', copy: true }
|
|
||||||
].concat(_HTML_DEFAULT_SCRIPTS_DART)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatDart: {
|
|
||||||
packageName: 'dart_style',
|
|
||||||
args: ['dart_style:format', '-w', 'dist/dart']
|
|
||||||
},
|
|
||||||
test: {
|
|
||||||
js: {
|
|
||||||
cjs: [
|
|
||||||
'/angular2/test/change_detection/**/*_spec.js',
|
|
||||||
'/angular2/test/core/annotations/**/*_spec.js',
|
|
||||||
'/angular2/test/core/compiler/**/*_spec.js',
|
|
||||||
'/angular2/test/di/**/*_spec.js',
|
|
||||||
'/angular2/test/directives/**/*_spec.js',
|
|
||||||
'/angular2/test/facade/**/*_spec.js',
|
|
||||||
'/angular2/test/forms/**/*_spec.js',
|
|
||||||
'/angular2/test/mock/**/*_spec.js',
|
|
||||||
'/angular2/test/reflection/**/*_spec.js',
|
|
||||||
'/angular2/test/services/**/*_spec.js',
|
|
||||||
'/angular2/test/test_lib/**/*_spec.js'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
CONFIG.test.js.cjs = CONFIG.test.js.cjs.map(function(s) {return CONFIG.dest.js.cjs + s});
|
|
||||||
|
|
||||||
// ------------
|
// Generate the public API golden files
|
||||||
// clean
|
gulp.task('public-api:update', ['build.sh'], (done) => {
|
||||||
|
const childProcess = require('child_process');
|
||||||
|
|
||||||
gulp.task('build/clean.js', clean(gulp, gulpPlugins, {
|
childProcess
|
||||||
path: CONFIG.dest.js.all
|
.spawn(
|
||||||
}));
|
path.join(__dirname, platformScriptPath(`/node_modules/.bin/ts-api-guardian`)),
|
||||||
|
['--outDir', publicApiDir].concat(publicApiArgs), {stdio: 'inherit'})
|
||||||
|
.on('close', done);
|
||||||
|
});
|
||||||
|
|
||||||
gulp.task('build/clean.dart', clean(gulp, gulpPlugins, {
|
// Check the coding standards and programming errors
|
||||||
path: CONFIG.dest.dart
|
gulp.task('lint', ['format:enforce', 'tools:build'], () => {
|
||||||
}));
|
const tslint = require('gulp-tslint');
|
||||||
|
// Built-in rules are at
|
||||||
|
// https://palantir.github.io/tslint/rules/
|
||||||
|
const tslintConfig = require('./tslint.json');
|
||||||
|
return gulp
|
||||||
|
.src([
|
||||||
|
// todo(vicb): add .js files when supported
|
||||||
|
// see https://github.com/palantir/tslint/pull/1515
|
||||||
|
'./modules/**/*.ts',
|
||||||
|
'./tools/**/*.ts',
|
||||||
|
'./*.ts',
|
||||||
|
|
||||||
gulp.task('build/clean.docs', clean(gulp, gulpPlugins, {
|
// Ignore TypeScript mocks because it's not managed by us
|
||||||
path: CONFIG.dest.docs
|
'!./tools/@angular/tsc-wrapped/test/typescript.mocks.ts',
|
||||||
}));
|
|
||||||
|
|
||||||
|
// Ignore generated files due to lack of copyright header
|
||||||
|
// todo(alfaproject): make generated files lintable
|
||||||
|
'!**/*.d.ts',
|
||||||
|
'!**/*.ngfactory.ts',
|
||||||
|
])
|
||||||
|
.pipe(tslint({
|
||||||
|
tslint: require('tslint').default,
|
||||||
|
configuration: tslintConfig,
|
||||||
|
formatter: 'prose',
|
||||||
|
}))
|
||||||
|
.pipe(tslint.report({emitError: true}));
|
||||||
|
});
|
||||||
|
|
||||||
// ------------
|
gulp.task('tools:build', (done) => { tsc('tools/', done); });
|
||||||
// transpile
|
|
||||||
|
|
||||||
gulp.task('build/transpile.js.dev.es6', transpile(gulp, gulpPlugins, {
|
// Check for circular dependency in the source code
|
||||||
src: CONFIG.transpile.src.js,
|
gulp.task('check-cycle', (done) => {
|
||||||
dest: CONFIG.dest.js.dev.es6,
|
const madge = require('madge');
|
||||||
outputExt: 'es6',
|
|
||||||
options: CONFIG.transpile.options.js.dev,
|
|
||||||
srcFolderInsertion: CONFIG.srcFolderInsertion.js
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/transpile.js.dev.es5', function() {
|
const dependencyObject = madge(['dist/all/'], {
|
||||||
return es5build({
|
format: 'cjs',
|
||||||
src: CONFIG.dest.js.dev.es6,
|
extensions: ['.js'],
|
||||||
dest: CONFIG.dest.js.dev.es5,
|
onParseFile: function(data) { data.src = data.src.replace(/\/\* circular \*\//g, '//'); }
|
||||||
modules: 'instantiate'
|
|
||||||
});
|
});
|
||||||
});
|
const circularDependencies = dependencyObject.circular().getArray();
|
||||||
|
|
||||||
gulp.task('build/transpile.js.dev', function(done) {
|
|
||||||
runSequence(
|
|
||||||
'build/transpile.js.dev.es6',
|
|
||||||
'build/transpile.js.dev.es5',
|
|
||||||
done
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build/transpile.js.prod.es6', transpile(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.transpile.src.js,
|
|
||||||
dest: CONFIG.dest.js.prod.es6,
|
|
||||||
outputExt: 'es6',
|
|
||||||
options: CONFIG.transpile.options.js.prod,
|
|
||||||
srcFolderInsertion: CONFIG.srcFolderInsertion.js
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/transpile.js.prod.es5', function() {
|
|
||||||
return es5build({
|
|
||||||
src: CONFIG.dest.js.prod.es6,
|
|
||||||
dest: CONFIG.dest.js.prod.es5,
|
|
||||||
modules: 'instantiate'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build/transpile.js.prod', function(done) {
|
|
||||||
runSequence(
|
|
||||||
'build/transpile.js.prod.es6',
|
|
||||||
'build/transpile.js.prod.es5',
|
|
||||||
done
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build/transpile.js.cjs', transpile(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.transpile.src.js.concat(['modules/**/*.cjs']),
|
|
||||||
dest: CONFIG.dest.js.cjs,
|
|
||||||
outputExt: 'js',
|
|
||||||
options: CONFIG.transpile.options.js.cjs,
|
|
||||||
srcFolderInsertion: CONFIG.srcFolderInsertion.js
|
|
||||||
}));
|
|
||||||
gulp.task('build/transformCJSTests', function() {
|
|
||||||
return gulp.src(CONFIG.dest.js.cjs + '/angular2/test/**/*_spec.js').pipe(transformCJSTests()).pipe(gulp.dest(CONFIG.dest.js.cjs + '/angular2/test/'));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build/transpile.dart', transpile(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.transpile.src.dart,
|
|
||||||
dest: CONFIG.dest.dart,
|
|
||||||
outputExt: 'dart',
|
|
||||||
options: CONFIG.transpile.options.dart,
|
|
||||||
srcFolderInsertion: CONFIG.srcFolderInsertion.dart
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// html
|
|
||||||
|
|
||||||
gulp.task('build/html.js.dev', html(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.html.src.js,
|
|
||||||
dest: CONFIG.dest.js.dev.es5,
|
|
||||||
srcFolderInsertion: CONFIG.srcFolderInsertion.js,
|
|
||||||
scriptsPerFolder: CONFIG.html.scriptsPerFolder.js
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/html.js.prod', html(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.html.src.js,
|
|
||||||
dest: CONFIG.dest.js.prod.es5,
|
|
||||||
srcFolderInsertion: CONFIG.srcFolderInsertion.js,
|
|
||||||
scriptsPerFolder: CONFIG.html.scriptsPerFolder.js
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/html.dart', html(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.html.src.dart,
|
|
||||||
dest: CONFIG.dest.dart,
|
|
||||||
srcFolderInsertion: CONFIG.srcFolderInsertion.dart,
|
|
||||||
scriptsPerFolder: CONFIG.html.scriptsPerFolder.dart
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// copy
|
|
||||||
|
|
||||||
gulp.task('build/copy.js.cjs', copy.copy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.copy.js.cjs.src,
|
|
||||||
pipes: CONFIG.copy.js.cjs.pipes,
|
|
||||||
dest: CONFIG.dest.js.cjs
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/copy.js.dev', copy.copy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.copy.js.dev.src,
|
|
||||||
pipes: CONFIG.copy.js.dev.pipes,
|
|
||||||
dest: CONFIG.dest.js.dev.es5
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/copy.js.prod', copy.copy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.copy.js.prod.src,
|
|
||||||
pipes: CONFIG.copy.js.prod.pipes,
|
|
||||||
dest: CONFIG.dest.js.prod.es5
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/copy.dart', copy.copy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.copy.dart.src,
|
|
||||||
pipes: CONFIG.copy.dart.pipes,
|
|
||||||
dest: CONFIG.dest.dart
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// multicopy
|
|
||||||
|
|
||||||
gulp.task('build/multicopy.js.cjs', copy.multicopy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.multicopy.js.cjs.src,
|
|
||||||
pipes: CONFIG.multicopy.js.cjs.pipes,
|
|
||||||
exclude: CONFIG.multicopy.js.cjs.exclude,
|
|
||||||
dest: CONFIG.dest.js.cjs
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/multicopy.js.dev.es6', copy.multicopy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.multicopy.js.dev.es6.src,
|
|
||||||
pipes: CONFIG.multicopy.js.dev.es6.pipes,
|
|
||||||
exclude: CONFIG.multicopy.js.dev.es6.exclude,
|
|
||||||
dest: CONFIG.dest.js.dev.es6
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/multicopy.js.prod.es6', copy.multicopy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.multicopy.js.prod.es6.src,
|
|
||||||
pipes: CONFIG.multicopy.js.prod.es6.pipes,
|
|
||||||
exclude: CONFIG.multicopy.js.prod.es6.exclude,
|
|
||||||
dest: CONFIG.dest.js.prod.es6
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('build/multicopy.dart', copy.multicopy(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.multicopy.dart.src,
|
|
||||||
pipes: CONFIG.multicopy.dart.pipes,
|
|
||||||
exclude: CONFIG.multicopy.dart.exclude,
|
|
||||||
dest: CONFIG.dest.dart
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// pubspec
|
|
||||||
|
|
||||||
gulp.task('build/pubspec.dart', pubget(gulp, gulpPlugins, {
|
|
||||||
dir: CONFIG.dest.dart,
|
|
||||||
command: DART_SDK.PUB
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// linknodemodules
|
|
||||||
|
|
||||||
gulp.task('build/linknodemodules.js.cjs', linknodemodules(gulp, gulpPlugins, {
|
|
||||||
dir: CONFIG.dest.js.cjs
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// dartanalyzer
|
|
||||||
|
|
||||||
gulp.task('build/analyze.dart', dartanalyzer(gulp, gulpPlugins, {
|
|
||||||
dest: CONFIG.dest.dart,
|
|
||||||
command: DART_SDK.ANALYZER
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// pubbuild
|
|
||||||
|
|
||||||
gulp.task('build/pubbuild.dart', pubbuild(gulp, gulpPlugins, {
|
|
||||||
src: CONFIG.dest.dart,
|
|
||||||
dest: CONFIG.dest.js.dart2js,
|
|
||||||
command: DART_SDK.PUB
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// format dart
|
|
||||||
|
|
||||||
gulp.task('build/format.dart', rundartpackage(gulp, gulpPlugins, {
|
|
||||||
pub: DART_SDK.PUB,
|
|
||||||
packageName: CONFIG.formatDart.packageName,
|
|
||||||
args: CONFIG.formatDart.args
|
|
||||||
}));
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
// check circular dependencies in Node.js context
|
|
||||||
gulp.task('build/checkCircularDependencies', function (done) {
|
|
||||||
var dependencyObject = madge(CONFIG.dest.js.dev.es6, {
|
|
||||||
format: 'es6',
|
|
||||||
paths: [CONFIG.dest.js.dev.es6],
|
|
||||||
extensions: ['.js', '.es6'],
|
|
||||||
onParseFile: function(data) {
|
|
||||||
data.src = data.src.replace(/import \* as/g, "//import * as");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var circularDependencies = dependencyObject.circular().getArray();
|
|
||||||
if (circularDependencies.length > 0) {
|
if (circularDependencies.length > 0) {
|
||||||
|
console.log('Found circular dependencies!');
|
||||||
console.log(circularDependencies);
|
console.log(circularDependencies);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
// ------------------
|
// Serve the built files
|
||||||
// web servers
|
gulp.task('serve', () => {
|
||||||
gulp.task('serve.js.dev', jsserve(gulp, gulpPlugins, {
|
const connect = require('gulp-connect');
|
||||||
path: CONFIG.dest.js.dev.es5,
|
const cors = require('cors');
|
||||||
port: 8000
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('serve.js.prod', jsserve(gulp, gulpPlugins, {
|
connect.server({
|
||||||
path: CONFIG.dest.js.prod.es5,
|
root: `${__dirname}/dist`,
|
||||||
port: 8001
|
port: 8000,
|
||||||
}));
|
livereload: false,
|
||||||
|
open: false,
|
||||||
gulp.task('serve.js.dart2js', jsserve(gulp, gulpPlugins, {
|
middleware: (connect, opt) => [cors()],
|
||||||
path: CONFIG.dest.js.dart2js,
|
|
||||||
port: 8002
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('serve/examples.dart', pubserve(gulp, gulpPlugins, {
|
|
||||||
command: DART_SDK.PUB,
|
|
||||||
path: CONFIG.dest.dart + '/examples'
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('serve/benchmarks.dart', pubserve(gulp, gulpPlugins, {
|
|
||||||
command: DART_SDK.PUB,
|
|
||||||
path: CONFIG.dest.dart + '/benchmarks'
|
|
||||||
}));
|
|
||||||
|
|
||||||
gulp.task('serve/benchmarks_external.dart', pubserve(gulp, gulpPlugins, {
|
|
||||||
command: DART_SDK.PUB,
|
|
||||||
path: CONFIG.dest.dart + '/benchmarks_external'
|
|
||||||
}));
|
|
||||||
|
|
||||||
// --------------
|
|
||||||
// doc generation
|
|
||||||
var Dgeni = require('dgeni');
|
|
||||||
var bower = require('bower');
|
|
||||||
var jasmine = require('gulp-jasmine');
|
|
||||||
var webserver = require('gulp-webserver');
|
|
||||||
|
|
||||||
gulp.task('docs/bower', function() {
|
|
||||||
var bowerTask = bower.commands.install(undefined, undefined, { cwd: 'docs' });
|
|
||||||
bowerTask.on('log', function (result) {
|
|
||||||
console.log('bower:', result.id, result.data.endpoint.name);
|
|
||||||
});
|
});
|
||||||
bowerTask.on('error', function(error) {
|
});
|
||||||
console.log(error);
|
|
||||||
|
// Serve the examples
|
||||||
|
gulp.task('serve-examples', () => {
|
||||||
|
const connect = require('gulp-connect');
|
||||||
|
const cors = require('cors');
|
||||||
|
|
||||||
|
connect.server({
|
||||||
|
root: `${__dirname}/dist/examples`,
|
||||||
|
port: 8001,
|
||||||
|
livereload: false,
|
||||||
|
open: false,
|
||||||
|
middleware: (connect, opt) => [cors()],
|
||||||
});
|
});
|
||||||
return bowerTask;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function createDocsTasks(public) {
|
// Update the changelog with the latest changes
|
||||||
var dgeniPackage = public ? './docs/public-docs-package' : './docs/dgeni-package';
|
gulp.task('changelog', () => {
|
||||||
var distDocsPath = public ? 'dist/public_docs' : 'dist/docs';
|
const conventionalChangelog = require('gulp-conventional-changelog');
|
||||||
var taskPrefix = public ? 'public_docs' : 'docs';
|
|
||||||
|
|
||||||
gulp.task(taskPrefix + '/dgeni', function() {
|
return gulp.src('CHANGELOG.md')
|
||||||
try {
|
.pipe(conventionalChangelog({preset: 'angular', releaseCount: 1}, {
|
||||||
var dgeni = new Dgeni([require(dgeniPackage)]);
|
// Conventional Changelog Context
|
||||||
return dgeni.generate();
|
// We have to manually set version number so it doesn't get prefixed with `v`
|
||||||
} catch(x) {
|
// See https://github.com/conventional-changelog/conventional-changelog-core/issues/10
|
||||||
console.log(x.stack);
|
currentTag: require('./package.json').version
|
||||||
throw x;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(taskPrefix + '/assets', ['docs/bower'], function() {
|
|
||||||
return gulp.src('docs/bower_components/**/*')
|
|
||||||
.pipe(gulp.dest(distDocsPath + '/lib'));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(taskPrefix + '/app', function() {
|
|
||||||
return gulp.src('docs/app/**/*')
|
|
||||||
.pipe(gulp.dest(distDocsPath));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(taskPrefix, [taskPrefix + '/assets', taskPrefix + '/app', taskPrefix + '/dgeni']);
|
|
||||||
gulp.task(taskPrefix + '/watch', function() {
|
|
||||||
return gulp.watch('docs/app/**/*', [taskPrefix + '/app']);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(taskPrefix + '/test', function () {
|
|
||||||
return gulp.src('docs/**/*.spec.js')
|
|
||||||
.pipe(jasmine({
|
|
||||||
includeStackTrace: true
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task(taskPrefix + '/serve', function() {
|
|
||||||
gulp.src(distDocsPath + '/')
|
|
||||||
.pipe(webserver({
|
|
||||||
fallback: 'index.html'
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
createDocsTasks(true);
|
|
||||||
createDocsTasks(false);
|
|
||||||
|
|
||||||
// ------------------
|
|
||||||
// karma tests
|
|
||||||
// These tests run in the browser and are allowed to access
|
|
||||||
// HTML DOM APIs.
|
|
||||||
function getBrowsersFromCLI() {
|
|
||||||
var args = minimist(process.argv.slice(2));
|
|
||||||
return [args.browsers?args.browsers:'DartiumWithWebPlatform']
|
|
||||||
}
|
|
||||||
gulp.task('test.unit.js', function (done) {
|
|
||||||
karma.start({configFile: __dirname + '/karma-js.conf.js'}, done);
|
|
||||||
});
|
|
||||||
gulp.task('test.unit.dart', function (done) {
|
|
||||||
karma.start({configFile: __dirname + '/karma-dart.conf.js'}, done);
|
|
||||||
});
|
|
||||||
gulp.task('test.unit.js/ci', function (done) {
|
|
||||||
karma.start({configFile: __dirname + '/karma-js.conf.js',
|
|
||||||
singleRun: true, reporters: ['dots'], browsers: getBrowsersFromCLI()}, done);
|
|
||||||
});
|
|
||||||
gulp.task('test.unit.dart/ci', function (done) {
|
|
||||||
karma.start({configFile: __dirname + '/karma-dart.conf.js',
|
|
||||||
singleRun: true, reporters: ['dots'], browsers: getBrowsersFromCLI()}, done);
|
|
||||||
});
|
|
||||||
gulp.task('test.unit.cjs/ci', function () {
|
|
||||||
return gulp.src(CONFIG.test.js.cjs).pipe(jasmine({includeStackTrace: true, timeout: 1000}));
|
|
||||||
});
|
|
||||||
gulp.task('test.unit.cjs', ['build.js.cjs'], function () {
|
|
||||||
//Run tests once
|
|
||||||
runSequence('test.unit.cjs/ci', function() {});
|
|
||||||
//Watcher to transpile file changed
|
|
||||||
gulp.watch(CONFIG.transpile.src.js.concat(['modules/**/*.cjs']), function(event) {
|
|
||||||
var relPath = path.relative(__dirname, event.path).replace(/\\/g, "/");
|
|
||||||
gulp.src(relPath)
|
|
||||||
.pipe(gulpPlugins.rename({extname: '.'+ 'js'}))
|
|
||||||
.pipe(util.insertSrcFolder(gulpPlugins, CONFIG.srcFolderInsertion.js))
|
|
||||||
.pipe(gulpTraceur(CONFIG.transpile.options.js.cjs, file2moduleName))
|
|
||||||
.pipe(transformCJSTests())
|
|
||||||
.pipe(gulp.dest(CONFIG.dest.js.cjs + path.dirname(relPath.replace("modules", ""))));
|
|
||||||
});
|
|
||||||
//Watcher to run tests when dist/js/cjs/angular2 is updated by the first watcher (after clearing the node cache)
|
|
||||||
gulp.watch(CONFIG.dest.js.cjs + '/angular2/**/*.js', function(event) {
|
|
||||||
for (var id in require.cache) {
|
|
||||||
if (id.replace(/\\/g, "/").indexOf(CONFIG.dest.js.cjs) > -1) {
|
|
||||||
delete require.cache[id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runSequence('test.unit.cjs/ci', function() {});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// ------------------
|
|
||||||
// server tests
|
|
||||||
// These tests run on the VM on the command-line and are
|
|
||||||
// allowed to access the file system and network.
|
|
||||||
gulp.task('test.server.dart', runServerDartTests(gulp, gulpPlugins, {
|
|
||||||
dest: 'dist/dart'
|
|
||||||
}));
|
|
||||||
|
|
||||||
// -----------------
|
|
||||||
// test builders
|
|
||||||
gulp.task('test.transpiler.unittest', function (done) {
|
|
||||||
return gulp.src('tools/transpiler/unittest/**/*.js')
|
|
||||||
.pipe(jasmine({
|
|
||||||
includeStackTrace: true
|
|
||||||
}))
|
}))
|
||||||
|
.pipe(gulp.dest('./'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Copy test resources to dist
|
function tsc(projectPath, done) {
|
||||||
gulp.task('tests/transform.dart', function() {
|
const childProcess = require('child_process');
|
||||||
return gulp.src('modules/angular2/test/transform/**')
|
|
||||||
.pipe(gulp.dest('dist/dart/angular2/test/transform'));
|
|
||||||
});
|
|
||||||
|
|
||||||
|
childProcess
|
||||||
|
.spawn(
|
||||||
|
path.normalize(platformScriptPath(`${__dirname}/node_modules/.bin/tsc`)),
|
||||||
|
['-p', path.join(__dirname, projectPath)], {stdio: 'inherit'})
|
||||||
|
.on('close', done);
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the script path for the current platform
|
||||||
// -----------------
|
function platformScriptPath(path) {
|
||||||
// orchestrated targets
|
return /^win/.test(os.platform()) ? `${path}.cmd` : path;
|
||||||
|
}
|
||||||
// Builds all Dart packages, but does not compile them
|
|
||||||
gulp.task('build/packages.dart', function(done) {
|
|
||||||
runSequence(
|
|
||||||
['build/transpile.dart', 'build/html.dart', 'build/copy.dart', 'build/multicopy.dart'],
|
|
||||||
'tests/transform.dart',
|
|
||||||
'build/format.dart',
|
|
||||||
'build/pubspec.dart',
|
|
||||||
done
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Builds and compiles all Dart packages
|
|
||||||
gulp.task('build.dart', function(done) {
|
|
||||||
runSequence(
|
|
||||||
'build/packages.dart',
|
|
||||||
'build/analyze.dart',
|
|
||||||
'build/pubbuild.dart',
|
|
||||||
done
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build.js.dev', function(done) {
|
|
||||||
runSequence(
|
|
||||||
['build/transpile.js.dev', 'build/html.js.dev', 'build/copy.js.dev', 'build/multicopy.js.dev.es6'],
|
|
||||||
'build/checkCircularDependencies',
|
|
||||||
done
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build.js.prod', function(done) {
|
|
||||||
runSequence(
|
|
||||||
['build/transpile.js.prod', 'build/html.js.prod', 'build/copy.js.prod', 'build/multicopy.js.prod.es6'],
|
|
||||||
done
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build.js.cjs', function(done) {
|
|
||||||
runSequence(
|
|
||||||
['build/transpile.js.cjs', 'build/copy.js.cjs', 'build/multicopy.js.cjs'],
|
|
||||||
['build/linknodemodules.js.cjs'],
|
|
||||||
'build/transformCJSTests',
|
|
||||||
done
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('build.js', ['build.js.dev', 'build.js.prod', 'build.js.cjs']);
|
|
||||||
|
|
||||||
gulp.task('clean', ['build/clean.js', 'build/clean.dart', 'build/clean.docs']);
|
|
||||||
|
|
||||||
gulp.task('build', ['build.js', 'build.dart']);
|
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
// Karma configuration
|
|
||||||
// Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT)
|
|
||||||
var file2moduleName = require('./tools/build/file2modulename');
|
|
||||||
|
|
||||||
module.exports = function(config) {
|
|
||||||
config.set({
|
|
||||||
|
|
||||||
frameworks: ['dart-unittest'],
|
|
||||||
|
|
||||||
files: [
|
|
||||||
// Unit test files needs to be included.
|
|
||||||
// Karma-dart generates `__adapter_unittest.dart` that imports these files.
|
|
||||||
{pattern: 'modules/*/test/**/*_spec.js', included: true},
|
|
||||||
{pattern: 'tools/transpiler/spec/**/*_spec.js', included: true},
|
|
||||||
|
|
||||||
// These files are not included, they are imported by the unit tests above.
|
|
||||||
{pattern: 'modules/**', included: false},
|
|
||||||
{pattern: 'tools/transpiler/spec/**/*', included: false},
|
|
||||||
|
|
||||||
// Dependencies, installed with `pub install`.
|
|
||||||
{pattern: 'packages/**/*.dart', included: false, watched: false},
|
|
||||||
|
|
||||||
// Init and configure guiness.
|
|
||||||
{pattern: 'test-main.dart', included: true}
|
|
||||||
],
|
|
||||||
|
|
||||||
karmaDartImports: {
|
|
||||||
guinness: 'package:guinness/guinness_html.dart'
|
|
||||||
},
|
|
||||||
|
|
||||||
// TODO(vojta): Remove the localhost:9877 from urls, once the proxy fix is merged:
|
|
||||||
// https://github.com/karma-runner/karma/pull/1207
|
|
||||||
//
|
|
||||||
// Map packages to the correct urls where Karma serves them.
|
|
||||||
proxies: {
|
|
||||||
// Dependencies installed with `pub install`.
|
|
||||||
'/packages/unittest': 'http://localhost:9877/base/packages/unittest',
|
|
||||||
'/packages/guinness': 'http://localhost:9877/base/packages/guinness',
|
|
||||||
'/packages/matcher': 'http://localhost:9877/base/packages/matcher',
|
|
||||||
'/packages/stack_trace': 'http://localhost:9877/base/packages/stack_trace',
|
|
||||||
'/packages/collection': 'http://localhost:9877/base/packages/collection',
|
|
||||||
'/packages/path': 'http://localhost:9877/base/packages/path',
|
|
||||||
|
|
||||||
// Local dependencies, transpiled from the source.
|
|
||||||
'/packages/angular': 'http://localhost:9877/base/modules/angular',
|
|
||||||
'/packages/benchpress': 'http://localhost:9877/base/modules/benchpress',
|
|
||||||
'/packages/core': 'http://localhost:9877/base/modules/core',
|
|
||||||
'/packages/change_detection': 'http://localhost:9877/base/modules/change_detection',
|
|
||||||
'/packages/reflection': 'http://localhost:9877/base/modules/reflection',
|
|
||||||
'/packages/di': 'http://localhost:9877/base/modules/di',
|
|
||||||
'/packages/directives': 'http://localhost:9877/base/modules/directives',
|
|
||||||
'/packages/facade': 'http://localhost:9877/base/modules/facade',
|
|
||||||
'/packages/forms': 'http://localhost:9877/base/modules/forms',
|
|
||||||
'/packages/test_lib': 'http://localhost:9877/base/modules/test_lib',
|
|
||||||
'/packages/mock': 'http://localhost:9877/base/modules/mock',
|
|
||||||
},
|
|
||||||
|
|
||||||
preprocessors: {
|
|
||||||
'modules/**/*.js': ['traceur'],
|
|
||||||
'tools/**/*.js': ['traceur']
|
|
||||||
},
|
|
||||||
|
|
||||||
traceurPreprocessor: {
|
|
||||||
options: {
|
|
||||||
outputLanguage: 'dart',
|
|
||||||
sourceMaps: true,
|
|
||||||
script: false,
|
|
||||||
modules: 'register',
|
|
||||||
memberVariables: true,
|
|
||||||
types: true,
|
|
||||||
// typeAssertions: true,
|
|
||||||
// typeAssertionModule: 'assert',
|
|
||||||
annotations: true
|
|
||||||
},
|
|
||||||
resolveModuleName: file2moduleName,
|
|
||||||
transformPath: function(fileName) {
|
|
||||||
return fileName.replace('.js', '.dart');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
customLaunchers: {
|
|
||||||
DartiumWithWebPlatform: {
|
|
||||||
base: 'Dartium',
|
|
||||||
flags: ['--enable-experimental-web-platform-features'] }
|
|
||||||
},
|
|
||||||
browsers: ['DartiumWithWebPlatform'],
|
|
||||||
|
|
||||||
port: 9877
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
config.plugins.push(require('./tools/transpiler/karma-traceur-preprocessor'));
|
|
||||||
};
|
|
144
karma-js.conf.js
144
karma-js.conf.js
@ -1,7 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
var browserProvidersConf = require('./browser-providers.conf.js');
|
||||||
|
var internalAngularReporter = require('./tools/karma/reporter.js');
|
||||||
|
|
||||||
// Karma configuration
|
// Karma configuration
|
||||||
// Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT)
|
// Generated on Thu Sep 25 2014 11:52:02 GMT-0700 (PDT)
|
||||||
var file2moduleName = require('./tools/build/file2modulename');
|
|
||||||
|
|
||||||
module.exports = function(config) {
|
module.exports = function(config) {
|
||||||
config.set({
|
config.set({
|
||||||
|
|
||||||
@ -9,60 +18,119 @@ module.exports = function(config) {
|
|||||||
|
|
||||||
files: [
|
files: [
|
||||||
// Sources and specs.
|
// Sources and specs.
|
||||||
// Loaded through the es6-module-loader, in `test-main.js`.
|
// Loaded through the System loader, in `test-main.js`.
|
||||||
{pattern: 'modules/**', included: false},
|
{pattern: 'dist/all/@angular/**/*.js', included: false, watched: true},
|
||||||
{pattern: 'tools/transpiler/spec/**', included: false},
|
|
||||||
|
'node_modules/core-js/client/core.js',
|
||||||
|
// include Angular v1 for upgrade module testing
|
||||||
|
'node_modules/angular/angular.js',
|
||||||
|
'node_modules/angular-mocks/angular-mocks.js',
|
||||||
|
|
||||||
|
'node_modules/zone.js/dist/zone.js',
|
||||||
|
'node_modules/zone.js/dist/long-stack-trace-zone.js',
|
||||||
|
'node_modules/zone.js/dist/proxy.js',
|
||||||
|
'node_modules/zone.js/dist/sync-test.js',
|
||||||
|
'node_modules/zone.js/dist/jasmine-patch.js',
|
||||||
|
'node_modules/zone.js/dist/async-test.js',
|
||||||
|
'node_modules/zone.js/dist/fake-async-test.js',
|
||||||
|
|
||||||
'node_modules/traceur/bin/traceur-runtime.js',
|
|
||||||
'node_modules/es6-module-loader/dist/es6-module-loader-sans-promises.src.js',
|
|
||||||
// Including systemjs because it defines `__eval`, which produces correct stack traces.
|
// Including systemjs because it defines `__eval`, which produces correct stack traces.
|
||||||
|
'shims_for_IE.js',
|
||||||
'node_modules/systemjs/dist/system.src.js',
|
'node_modules/systemjs/dist/system.src.js',
|
||||||
'node_modules/systemjs/lib/extension-register.js',
|
{pattern: 'node_modules/rxjs/**', included: false, watched: false, served: true},
|
||||||
'node_modules/zone.js/zone.js',
|
'node_modules/reflect-metadata/Reflect.js',
|
||||||
'node_modules/zone.js/long-stack-trace-zone.js',
|
|
||||||
|
|
||||||
'tools/build/file2modulename.js',
|
'tools/build/file2modulename.js',
|
||||||
'test-main.js'
|
'test-main.js',
|
||||||
|
{pattern: 'dist/all/empty.*', included: false, watched: false},
|
||||||
|
{
|
||||||
|
pattern: 'modules/@angular/platform-browser/test/static_assets/**',
|
||||||
|
included: false,
|
||||||
|
watched: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pattern: 'modules/@angular/platform-browser/test/browser/static_assets/**',
|
||||||
|
included: false,
|
||||||
|
watched: false,
|
||||||
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
exclude: [
|
exclude: [
|
||||||
'modules/**/e2e_test/**'
|
'dist/all/@angular/**/e2e_test/**',
|
||||||
|
'dist/all/@angular/**/*node_only_spec.js',
|
||||||
|
'dist/all/@angular/benchpress/**',
|
||||||
|
'dist/all/@angular/compiler-cli/**',
|
||||||
|
'dist/all/@angular/compiler/test/aot/**',
|
||||||
|
'dist/all/@angular/examples/**/e2e_test/*',
|
||||||
|
'dist/all/@angular/language-service/**',
|
||||||
|
'dist/all/@angular/router/**',
|
||||||
|
'dist/all/@angular/platform-browser/testing/e2e_util.js',
|
||||||
|
'dist/all/angular1_router.js',
|
||||||
|
'dist/examples/**/e2e_test/**',
|
||||||
|
],
|
||||||
|
|
||||||
|
customLaunchers: browserProvidersConf.customLaunchers,
|
||||||
|
|
||||||
|
plugins: [
|
||||||
|
'karma-jasmine',
|
||||||
|
'karma-browserstack-launcher',
|
||||||
|
'karma-sauce-launcher',
|
||||||
|
'karma-chrome-launcher',
|
||||||
|
'karma-sourcemap-loader',
|
||||||
|
internalAngularReporter,
|
||||||
],
|
],
|
||||||
|
|
||||||
preprocessors: {
|
preprocessors: {
|
||||||
'modules/**/*.js': ['traceur'],
|
'**/*.js': ['sourcemap'],
|
||||||
'modules/**/*.es6': ['traceur'],
|
|
||||||
'tools/transpiler/spec/**/*.js': ['traceur'],
|
|
||||||
'tools/transpiler/spec/**/*.es6': ['traceur'],
|
|
||||||
},
|
},
|
||||||
|
|
||||||
traceurPreprocessor: {
|
reporters: ['internal-angular'],
|
||||||
|
sauceLabs: {
|
||||||
|
testName: 'Angular2',
|
||||||
|
retryLimit: 3,
|
||||||
|
startConnect: false,
|
||||||
|
recordVideo: false,
|
||||||
|
recordScreenshots: false,
|
||||||
options: {
|
options: {
|
||||||
outputLanguage: 'es5',
|
'selenium-version': '2.53.0',
|
||||||
sourceMaps: true,
|
'command-timeout': 600,
|
||||||
script: false,
|
'idle-timeout': 600,
|
||||||
memberVariables: true,
|
'max-duration': 5400,
|
||||||
modules: 'instantiate',
|
|
||||||
types: true,
|
|
||||||
typeAssertions: true,
|
|
||||||
typeAssertionModule: 'rtts_assert/rtts_assert',
|
|
||||||
annotations: true
|
|
||||||
},
|
|
||||||
resolveModuleName: file2moduleName,
|
|
||||||
transformPath: function(fileName) {
|
|
||||||
return fileName.replace(/\.es6$/, '.js');
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
customLaunchers: {
|
browserStack: {
|
||||||
DartiumWithWebPlatform: {
|
project: 'Angular2',
|
||||||
base: 'Dartium',
|
startTunnel: false,
|
||||||
flags: ['--enable-experimental-web-platform-features'] }
|
retryLimit: 3,
|
||||||
|
timeout: 1800,
|
||||||
|
pollingTimeout: 10000,
|
||||||
},
|
},
|
||||||
browsers: ['ChromeCanary'],
|
|
||||||
|
|
||||||
port: 9876
|
browsers: ['Chrome'],
|
||||||
|
|
||||||
|
port: 9876,
|
||||||
|
captureTimeout: 180000,
|
||||||
|
browserDisconnectTimeout: 180000,
|
||||||
|
browserDisconnectTolerance: 3,
|
||||||
|
browserNoActivityTimeout: 300000,
|
||||||
});
|
});
|
||||||
|
|
||||||
config.plugins.push(require('./tools/transpiler/karma-traceur-preprocessor'));
|
if (process.env.TRAVIS) {
|
||||||
|
var buildId =
|
||||||
|
'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')';
|
||||||
|
if (process.env.CI_MODE.startsWith('saucelabs')) {
|
||||||
|
config.sauceLabs.build = buildId;
|
||||||
|
config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;
|
||||||
|
|
||||||
|
// TODO(mlaval): remove once SauceLabs supports websockets.
|
||||||
|
// This speeds up the capturing a bit, as browsers don't even try to use websocket.
|
||||||
|
console.log('>>>> setting socket.io transport to polling <<<<');
|
||||||
|
config.transports = ['polling'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.CI_MODE.startsWith('browserstack')) {
|
||||||
|
config.browserStack.build = buildId;
|
||||||
|
config.browserStack.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -1 +0,0 @@
|
|||||||
karma-js.conf.js
|
|
6
modules/@angular/README.md
Normal file
6
modules/@angular/README.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Angular
|
||||||
|
=======
|
||||||
|
|
||||||
|
The sources for this package are in the main [Angular](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo.
|
||||||
|
|
||||||
|
License: MIT
|
305
modules/@angular/benchpress/README.md
Normal file
305
modules/@angular/benchpress/README.md
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
# Benchpress
|
||||||
|
|
||||||
|
Benchpress is a framework for e2e performance tests.
|
||||||
|
See [here for an example project](https://github.com/angular/benchpress-tree).
|
||||||
|
|
||||||
|
The sources for this package are in the main [Angular2](https://github.com/angular/angular) repo. Please file issues and pull requests against that repo.
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
|
||||||
|
# Why?
|
||||||
|
|
||||||
|
There are so called "micro benchmarks" that essentially use a stop watch in the browser to measure time
|
||||||
|
(e.g. via `performance.now()`). This approach is limited to time, and in some cases memory
|
||||||
|
(Chrome with special flags), as metric. It does not allow to measure:
|
||||||
|
|
||||||
|
- rendering time: e.g. the time the browser spends to layout or paint elements. This can e.g. used to
|
||||||
|
test the performance impact of stylesheet changes.
|
||||||
|
- garbage collection: e.g. how long the browser paused script execution, and how much memory was collected.
|
||||||
|
This can be used to stabilize script execution time, as garbage collection times are usually very
|
||||||
|
unpredictable. This data can also be used to measure and improve memory usage of applications,
|
||||||
|
as the garbage collection amount directly affects garbage collection time.
|
||||||
|
- distinguish script execution time from waiting: e.g. to measure the client side only time that is spent
|
||||||
|
in a complex user interaction, ignoring backend calls.
|
||||||
|
- measure fps to assert the smoothness of scrolling and animations.
|
||||||
|
|
||||||
|
This kind of data is already available in the DevTools of modern browsers. However, there is no standard way to
|
||||||
|
use those tools in an automated way to measure web app performance, especially not across platforms.
|
||||||
|
|
||||||
|
Benchpress tries to fill this gap, i.e. allow to access all kinds of performance metrics in an automated way.
|
||||||
|
|
||||||
|
|
||||||
|
# How it works
|
||||||
|
|
||||||
|
Benchpress uses webdriver to read out the so called "performance log" of browsers. This contains all kinds of interesting
|
||||||
|
data, e.g. when a script started/ended executing, gc started/ended, the browser painted something to the screen, ...
|
||||||
|
|
||||||
|
As browsers are different, benchpress has plugins to normalizes these events.
|
||||||
|
|
||||||
|
|
||||||
|
# Features
|
||||||
|
|
||||||
|
* Provides a loop (so called "Sampler") that executes the benchmark multiple times
|
||||||
|
* Automatically waits/detects until the browser is "warm"
|
||||||
|
* Reporters provide a normalized way to store results:
|
||||||
|
- console reporter
|
||||||
|
- file reporter
|
||||||
|
- Google Big Query reporter (coming soon)
|
||||||
|
* Supports micro benchmarks as well via `console.time()` / `console.timeEnd()`
|
||||||
|
- `console.time()` / `console.timeEnd()` mark the timeline in the DevTools, so it makes sense
|
||||||
|
to use them in micro benchmark to visualize and understand them, with or without benchpress.
|
||||||
|
- running micro benchmarks in benchpress leverages the already existing reporters,
|
||||||
|
the sampler and the auto warmup feature of benchpress.
|
||||||
|
|
||||||
|
|
||||||
|
# Supported browsers
|
||||||
|
|
||||||
|
* Chrome on all platforms
|
||||||
|
* Mobile Safari (iOS)
|
||||||
|
* Firefox (work in progress)
|
||||||
|
|
||||||
|
|
||||||
|
# How to write a benchmark
|
||||||
|
|
||||||
|
A benchmark in benchpress is made by an application under test
|
||||||
|
and a benchmark driver. The application under test is the
|
||||||
|
actual application consisting of html/css/js that should be tests.
|
||||||
|
A benchmark driver is a webdriver test that interacts with the
|
||||||
|
application under test.
|
||||||
|
|
||||||
|
|
||||||
|
## A simple benchmark
|
||||||
|
|
||||||
|
Let's assume we want to measure the script execution time, as well as the render time
|
||||||
|
that it takes to fill a container element with a complex html string.
|
||||||
|
|
||||||
|
The application under test could look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
index.html:
|
||||||
|
|
||||||
|
<button id="reset" onclick="reset()">Reset</button>
|
||||||
|
<button id="fill" onclick="fill()">fill innerHTML</button>
|
||||||
|
<div id="container"></div>
|
||||||
|
<script>
|
||||||
|
var container = document.getElementById('container');
|
||||||
|
var complexHtmlString = '...'; // TODO
|
||||||
|
|
||||||
|
function reset() { container.innerHTML = ''; }
|
||||||
|
|
||||||
|
function fill() {
|
||||||
|
container.innerHTML = complexHtmlString;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
A benchmark driver could look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
// A runner contains the shared configuration
|
||||||
|
// and can be shared across multiple tests.
|
||||||
|
var runner = new Runner(...);
|
||||||
|
|
||||||
|
driver.get('http://myserver/index.html');
|
||||||
|
|
||||||
|
var resetBtn = driver.findElement(By.id('reset'));
|
||||||
|
var fillBtn = driver.findElement(By.id('fill'));
|
||||||
|
|
||||||
|
runner.sample({
|
||||||
|
id: 'fillElement',
|
||||||
|
// Prepare is optional...
|
||||||
|
prepare: () {
|
||||||
|
resetBtn.click();
|
||||||
|
},
|
||||||
|
execute: () {
|
||||||
|
fillBtn.click();
|
||||||
|
// Note: if fillBtn would use some asynchronous code,
|
||||||
|
// we would need to wait here for its end.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Measuring in the browser
|
||||||
|
|
||||||
|
If the application under test would like to, it can measure on its own.
|
||||||
|
E.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
index.html:
|
||||||
|
|
||||||
|
<button id="measure" onclick="measure()">Measure document.createElement</button>
|
||||||
|
<script>
|
||||||
|
function measure() {
|
||||||
|
console.time('createElement*10000');
|
||||||
|
for (var i=0; i<100000; i++) {
|
||||||
|
document.createElement('div');
|
||||||
|
}
|
||||||
|
console.timeEnd('createElement*10000');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
When the `measure` button is clicked, it marks the timeline and creates 10000 elements.
|
||||||
|
It uses the special names `createElement*10000` to tell benchpress that the
|
||||||
|
time that was measured is for 10000 calls to createElement and that benchpress should
|
||||||
|
take the average for it.
|
||||||
|
|
||||||
|
A test driver for this would look like this:
|
||||||
|
|
||||||
|
````
|
||||||
|
driver.get('.../index.html');
|
||||||
|
|
||||||
|
var measureBtn = driver.findElement(By.id('measure'));
|
||||||
|
runner.sample({
|
||||||
|
id: 'createElement test',
|
||||||
|
microMetrics: {
|
||||||
|
'createElement': 'time to create an element (ms)'
|
||||||
|
},
|
||||||
|
execute: () {
|
||||||
|
measureBtn.click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
````
|
||||||
|
|
||||||
|
When looking into the DevTools Timeline, we see a marker as well:
|
||||||
|

|
||||||
|
|
||||||
|
### Custom Metrics Without Using `console.time`
|
||||||
|
|
||||||
|
It's also possible to measure any "user metric" within the browser
|
||||||
|
by setting a numeric value on the `window` object. For example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
bootstrap(App)
|
||||||
|
.then(() => {
|
||||||
|
window.timeToBootstrap = Date.now() - performance.timing.navigationStart;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
A test driver for this user metric could be written as follows:
|
||||||
|
|
||||||
|
```js
|
||||||
|
|
||||||
|
describe('home page load', function() {
|
||||||
|
it('should log load time for a 2G connection', done => {
|
||||||
|
runner.sample({
|
||||||
|
execute: () => {
|
||||||
|
browser.get(`http://localhost:8080`);
|
||||||
|
},
|
||||||
|
userMetrics: {
|
||||||
|
timeToBootstrap: 'The time in milliseconds to bootstrap'
|
||||||
|
},
|
||||||
|
providers: [
|
||||||
|
{provide: RegressionSlopeValidator.METRIC, useValue: 'timeToBootstrap'}
|
||||||
|
]
|
||||||
|
}).then(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Using this strategy, benchpress will wait until the specified property name,
|
||||||
|
`timeToBootstrap` in this case, is defined as a number on the `window` object
|
||||||
|
inside the application under test.
|
||||||
|
|
||||||
|
# Smoothness Metrics
|
||||||
|
|
||||||
|
Benchpress can also measure the "smoothness" of scrolling and animations. In order to do that, the following set of metrics can be collected by benchpress:
|
||||||
|
|
||||||
|
- `frameTime.mean`: mean frame time in ms (target: 16.6ms for 60fps)
|
||||||
|
- `frameTime.worst`: worst frame time in ms
|
||||||
|
- `frameTime.best`: best frame time in ms
|
||||||
|
- `frameTime.smooth`: percentage of frames that hit 60fps
|
||||||
|
|
||||||
|
To collect these metrics, you need to execute `console.time('frameCapture')` and `console.timeEnd('frameCapture')` either in your benchmark application or in you benchmark driver via webdriver. The metrics mentioned above will only be collected between those two calls and it is recommended to wrap the time/timeEnd calls as closely as possible around the action you want to evaluate to get accurate measurements.
|
||||||
|
|
||||||
|
In addition to that, one extra provider needs to be passed to benchpress in tests that want to collect these metrics:
|
||||||
|
|
||||||
|
benchpress.sample(providers: [{provide: bp.Options.CAPTURE_FRAMES, useValue: true}], ... )
|
||||||
|
|
||||||
|
# Requests Metrics
|
||||||
|
|
||||||
|
Benchpress can also record the number of requests sent and count the received "encoded" bytes since [window.performance.timing.navigationStart](http://www.w3.org/TR/navigation-timing/#dom-performancetiming-navigationstart):
|
||||||
|
|
||||||
|
- `receivedData`: number of bytes received since the last navigation start
|
||||||
|
- `requestCount`: number of requests sent since the last navigation start
|
||||||
|
|
||||||
|
To collect these metrics, you need the following corresponding extra providers:
|
||||||
|
|
||||||
|
benchpress.sample(providers: [
|
||||||
|
{provide: bp.Options.RECEIVED_DATA, useValue: true},
|
||||||
|
{provide: bp.Options.REQUEST_COUNT, useValue: true}
|
||||||
|
], ... )
|
||||||
|
|
||||||
|
# Best practices
|
||||||
|
|
||||||
|
* Use normalized environments
|
||||||
|
- metrics that are dependent on the performance of the execution environment must be executed on a normalized machine
|
||||||
|
- e.g. a real mobile device whose cpu frequency is set to a fixed value.
|
||||||
|
* see our [build script](https://github.com/angular/angular/blob/master/scripts/ci/android_cpu.sh)
|
||||||
|
* this requires root access, e.g. via a userdebug build of Android on a Google Nexus device
|
||||||
|
(see [here](https://source.android.com/source/building-running.html) and [here](https://source.android.com/source/building-devices.html#obtaining-proprietary-binaries))
|
||||||
|
- e.g. a calibrated machine that does not run background jobs, has a fixed cpu frequency, ...
|
||||||
|
|
||||||
|
* Use relative comparisons
|
||||||
|
- relative comparisons are less likely to change over time and help to interpret the results of benchmarks
|
||||||
|
- e.g. compare an example written using a ui framework against a hand coded example and track the ratio
|
||||||
|
|
||||||
|
* Assert post-commit for commit ranges
|
||||||
|
- running benchmarks can take some time. Running them before every commit is usually too slow.
|
||||||
|
- when a regression is detected for a commit range, use bisection to find the problematic commit
|
||||||
|
|
||||||
|
* Repeat benchmarks multiple times in a fresh window
|
||||||
|
- run the same benchmark multiple times in a fresh window and then take the minimal average value of each benchmark run
|
||||||
|
|
||||||
|
* Use force gc with care
|
||||||
|
- forcing gc can skew the script execution time and gcTime numbers,
|
||||||
|
but might be needed to get stable gc time / gc amount numbers
|
||||||
|
|
||||||
|
* Open a new window for every test
|
||||||
|
- browsers (e.g. chrome) might keep JIT statistics over page reloads and optimize pages differently depending on what has been loaded before
|
||||||
|
|
||||||
|
# Detailed overview
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Definitions:
|
||||||
|
|
||||||
|
* valid sample: a sample that represents the world that should be measured in a good way.
|
||||||
|
* complete sample: sample of all measure values collected so far
|
||||||
|
|
||||||
|
Components:
|
||||||
|
|
||||||
|
* Runner
|
||||||
|
- contains a default configuration
|
||||||
|
- creates a new injector for every sample call, via which all other components are created
|
||||||
|
|
||||||
|
* Sampler
|
||||||
|
- gets data from the metrics
|
||||||
|
- reports measure values immediately to the reporters
|
||||||
|
- loops until the validator is able to extract a valid sample out of the complete sample (see below).
|
||||||
|
- reports the valid sample and the complete sample to the reporters
|
||||||
|
|
||||||
|
* Metric
|
||||||
|
- gets measure values from the browser
|
||||||
|
- e.g. reads out performance logs, DOM values, JavaScript values
|
||||||
|
|
||||||
|
* Validator
|
||||||
|
- extracts a valid sample out of the complete sample of all measure values.
|
||||||
|
- e.g. wait until there are 10 samples and take them as valid sample (would include warmup time)
|
||||||
|
- e.g. wait until the regression slope for the metric `scriptTime` through the last 10 measure values is >=0, i.e. the values for the `scriptTime` metric are no more decreasing
|
||||||
|
|
||||||
|
* Reporter
|
||||||
|
- reports measure values, the valid sample and the complete sample to backends
|
||||||
|
- e.g. a reporter that prints to the console, a reporter that reports values into Google BigQuery, ...
|
||||||
|
|
||||||
|
* WebDriverAdapter
|
||||||
|
- abstraction over the used web driver client
|
||||||
|
- one implementation for every webdriver client
|
||||||
|
E.g. one for selenium-webdriver Node.js module, dart async webdriver, dart sync webdriver, ...
|
||||||
|
|
||||||
|
* WebDriverExtension
|
||||||
|
- implements additional methods that are standardized in the webdriver protocol using the WebDriverAdapter
|
||||||
|
- provides functionality like force gc, read out performance logs in a normalized format
|
||||||
|
- one implementation per browser, e.g. one for Chrome, one for mobile Safari, one for Firefox
|
||||||
|
|
||||||
|
|
BIN
modules/@angular/benchpress/docs/marked_timeline.png
Normal file
BIN
modules/@angular/benchpress/docs/marked_timeline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
modules/@angular/benchpress/docs/overview.png
Normal file
BIN
modules/@angular/benchpress/docs/overview.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
34
modules/@angular/benchpress/index.ts
Normal file
34
modules/@angular/benchpress/index.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Must be imported first, because angular2 decorators throws on load.
|
||||||
|
import 'reflect-metadata';
|
||||||
|
|
||||||
|
export {InjectionToken, Injector, Provider, ReflectiveInjector} from '@angular/core';
|
||||||
|
export {Options} from './src/common_options';
|
||||||
|
export {MeasureValues} from './src/measure_values';
|
||||||
|
export {Metric} from './src/metric';
|
||||||
|
export {MultiMetric} from './src/metric/multi_metric';
|
||||||
|
export {PerflogMetric} from './src/metric/perflog_metric';
|
||||||
|
export {UserMetric} from './src/metric/user_metric';
|
||||||
|
export {Reporter} from './src/reporter';
|
||||||
|
export {ConsoleReporter} from './src/reporter/console_reporter';
|
||||||
|
export {JsonFileReporter} from './src/reporter/json_file_reporter';
|
||||||
|
export {MultiReporter} from './src/reporter/multi_reporter';
|
||||||
|
export {Runner} from './src/runner';
|
||||||
|
export {SampleDescription} from './src/sample_description';
|
||||||
|
export {SampleState, Sampler} from './src/sampler';
|
||||||
|
export {Validator} from './src/validator';
|
||||||
|
export {RegressionSlopeValidator} from './src/validator/regression_slope_validator';
|
||||||
|
export {SizeValidator} from './src/validator/size_validator';
|
||||||
|
export {WebDriverAdapter} from './src/web_driver_adapter';
|
||||||
|
export {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from './src/web_driver_extension';
|
||||||
|
export {ChromeDriverExtension} from './src/webdriver/chrome_driver_extension';
|
||||||
|
export {FirefoxDriverExtension} from './src/webdriver/firefox_driver_extension';
|
||||||
|
export {IOsDriverExtension} from './src/webdriver/ios_driver_extension';
|
||||||
|
export {SeleniumWebDriverAdapter} from './src/webdriver/selenium_webdriver_adapter';
|
31
modules/@angular/benchpress/package.json
Normal file
31
modules/@angular/benchpress/package.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "@angular/benchpress",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Benchpress - a framework for e2e performance tests",
|
||||||
|
"main": "index.js",
|
||||||
|
"typings": "index.d.ts",
|
||||||
|
"dependencies": {
|
||||||
|
"@angular/core": "^2.0.0-rc.7",
|
||||||
|
"reflect-metadata": "^0.1.2",
|
||||||
|
"rxjs": "^5.0.1",
|
||||||
|
"jpm": "1.1.4",
|
||||||
|
"firefox-profile": "0.4.0",
|
||||||
|
"selenium-webdriver": "^2.53.3"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/angular/angular.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"angular",
|
||||||
|
"benchmarks"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"Tobias Bosch <tbosch@google.com> (https://angular.io/)"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/angular/angular/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/angular/angular/tree/master/modules/@angular/compiler-cli"
|
||||||
|
}
|
16
modules/@angular/benchpress/publish.sh
Executable file
16
modules/@angular/benchpress/publish.sh
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
cd $(dirname $0)/../../..
|
||||||
|
ROOTDIR=$(pwd)
|
||||||
|
SRCDIR=${ROOTDIR}/modules/@angular/benchpress
|
||||||
|
DESTDIR=${ROOTDIR}/dist/packages-dist/benchpress
|
||||||
|
|
||||||
|
rm -fr ${DESTDIR}
|
||||||
|
|
||||||
|
echo "====== BUILDING... ====="
|
||||||
|
./build.sh --packages=core,benchpress --bundle=false
|
||||||
|
|
||||||
|
echo "====== PUBLISHING: ${DESTDIR} ====="
|
||||||
|
npm publish ${DESTDIR} --access public
|
53
modules/@angular/benchpress/src/common_options.ts
Normal file
53
modules/@angular/benchpress/src/common_options.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {InjectionToken} from '@angular/core';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
export class Options {
|
||||||
|
static SAMPLE_ID = new InjectionToken('Options.sampleId');
|
||||||
|
static DEFAULT_DESCRIPTION = new InjectionToken('Options.defaultDescription');
|
||||||
|
static SAMPLE_DESCRIPTION = new InjectionToken('Options.sampleDescription');
|
||||||
|
static FORCE_GC = new InjectionToken('Options.forceGc');
|
||||||
|
static NO_PREPARE = () => true;
|
||||||
|
static PREPARE = new InjectionToken('Options.prepare');
|
||||||
|
static EXECUTE = new InjectionToken('Options.execute');
|
||||||
|
static CAPABILITIES = new InjectionToken('Options.capabilities');
|
||||||
|
static USER_AGENT = new InjectionToken('Options.userAgent');
|
||||||
|
static MICRO_METRICS = new InjectionToken('Options.microMetrics');
|
||||||
|
static USER_METRICS = new InjectionToken('Options.userMetrics');
|
||||||
|
static NOW = new InjectionToken('Options.now');
|
||||||
|
static WRITE_FILE = new InjectionToken('Options.writeFile');
|
||||||
|
static RECEIVED_DATA = new InjectionToken('Options.receivedData');
|
||||||
|
static REQUEST_COUNT = new InjectionToken('Options.requestCount');
|
||||||
|
static CAPTURE_FRAMES = new InjectionToken('Options.frameCapture');
|
||||||
|
static DEFAULT_PROVIDERS = [
|
||||||
|
{provide: Options.DEFAULT_DESCRIPTION, useValue: {}},
|
||||||
|
{provide: Options.SAMPLE_DESCRIPTION, useValue: {}},
|
||||||
|
{provide: Options.FORCE_GC, useValue: false},
|
||||||
|
{provide: Options.PREPARE, useValue: Options.NO_PREPARE},
|
||||||
|
{provide: Options.MICRO_METRICS, useValue: {}}, {provide: Options.USER_METRICS, useValue: {}},
|
||||||
|
{provide: Options.NOW, useValue: () => new Date()},
|
||||||
|
{provide: Options.RECEIVED_DATA, useValue: false},
|
||||||
|
{provide: Options.REQUEST_COUNT, useValue: false},
|
||||||
|
{provide: Options.CAPTURE_FRAMES, useValue: false},
|
||||||
|
{provide: Options.WRITE_FILE, useValue: writeFile}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeFile(filename: string, content: string): Promise<any> {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
fs.writeFile(filename, content, (error) => {
|
||||||
|
if (error) {
|
||||||
|
reject(error);
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
1
modules/@angular/benchpress/src/facade
Symbolic link
1
modules/@angular/benchpress/src/facade
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../facade/src
|
2
modules/@angular/benchpress/src/firefox_extension/.gitignore
vendored
Normal file
2
modules/@angular/benchpress/src/firefox_extension/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.xpi
|
||||||
|
addon-sdk*
|
@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare var exportFunction: any;
|
||||||
|
declare var unsafeWindow: any;
|
||||||
|
|
||||||
|
exportFunction(function() {
|
||||||
|
const curTime = unsafeWindow.performance.now();
|
||||||
|
(<any>self).port.emit('startProfiler', curTime);
|
||||||
|
}, unsafeWindow, {defineAs: 'startProfiler'});
|
||||||
|
|
||||||
|
exportFunction(function() {
|
||||||
|
(<any>self).port.emit('stopProfiler');
|
||||||
|
}, unsafeWindow, {defineAs: 'stopProfiler'});
|
||||||
|
|
||||||
|
exportFunction(function(cb: Function) {
|
||||||
|
(<any>self).port.once('perfProfile', cb);
|
||||||
|
(<any>self).port.emit('getProfile');
|
||||||
|
}, unsafeWindow, {defineAs: 'getProfile'});
|
||||||
|
|
||||||
|
exportFunction(function() {
|
||||||
|
(<any>self).port.emit('forceGC');
|
||||||
|
}, unsafeWindow, {defineAs: 'forceGC'});
|
||||||
|
|
||||||
|
exportFunction(function(name: string) {
|
||||||
|
const curTime = unsafeWindow.performance.now();
|
||||||
|
(<any>self).port.emit('markStart', name, curTime);
|
||||||
|
}, unsafeWindow, {defineAs: 'markStart'});
|
||||||
|
|
||||||
|
exportFunction(function(name: string) {
|
||||||
|
const curTime = unsafeWindow.performance.now();
|
||||||
|
(<any>self).port.emit('markEnd', name, curTime);
|
||||||
|
}, unsafeWindow, {defineAs: 'markEnd'});
|
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
const {Cc, Ci, Cu} = require('chrome');
|
||||||
|
const os = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
|
||||||
|
const ParserUtil = require('./parser_util');
|
||||||
|
|
||||||
|
class Profiler {
|
||||||
|
private _profiler: any;
|
||||||
|
private _markerEvents: any[];
|
||||||
|
private _profilerStartTime: number;
|
||||||
|
|
||||||
|
constructor() { this._profiler = Cc['@mozilla.org/tools/profiler;1'].getService(Ci.nsIProfiler); }
|
||||||
|
|
||||||
|
start(entries: any, interval: any, features: any, timeStarted: any) {
|
||||||
|
this._profiler.StartProfiler(entries, interval, features, features.length);
|
||||||
|
this._profilerStartTime = timeStarted;
|
||||||
|
this._markerEvents = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
stop() { this._profiler.StopProfiler(); }
|
||||||
|
|
||||||
|
getProfilePerfEvents() {
|
||||||
|
const profileData = this._profiler.getProfileData();
|
||||||
|
let perfEvents = ParserUtil.convertPerfProfileToEvents(profileData);
|
||||||
|
perfEvents = this._mergeMarkerEvents(perfEvents);
|
||||||
|
perfEvents.sort(function(event1: any, event2: any) {
|
||||||
|
return event1.ts - event2.ts;
|
||||||
|
}); // Sort by ts
|
||||||
|
return perfEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
private _mergeMarkerEvents(perfEvents: any[]): any[] {
|
||||||
|
this._markerEvents.forEach(function(markerEvent) { perfEvents.push(markerEvent); });
|
||||||
|
return perfEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
addStartEvent(name: string, timeStarted: number) {
|
||||||
|
this._markerEvents.push({ph: 'B', ts: timeStarted - this._profilerStartTime, name: name});
|
||||||
|
}
|
||||||
|
|
||||||
|
addEndEvent(name: string, timeEnded: number) {
|
||||||
|
this._markerEvents.push({ph: 'E', ts: timeEnded - this._profilerStartTime, name: name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function forceGC() {
|
||||||
|
Cu.forceGC();
|
||||||
|
os.notifyObservers(null, 'child-gc-request', null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mod = require('sdk/page-mod');
|
||||||
|
const data = require('sdk/self').data;
|
||||||
|
const profiler = new Profiler();
|
||||||
|
mod.PageMod({
|
||||||
|
include: ['*'],
|
||||||
|
contentScriptFile: data.url('installed_script.js'),
|
||||||
|
onAttach: (worker: any) => {
|
||||||
|
worker.port.on(
|
||||||
|
'startProfiler',
|
||||||
|
(timeStarted: any) => profiler.start(
|
||||||
|
/* = profiler memory */ 3000000, 0.1, ['leaf', 'js', 'stackwalk', 'gc'], timeStarted));
|
||||||
|
worker.port.on('stopProfiler', () => profiler.stop());
|
||||||
|
worker.port.on(
|
||||||
|
'getProfile', () => worker.port.emit('perfProfile', profiler.getProfilePerfEvents()));
|
||||||
|
worker.port.on('forceGC', forceGC);
|
||||||
|
worker.port.on(
|
||||||
|
'markStart', (name: string, timeStarted: any) => profiler.addStartEvent(name, timeStarted));
|
||||||
|
worker.port.on(
|
||||||
|
'markEnd', (name: string, timeEnded: any) => profiler.addEndEvent(name, timeEnded));
|
||||||
|
}
|
||||||
|
});
|
@ -0,0 +1,92 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} perfProfile The perf profile JSON object.
|
||||||
|
* @return {Object[]} An array of recognized events that are captured
|
||||||
|
* within the perf profile.
|
||||||
|
*/
|
||||||
|
export function convertPerfProfileToEvents(perfProfile: any): any[] {
|
||||||
|
const inProgressEvents = new Map(); // map from event name to start time
|
||||||
|
const finishedEvents: {[key: string]: any}[] = []; // Event[] finished events
|
||||||
|
const addFinishedEvent = function(eventName: string, startTime: number, endTime: number) {
|
||||||
|
const categorizedEventName = categorizeEvent(eventName);
|
||||||
|
let args: {[key: string]: any} = undefined;
|
||||||
|
if (categorizedEventName == 'gc') {
|
||||||
|
// TODO: We cannot measure heap size at the moment
|
||||||
|
args = {usedHeapSize: 0};
|
||||||
|
}
|
||||||
|
if (startTime == endTime) {
|
||||||
|
// Finished instantly
|
||||||
|
finishedEvents.push({ph: 'X', ts: startTime, name: categorizedEventName, args: args});
|
||||||
|
} else {
|
||||||
|
// Has duration
|
||||||
|
finishedEvents.push({ph: 'B', ts: startTime, name: categorizedEventName, args: args});
|
||||||
|
finishedEvents.push({ph: 'E', ts: endTime, name: categorizedEventName, args: args});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const samples = perfProfile.threads[0].samples;
|
||||||
|
// In perf profile, firefox samples all the frames in set time intervals. Here
|
||||||
|
// we go through all the samples and construct the start and end time for each
|
||||||
|
// event.
|
||||||
|
for (let i = 0; i < samples.length; ++i) {
|
||||||
|
const sample = samples[i];
|
||||||
|
const sampleTime = sample.time;
|
||||||
|
|
||||||
|
// Add all the frames into a set so it's easier/faster to find the set
|
||||||
|
// differences
|
||||||
|
const sampleFrames = new Set();
|
||||||
|
sample.frames.forEach(function(frame: {[key: string]: any}) {
|
||||||
|
sampleFrames.add(frame['location']);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If an event is in the inProgressEvents map, but not in the current sample,
|
||||||
|
// then it must have just finished. We add this event to the finishedEvents
|
||||||
|
// array and remove it from the inProgressEvents map.
|
||||||
|
const previousSampleTime = (i == 0 ? /* not used */ -1 : samples[i - 1].time);
|
||||||
|
inProgressEvents.forEach(function(startTime, eventName) {
|
||||||
|
if (!(sampleFrames.has(eventName))) {
|
||||||
|
addFinishedEvent(eventName, startTime, previousSampleTime);
|
||||||
|
inProgressEvents.delete(eventName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// If an event is in the current sample, but not in the inProgressEvents map,
|
||||||
|
// then it must have just started. We add this event to the inProgressEvents
|
||||||
|
// map.
|
||||||
|
sampleFrames.forEach(function(eventName) {
|
||||||
|
if (!(inProgressEvents.has(eventName))) {
|
||||||
|
inProgressEvents.set(eventName, sampleTime);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// If anything is still in progress, we need to included it as a finished event
|
||||||
|
// since recording ended.
|
||||||
|
const lastSampleTime = samples[samples.length - 1].time;
|
||||||
|
inProgressEvents.forEach(function(startTime, eventName) {
|
||||||
|
addFinishedEvent(eventName, startTime, lastSampleTime);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove all the unknown categories.
|
||||||
|
return finishedEvents.filter(function(event) { return event['name'] != 'unknown'; });
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this is most likely not exhaustive.
|
||||||
|
export function categorizeEvent(eventName: string): string {
|
||||||
|
if (eventName.indexOf('PresShell::Paint') > -1) {
|
||||||
|
return 'render';
|
||||||
|
} else if (eventName.indexOf('FirefoxDriver.prototype.executeScript') > -1) {
|
||||||
|
return 'script';
|
||||||
|
} else if (eventName.indexOf('forceGC') > -1) {
|
||||||
|
return 'gc';
|
||||||
|
} else {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
const q = require('q');
|
||||||
|
const FirefoxProfile = require('firefox-profile');
|
||||||
|
const jpm = require('jpm/lib/xpi');
|
||||||
|
const pathUtil = require('path');
|
||||||
|
|
||||||
|
const PERF_ADDON_PACKAGE_JSON_DIR = '..';
|
||||||
|
|
||||||
|
exports.getAbsolutePath = function(path: string) {
|
||||||
|
const normalizedPath = pathUtil.normalize(path);
|
||||||
|
if (pathUtil.resolve(normalizedPath) == normalizedPath) {
|
||||||
|
// Already absolute path
|
||||||
|
return normalizedPath;
|
||||||
|
} else {
|
||||||
|
return pathUtil.join(__dirname, normalizedPath);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getFirefoxProfile = function(extensionPath: string) {
|
||||||
|
const deferred = q.defer();
|
||||||
|
|
||||||
|
const firefoxProfile = new FirefoxProfile();
|
||||||
|
firefoxProfile.addExtensions([extensionPath], () => {
|
||||||
|
firefoxProfile.encoded((encodedProfile: any) => {
|
||||||
|
const multiCapabilities = [{browserName: 'firefox', firefox_profile: encodedProfile}];
|
||||||
|
deferred.resolve(multiCapabilities);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.getFirefoxProfileWithExtension = function() {
|
||||||
|
const absPackageJsonDir = pathUtil.join(__dirname, PERF_ADDON_PACKAGE_JSON_DIR);
|
||||||
|
const packageJson = require(pathUtil.join(absPackageJsonDir, 'package.json'));
|
||||||
|
|
||||||
|
const savedCwd = process.cwd();
|
||||||
|
process.chdir(absPackageJsonDir);
|
||||||
|
|
||||||
|
return jpm(packageJson).then((xpiPath: string) => {
|
||||||
|
process.chdir(savedCwd);
|
||||||
|
return exports.getFirefoxProfile(xpiPath);
|
||||||
|
});
|
||||||
|
};
|
@ -0,0 +1 @@
|
|||||||
|
{ "version" : "0.0.1", "main" : "lib/main.js", "name" : "ffperf-addon" }
|
20
modules/@angular/benchpress/src/measure_values.ts
Normal file
20
modules/@angular/benchpress/src/measure_values.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class MeasureValues {
|
||||||
|
constructor(
|
||||||
|
public runIndex: number, public timeStamp: Date, public values: {[key: string]: any}) {}
|
||||||
|
|
||||||
|
toJson() {
|
||||||
|
return {
|
||||||
|
'timeStamp': this.timeStamp.toJSON(),
|
||||||
|
'runIndex': this.runIndex,
|
||||||
|
'values': this.values,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
31
modules/@angular/benchpress/src/metric.ts
Normal file
31
modules/@angular/benchpress/src/metric.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A metric is measures values
|
||||||
|
*/
|
||||||
|
export abstract class Metric {
|
||||||
|
/**
|
||||||
|
* Starts measuring
|
||||||
|
*/
|
||||||
|
beginMeasure(): Promise<any> { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends measuring and reports the data
|
||||||
|
* since the begin call.
|
||||||
|
* @param restart: Whether to restart right after this.
|
||||||
|
*/
|
||||||
|
endMeasure(restart: boolean): Promise<{[key: string]: any}> { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the metrics provided by this metric implementation.
|
||||||
|
* (e.g. units, ...)
|
||||||
|
*/
|
||||||
|
describe(): {[key: string]: string} { throw new Error('NYI'); }
|
||||||
|
}
|
63
modules/@angular/benchpress/src/metric/multi_metric.ts
Normal file
63
modules/@angular/benchpress/src/metric/multi_metric.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {InjectionToken, Injector} from '@angular/core';
|
||||||
|
|
||||||
|
import {Metric} from '../metric';
|
||||||
|
|
||||||
|
export class MultiMetric extends Metric {
|
||||||
|
static provideWith(childTokens: any[]): any[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
provide: _CHILDREN,
|
||||||
|
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
|
||||||
|
deps: [Injector]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: MultiMetric,
|
||||||
|
useFactory: (children: Metric[]) => new MultiMetric(children),
|
||||||
|
deps: [_CHILDREN]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private _metrics: Metric[]) { super(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts measuring
|
||||||
|
*/
|
||||||
|
beginMeasure(): Promise<any> {
|
||||||
|
return Promise.all(this._metrics.map(metric => metric.beginMeasure()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends measuring and reports the data
|
||||||
|
* since the begin call.
|
||||||
|
* @param restart: Whether to restart right after this.
|
||||||
|
*/
|
||||||
|
endMeasure(restart: boolean): Promise<{[key: string]: any}> {
|
||||||
|
return Promise.all(this._metrics.map(metric => metric.endMeasure(restart)))
|
||||||
|
.then(values => mergeStringMaps(<any>values));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the metrics provided by this metric implementation.
|
||||||
|
* (e.g. units, ...)
|
||||||
|
*/
|
||||||
|
describe(): {[key: string]: any} {
|
||||||
|
return mergeStringMaps(this._metrics.map((metric) => metric.describe()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeStringMaps(maps: {[key: string]: string}[]): {[key: string]: string} {
|
||||||
|
const result: {[key: string]: string} = {};
|
||||||
|
maps.forEach(map => { Object.keys(map).forEach(prop => { result[prop] = map[prop]; }); });
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _CHILDREN = new InjectionToken('MultiMetric.children');
|
371
modules/@angular/benchpress/src/metric/perflog_metric.ts
Normal file
371
modules/@angular/benchpress/src/metric/perflog_metric.ts
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable, InjectionToken} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from '../common_options';
|
||||||
|
import {Metric} from '../metric';
|
||||||
|
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A metric that reads out the performance log
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class PerflogMetric extends Metric {
|
||||||
|
static SET_TIMEOUT = new InjectionToken('PerflogMetric.setTimeout');
|
||||||
|
static PROVIDERS = [
|
||||||
|
PerflogMetric, {
|
||||||
|
provide: PerflogMetric.SET_TIMEOUT,
|
||||||
|
useValue: (fn: Function, millis: number) => <any>setTimeout(fn, millis)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
private _remainingEvents: PerfLogEvent[];
|
||||||
|
private _measureCount: number;
|
||||||
|
private _perfLogFeatures: PerfLogFeatures;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param driverExtension
|
||||||
|
* @param setTimeout
|
||||||
|
* @param microMetrics Name and description of metrics provided via console.time / console.timeEnd
|
||||||
|
**/
|
||||||
|
constructor(
|
||||||
|
private _driverExtension: WebDriverExtension,
|
||||||
|
@Inject(PerflogMetric.SET_TIMEOUT) private _setTimeout: Function,
|
||||||
|
@Inject(Options.MICRO_METRICS) private _microMetrics: {[key: string]: string},
|
||||||
|
@Inject(Options.FORCE_GC) private _forceGc: boolean,
|
||||||
|
@Inject(Options.CAPTURE_FRAMES) private _captureFrames: boolean,
|
||||||
|
@Inject(Options.RECEIVED_DATA) private _receivedData: boolean,
|
||||||
|
@Inject(Options.REQUEST_COUNT) private _requestCount: boolean) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._remainingEvents = [];
|
||||||
|
this._measureCount = 0;
|
||||||
|
this._perfLogFeatures = _driverExtension.perfLogFeatures();
|
||||||
|
if (!this._perfLogFeatures.userTiming) {
|
||||||
|
// User timing is needed for navigationStart.
|
||||||
|
this._receivedData = false;
|
||||||
|
this._requestCount = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe(): {[key: string]: string} {
|
||||||
|
const res: {[key: string]: any} = {
|
||||||
|
'scriptTime': 'script execution time in ms, including gc and render',
|
||||||
|
'pureScriptTime': 'script execution time in ms, without gc nor render'
|
||||||
|
};
|
||||||
|
if (this._perfLogFeatures.render) {
|
||||||
|
res['renderTime'] = 'render time in ms';
|
||||||
|
}
|
||||||
|
if (this._perfLogFeatures.gc) {
|
||||||
|
res['gcTime'] = 'gc time in ms';
|
||||||
|
res['gcAmount'] = 'gc amount in kbytes';
|
||||||
|
res['majorGcTime'] = 'time of major gcs in ms';
|
||||||
|
if (this._forceGc) {
|
||||||
|
res['forcedGcTime'] = 'forced gc time in ms';
|
||||||
|
res['forcedGcAmount'] = 'forced gc amount in kbytes';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._receivedData) {
|
||||||
|
res['receivedData'] = 'encoded bytes received since navigationStart';
|
||||||
|
}
|
||||||
|
if (this._requestCount) {
|
||||||
|
res['requestCount'] = 'count of requests sent since navigationStart';
|
||||||
|
}
|
||||||
|
if (this._captureFrames) {
|
||||||
|
if (!this._perfLogFeatures.frameCapture) {
|
||||||
|
const warningMsg = 'WARNING: Metric requested, but not supported by driver';
|
||||||
|
// using dot syntax for metric name to keep them grouped together in console reporter
|
||||||
|
res['frameTime.mean'] = warningMsg;
|
||||||
|
res['frameTime.worst'] = warningMsg;
|
||||||
|
res['frameTime.best'] = warningMsg;
|
||||||
|
res['frameTime.smooth'] = warningMsg;
|
||||||
|
} else {
|
||||||
|
res['frameTime.mean'] = 'mean frame time in ms (target: 16.6ms for 60fps)';
|
||||||
|
res['frameTime.worst'] = 'worst frame time in ms';
|
||||||
|
res['frameTime.best'] = 'best frame time in ms';
|
||||||
|
res['frameTime.smooth'] = 'percentage of frames that hit 60fps';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const name in this._microMetrics) {
|
||||||
|
res[name] = this._microMetrics[name];
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginMeasure(): Promise<any> {
|
||||||
|
let resultPromise = Promise.resolve(null);
|
||||||
|
if (this._forceGc) {
|
||||||
|
resultPromise = resultPromise.then((_) => this._driverExtension.gc());
|
||||||
|
}
|
||||||
|
return resultPromise.then((_) => this._beginMeasure());
|
||||||
|
}
|
||||||
|
|
||||||
|
endMeasure(restart: boolean): Promise<{[key: string]: number}> {
|
||||||
|
if (this._forceGc) {
|
||||||
|
return this._endPlainMeasureAndMeasureForceGc(restart);
|
||||||
|
} else {
|
||||||
|
return this._endMeasure(restart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
private _endPlainMeasureAndMeasureForceGc(restartMeasure: boolean) {
|
||||||
|
return this._endMeasure(true).then((measureValues) => {
|
||||||
|
// disable frame capture for measurements during forced gc
|
||||||
|
const originalFrameCaptureValue = this._captureFrames;
|
||||||
|
this._captureFrames = false;
|
||||||
|
return this._driverExtension.gc()
|
||||||
|
.then((_) => this._endMeasure(restartMeasure))
|
||||||
|
.then((forceGcMeasureValues) => {
|
||||||
|
this._captureFrames = originalFrameCaptureValue;
|
||||||
|
measureValues['forcedGcTime'] = forceGcMeasureValues['gcTime'];
|
||||||
|
measureValues['forcedGcAmount'] = forceGcMeasureValues['gcAmount'];
|
||||||
|
return measureValues;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _beginMeasure(): Promise<any> {
|
||||||
|
return this._driverExtension.timeBegin(this._markName(this._measureCount++));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _endMeasure(restart: boolean): Promise<{[key: string]: number}> {
|
||||||
|
const markName = this._markName(this._measureCount - 1);
|
||||||
|
const nextMarkName = restart ? this._markName(this._measureCount++) : null;
|
||||||
|
return this._driverExtension.timeEnd(markName, nextMarkName)
|
||||||
|
.then((_) => this._readUntilEndMark(markName));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _readUntilEndMark(
|
||||||
|
markName: string, loopCount: number = 0, startEvent: PerfLogEvent = null) {
|
||||||
|
if (loopCount > _MAX_RETRY_COUNT) {
|
||||||
|
throw new Error(`Tried too often to get the ending mark: ${loopCount}`);
|
||||||
|
}
|
||||||
|
return this._driverExtension.readPerfLog().then((events) => {
|
||||||
|
this._addEvents(events);
|
||||||
|
const result = this._aggregateEvents(this._remainingEvents, markName);
|
||||||
|
if (result) {
|
||||||
|
this._remainingEvents = events;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
let resolve: (result: any) => void;
|
||||||
|
const promise = new Promise(res => { resolve = res; });
|
||||||
|
this._setTimeout(() => resolve(this._readUntilEndMark(markName, loopCount + 1)), 100);
|
||||||
|
return promise;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _addEvents(events: PerfLogEvent[]) {
|
||||||
|
let needSort = false;
|
||||||
|
events.forEach(event => {
|
||||||
|
if (event['ph'] === 'X') {
|
||||||
|
needSort = true;
|
||||||
|
const startEvent: PerfLogEvent = {};
|
||||||
|
const endEvent: PerfLogEvent = {};
|
||||||
|
for (const prop in event) {
|
||||||
|
startEvent[prop] = event[prop];
|
||||||
|
endEvent[prop] = event[prop];
|
||||||
|
}
|
||||||
|
startEvent['ph'] = 'B';
|
||||||
|
endEvent['ph'] = 'E';
|
||||||
|
endEvent['ts'] = startEvent['ts'] + startEvent['dur'];
|
||||||
|
this._remainingEvents.push(startEvent);
|
||||||
|
this._remainingEvents.push(endEvent);
|
||||||
|
} else {
|
||||||
|
this._remainingEvents.push(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (needSort) {
|
||||||
|
// Need to sort because of the ph==='X' events
|
||||||
|
this._remainingEvents.sort((a, b) => {
|
||||||
|
const diff = a['ts'] - b['ts'];
|
||||||
|
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _aggregateEvents(events: PerfLogEvent[], markName: string): {[key: string]: number} {
|
||||||
|
const result: {[key: string]: number} = {'scriptTime': 0, 'pureScriptTime': 0};
|
||||||
|
if (this._perfLogFeatures.gc) {
|
||||||
|
result['gcTime'] = 0;
|
||||||
|
result['majorGcTime'] = 0;
|
||||||
|
result['gcAmount'] = 0;
|
||||||
|
}
|
||||||
|
if (this._perfLogFeatures.render) {
|
||||||
|
result['renderTime'] = 0;
|
||||||
|
}
|
||||||
|
if (this._captureFrames) {
|
||||||
|
result['frameTime.mean'] = 0;
|
||||||
|
result['frameTime.best'] = 0;
|
||||||
|
result['frameTime.worst'] = 0;
|
||||||
|
result['frameTime.smooth'] = 0;
|
||||||
|
}
|
||||||
|
for (const name in this._microMetrics) {
|
||||||
|
result[name] = 0;
|
||||||
|
}
|
||||||
|
if (this._receivedData) {
|
||||||
|
result['receivedData'] = 0;
|
||||||
|
}
|
||||||
|
if (this._requestCount) {
|
||||||
|
result['requestCount'] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let markStartEvent: PerfLogEvent = null;
|
||||||
|
let markEndEvent: PerfLogEvent = null;
|
||||||
|
events.forEach((event) => {
|
||||||
|
const ph = event['ph'];
|
||||||
|
const name = event['name'];
|
||||||
|
if (ph === 'B' && name === markName) {
|
||||||
|
markStartEvent = event;
|
||||||
|
} else if (ph === 'I' && name === 'navigationStart') {
|
||||||
|
// if a benchmark measures reload of a page, use the last
|
||||||
|
// navigationStart as begin event
|
||||||
|
markStartEvent = event;
|
||||||
|
} else if (ph === 'E' && name === markName) {
|
||||||
|
markEndEvent = event;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!markStartEvent || !markEndEvent) {
|
||||||
|
// not all events have been received, no further processing for now
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let gcTimeInScript = 0;
|
||||||
|
let renderTimeInScript = 0;
|
||||||
|
|
||||||
|
const frameTimestamps: number[] = [];
|
||||||
|
const frameTimes: number[] = [];
|
||||||
|
let frameCaptureStartEvent: PerfLogEvent = null;
|
||||||
|
let frameCaptureEndEvent: PerfLogEvent = null;
|
||||||
|
|
||||||
|
const intervalStarts: {[key: string]: PerfLogEvent} = {};
|
||||||
|
const intervalStartCount: {[key: string]: number} = {};
|
||||||
|
|
||||||
|
let inMeasureRange = false;
|
||||||
|
events.forEach((event) => {
|
||||||
|
const ph = event['ph'];
|
||||||
|
let name = event['name'];
|
||||||
|
let microIterations = 1;
|
||||||
|
const microIterationsMatch = name.match(_MICRO_ITERATIONS_REGEX);
|
||||||
|
if (microIterationsMatch) {
|
||||||
|
name = microIterationsMatch[1];
|
||||||
|
microIterations = parseInt(microIterationsMatch[2], 10);
|
||||||
|
}
|
||||||
|
if (event === markStartEvent) {
|
||||||
|
inMeasureRange = true;
|
||||||
|
} else if (event === markEndEvent) {
|
||||||
|
inMeasureRange = false;
|
||||||
|
}
|
||||||
|
if (!inMeasureRange || event['pid'] !== markStartEvent['pid']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._requestCount && name === 'sendRequest') {
|
||||||
|
result['requestCount'] += 1;
|
||||||
|
} else if (this._receivedData && name === 'receivedData' && ph === 'I') {
|
||||||
|
result['receivedData'] += event['args']['encodedDataLength'];
|
||||||
|
}
|
||||||
|
if (ph === 'B' && name === _MARK_NAME_FRAME_CAPUTRE) {
|
||||||
|
if (frameCaptureStartEvent) {
|
||||||
|
throw new Error('can capture frames only once per benchmark run');
|
||||||
|
}
|
||||||
|
if (!this._captureFrames) {
|
||||||
|
throw new Error(
|
||||||
|
'found start event for frame capture, but frame capture was not requested in benchpress');
|
||||||
|
}
|
||||||
|
frameCaptureStartEvent = event;
|
||||||
|
} else if (ph === 'E' && name === _MARK_NAME_FRAME_CAPUTRE) {
|
||||||
|
if (!frameCaptureStartEvent) {
|
||||||
|
throw new Error('missing start event for frame capture');
|
||||||
|
}
|
||||||
|
frameCaptureEndEvent = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ph === 'I' && frameCaptureStartEvent && !frameCaptureEndEvent && name === 'frame') {
|
||||||
|
frameTimestamps.push(event['ts']);
|
||||||
|
if (frameTimestamps.length >= 2) {
|
||||||
|
frameTimes.push(
|
||||||
|
frameTimestamps[frameTimestamps.length - 1] -
|
||||||
|
frameTimestamps[frameTimestamps.length - 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ph === 'B') {
|
||||||
|
if (!intervalStarts[name]) {
|
||||||
|
intervalStartCount[name] = 1;
|
||||||
|
intervalStarts[name] = event;
|
||||||
|
} else {
|
||||||
|
intervalStartCount[name]++;
|
||||||
|
}
|
||||||
|
} else if ((ph === 'E') && intervalStarts[name]) {
|
||||||
|
intervalStartCount[name]--;
|
||||||
|
if (intervalStartCount[name] === 0) {
|
||||||
|
const startEvent = intervalStarts[name];
|
||||||
|
const duration = (event['ts'] - startEvent['ts']);
|
||||||
|
intervalStarts[name] = null;
|
||||||
|
if (name === 'gc') {
|
||||||
|
result['gcTime'] += duration;
|
||||||
|
const amount =
|
||||||
|
(startEvent['args']['usedHeapSize'] - event['args']['usedHeapSize']) / 1000;
|
||||||
|
result['gcAmount'] += amount;
|
||||||
|
const majorGc = event['args']['majorGc'];
|
||||||
|
if (majorGc && majorGc) {
|
||||||
|
result['majorGcTime'] += duration;
|
||||||
|
}
|
||||||
|
if (intervalStarts['script']) {
|
||||||
|
gcTimeInScript += duration;
|
||||||
|
}
|
||||||
|
} else if (name === 'render') {
|
||||||
|
result['renderTime'] += duration;
|
||||||
|
if (intervalStarts['script']) {
|
||||||
|
renderTimeInScript += duration;
|
||||||
|
}
|
||||||
|
} else if (name === 'script') {
|
||||||
|
result['scriptTime'] += duration;
|
||||||
|
} else if (this._microMetrics[name]) {
|
||||||
|
(<any>result)[name] += duration / microIterations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (frameCaptureStartEvent && !frameCaptureEndEvent) {
|
||||||
|
throw new Error('missing end event for frame capture');
|
||||||
|
}
|
||||||
|
if (this._captureFrames && !frameCaptureStartEvent) {
|
||||||
|
throw new Error('frame capture requested in benchpress, but no start event was found');
|
||||||
|
}
|
||||||
|
if (frameTimes.length > 0) {
|
||||||
|
this._addFrameMetrics(result, frameTimes);
|
||||||
|
}
|
||||||
|
result['pureScriptTime'] = result['scriptTime'] - gcTimeInScript - renderTimeInScript;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _addFrameMetrics(result: {[key: string]: number}, frameTimes: any[]) {
|
||||||
|
result['frameTime.mean'] = frameTimes.reduce((a, b) => a + b, 0) / frameTimes.length;
|
||||||
|
const firstFrame = frameTimes[0];
|
||||||
|
result['frameTime.worst'] = frameTimes.reduce((a, b) => a > b ? a : b, firstFrame);
|
||||||
|
result['frameTime.best'] = frameTimes.reduce((a, b) => a < b ? a : b, firstFrame);
|
||||||
|
result['frameTime.smooth'] =
|
||||||
|
frameTimes.filter(t => t < _FRAME_TIME_SMOOTH_THRESHOLD).length / frameTimes.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _markName(index: number) { return `${_MARK_NAME_PREFIX}${index}`; }
|
||||||
|
}
|
||||||
|
|
||||||
|
const _MICRO_ITERATIONS_REGEX = /(.+)\*(\d+)$/;
|
||||||
|
|
||||||
|
const _MAX_RETRY_COUNT = 20;
|
||||||
|
const _MARK_NAME_PREFIX = 'benchpress';
|
||||||
|
|
||||||
|
const _MARK_NAME_FRAME_CAPUTRE = 'frameCapture';
|
||||||
|
// using 17ms as a somewhat looser threshold, instead of 16.6666ms
|
||||||
|
const _FRAME_TIME_SMOOTH_THRESHOLD = 17;
|
69
modules/@angular/benchpress/src/metric/user_metric.ts
Normal file
69
modules/@angular/benchpress/src/metric/user_metric.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from '../common_options';
|
||||||
|
import {Metric} from '../metric';
|
||||||
|
import {WebDriverAdapter} from '../web_driver_adapter';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserMetric extends Metric {
|
||||||
|
static PROVIDERS = [UserMetric];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(Options.USER_METRICS) private _userMetrics: {[key: string]: string},
|
||||||
|
private _wdAdapter: WebDriverAdapter) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts measuring
|
||||||
|
*/
|
||||||
|
beginMeasure(): Promise<any> { return Promise.resolve(true); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ends measuring.
|
||||||
|
*/
|
||||||
|
endMeasure(restart: boolean): Promise<{[key: string]: any}> {
|
||||||
|
let resolve: (result: any) => void;
|
||||||
|
let reject: (error: any) => void;
|
||||||
|
const promise = new Promise((res, rej) => {
|
||||||
|
resolve = res;
|
||||||
|
reject = rej;
|
||||||
|
});
|
||||||
|
const adapter = this._wdAdapter;
|
||||||
|
const names = Object.keys(this._userMetrics);
|
||||||
|
|
||||||
|
function getAndClearValues() {
|
||||||
|
Promise.all(names.map(name => adapter.executeScript(`return window.${name}`)))
|
||||||
|
.then((values: any[]) => {
|
||||||
|
if (values.every(v => typeof v === 'number')) {
|
||||||
|
Promise.all(names.map(name => adapter.executeScript(`delete window.${name}`)))
|
||||||
|
.then((_: any[]) => {
|
||||||
|
const map: {[k: string]: any} = {};
|
||||||
|
for (let i = 0, n = names.length; i < n; i++) {
|
||||||
|
map[names[i]] = values[i];
|
||||||
|
}
|
||||||
|
resolve(map);
|
||||||
|
}, reject);
|
||||||
|
} else {
|
||||||
|
<any>setTimeout(getAndClearValues, 100);
|
||||||
|
}
|
||||||
|
}, reject);
|
||||||
|
}
|
||||||
|
getAndClearValues();
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the metrics provided by this metric implementation.
|
||||||
|
* (e.g. units, ...)
|
||||||
|
*/
|
||||||
|
describe(): {[key: string]: any} { return this._userMetrics; }
|
||||||
|
}
|
20
modules/@angular/benchpress/src/reporter.ts
Normal file
20
modules/@angular/benchpress/src/reporter.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {MeasureValues} from './measure_values';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reporter reports measure values and the valid sample.
|
||||||
|
*/
|
||||||
|
export abstract class Reporter {
|
||||||
|
reportMeasureValues(values: MeasureValues): Promise<any> { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any> {
|
||||||
|
throw new Error('NYI');
|
||||||
|
}
|
||||||
|
}
|
83
modules/@angular/benchpress/src/reporter/console_reporter.ts
Normal file
83
modules/@angular/benchpress/src/reporter/console_reporter.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable, InjectionToken} from '@angular/core';
|
||||||
|
import {print} from '../facade/lang';
|
||||||
|
import {MeasureValues} from '../measure_values';
|
||||||
|
import {Reporter} from '../reporter';
|
||||||
|
import {SampleDescription} from '../sample_description';
|
||||||
|
|
||||||
|
import {formatNum, formatStats, sortedProps} from './util';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reporter for the console
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class ConsoleReporter extends Reporter {
|
||||||
|
static PRINT = new InjectionToken('ConsoleReporter.print');
|
||||||
|
static COLUMN_WIDTH = new InjectionToken('ConsoleReporter.columnWidth');
|
||||||
|
static PROVIDERS = [
|
||||||
|
ConsoleReporter, {provide: ConsoleReporter.COLUMN_WIDTH, useValue: 18},
|
||||||
|
{provide: ConsoleReporter.PRINT, useValue: print}
|
||||||
|
];
|
||||||
|
|
||||||
|
private static _lpad(value: string, columnWidth: number, fill = ' ') {
|
||||||
|
let result = '';
|
||||||
|
for (let i = 0; i < columnWidth - value.length; i++) {
|
||||||
|
result += fill;
|
||||||
|
}
|
||||||
|
return result + value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _metricNames: string[];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(ConsoleReporter.COLUMN_WIDTH) private _columnWidth: number,
|
||||||
|
sampleDescription: SampleDescription,
|
||||||
|
@Inject(ConsoleReporter.PRINT) private _print: Function) {
|
||||||
|
super();
|
||||||
|
this._metricNames = sortedProps(sampleDescription.metrics);
|
||||||
|
this._printDescription(sampleDescription);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _printDescription(sampleDescription: SampleDescription) {
|
||||||
|
this._print(`BENCHMARK ${sampleDescription.id}`);
|
||||||
|
this._print('Description:');
|
||||||
|
const props = sortedProps(sampleDescription.description);
|
||||||
|
props.forEach((prop) => { this._print(`- ${prop}: ${sampleDescription.description[prop]}`); });
|
||||||
|
this._print('Metrics:');
|
||||||
|
this._metricNames.forEach((metricName) => {
|
||||||
|
this._print(`- ${metricName}: ${sampleDescription.metrics[metricName]}`);
|
||||||
|
});
|
||||||
|
this._print('');
|
||||||
|
this._printStringRow(this._metricNames);
|
||||||
|
this._printStringRow(this._metricNames.map((_) => ''), '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
reportMeasureValues(measureValues: MeasureValues): Promise<any> {
|
||||||
|
const formattedValues = this._metricNames.map(metricName => {
|
||||||
|
const value = measureValues.values[metricName];
|
||||||
|
return formatNum(value);
|
||||||
|
});
|
||||||
|
this._printStringRow(formattedValues);
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
reportSample(completeSample: MeasureValues[], validSamples: MeasureValues[]): Promise<any> {
|
||||||
|
this._printStringRow(this._metricNames.map((_) => ''), '=');
|
||||||
|
this._printStringRow(
|
||||||
|
this._metricNames.map(metricName => formatStats(validSamples, metricName)));
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _printStringRow(parts: any[], fill = ' ') {
|
||||||
|
this._print(
|
||||||
|
parts.map(part => ConsoleReporter._lpad(part, this._columnWidth, fill)).join(' | '));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable, InjectionToken} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from '../common_options';
|
||||||
|
import {MeasureValues} from '../measure_values';
|
||||||
|
import {Reporter} from '../reporter';
|
||||||
|
import {SampleDescription} from '../sample_description';
|
||||||
|
|
||||||
|
import {formatStats, sortedProps} from './util';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A reporter that writes results into a json file.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class JsonFileReporter extends Reporter {
|
||||||
|
static PATH = new InjectionToken('JsonFileReporter.path');
|
||||||
|
static PROVIDERS = [JsonFileReporter, {provide: JsonFileReporter.PATH, useValue: '.'}];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _description: SampleDescription, @Inject(JsonFileReporter.PATH) private _path: string,
|
||||||
|
@Inject(Options.WRITE_FILE) private _writeFile: Function,
|
||||||
|
@Inject(Options.NOW) private _now: Function) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
reportMeasureValues(measureValues: MeasureValues): Promise<any> { return Promise.resolve(null); }
|
||||||
|
|
||||||
|
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any> {
|
||||||
|
const stats: {[key: string]: string} = {};
|
||||||
|
sortedProps(this._description.metrics).forEach((metricName) => {
|
||||||
|
stats[metricName] = formatStats(validSample, metricName);
|
||||||
|
});
|
||||||
|
const content = JSON.stringify(
|
||||||
|
{
|
||||||
|
'description': this._description,
|
||||||
|
'stats': stats,
|
||||||
|
'completeSample': completeSample,
|
||||||
|
'validSample': validSample,
|
||||||
|
},
|
||||||
|
null, 2);
|
||||||
|
const filePath = `${this._path}/${this._description.id}_${this._now().getTime()}.json`;
|
||||||
|
return this._writeFile(filePath, content);
|
||||||
|
}
|
||||||
|
}
|
42
modules/@angular/benchpress/src/reporter/multi_reporter.ts
Normal file
42
modules/@angular/benchpress/src/reporter/multi_reporter.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {InjectionToken, Injector} from '@angular/core';
|
||||||
|
|
||||||
|
import {MeasureValues} from '../measure_values';
|
||||||
|
import {Reporter} from '../reporter';
|
||||||
|
|
||||||
|
export class MultiReporter extends Reporter {
|
||||||
|
static provideWith(childTokens: any[]): any[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
provide: _CHILDREN,
|
||||||
|
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
|
||||||
|
deps: [Injector],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: MultiReporter,
|
||||||
|
useFactory: (children: Reporter[]) => new MultiReporter(children),
|
||||||
|
deps: [_CHILDREN]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(private _reporters: Reporter[]) { super(); }
|
||||||
|
|
||||||
|
reportMeasureValues(values: MeasureValues): Promise<any[]> {
|
||||||
|
return Promise.all(this._reporters.map(reporter => reporter.reportMeasureValues(values)));
|
||||||
|
}
|
||||||
|
|
||||||
|
reportSample(completeSample: MeasureValues[], validSample: MeasureValues[]): Promise<any[]> {
|
||||||
|
return Promise.all(
|
||||||
|
this._reporters.map(reporter => reporter.reportSample(completeSample, validSample)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _CHILDREN = new InjectionToken('MultiReporter.children');
|
28
modules/@angular/benchpress/src/reporter/util.ts
Normal file
28
modules/@angular/benchpress/src/reporter/util.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {MeasureValues} from '../measure_values';
|
||||||
|
import {Statistic} from '../statistic';
|
||||||
|
|
||||||
|
export function formatNum(n: number) {
|
||||||
|
return n.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sortedProps(obj: {[key: string]: any}) {
|
||||||
|
return Object.keys(obj).sort();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatStats(validSamples: MeasureValues[], metricName: string): string {
|
||||||
|
const samples = validSamples.map(measureValues => measureValues.values[metricName]);
|
||||||
|
const mean = Statistic.calculateMean(samples);
|
||||||
|
const cv = Statistic.calculateCoefficientOfVariation(samples, mean);
|
||||||
|
const formattedMean = formatNum(mean);
|
||||||
|
// Note: Don't use the unicode character for +- as it might cause
|
||||||
|
// hickups for consoles...
|
||||||
|
return isNaN(cv) ? formattedMean : `${formattedMean}+-${Math.floor(cv)}%`;
|
||||||
|
}
|
110
modules/@angular/benchpress/src/runner.ts
Normal file
110
modules/@angular/benchpress/src/runner.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Provider, ReflectiveInjector} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from './common_options';
|
||||||
|
import {isPresent} from './facade/lang';
|
||||||
|
import {Metric} from './metric';
|
||||||
|
import {MultiMetric} from './metric/multi_metric';
|
||||||
|
import {PerflogMetric} from './metric/perflog_metric';
|
||||||
|
import {UserMetric} from './metric/user_metric';
|
||||||
|
import {Reporter} from './reporter';
|
||||||
|
import {ConsoleReporter} from './reporter/console_reporter';
|
||||||
|
import {MultiReporter} from './reporter/multi_reporter';
|
||||||
|
import {SampleDescription} from './sample_description';
|
||||||
|
import {SampleState, Sampler} from './sampler';
|
||||||
|
import {Validator} from './validator';
|
||||||
|
import {RegressionSlopeValidator} from './validator/regression_slope_validator';
|
||||||
|
import {SizeValidator} from './validator/size_validator';
|
||||||
|
import {WebDriverAdapter} from './web_driver_adapter';
|
||||||
|
import {WebDriverExtension} from './web_driver_extension';
|
||||||
|
import {ChromeDriverExtension} from './webdriver/chrome_driver_extension';
|
||||||
|
import {FirefoxDriverExtension} from './webdriver/firefox_driver_extension';
|
||||||
|
import {IOsDriverExtension} from './webdriver/ios_driver_extension';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Runner is the main entry point for executing a sample run.
|
||||||
|
* It provides defaults, creates the injector and calls the sampler.
|
||||||
|
*/
|
||||||
|
export class Runner {
|
||||||
|
constructor(private _defaultProviders: Provider[] = []) {}
|
||||||
|
|
||||||
|
sample({id, execute, prepare, microMetrics, providers, userMetrics}: {
|
||||||
|
id: string,
|
||||||
|
execute?: Function,
|
||||||
|
prepare?: Function,
|
||||||
|
microMetrics?: {[key: string]: string},
|
||||||
|
providers?: Provider[],
|
||||||
|
userMetrics?: {[key: string]: string}
|
||||||
|
}): Promise<SampleState> {
|
||||||
|
const sampleProviders: Provider[] = [
|
||||||
|
_DEFAULT_PROVIDERS, this._defaultProviders, {provide: Options.SAMPLE_ID, useValue: id},
|
||||||
|
{provide: Options.EXECUTE, useValue: execute}
|
||||||
|
];
|
||||||
|
if (isPresent(prepare)) {
|
||||||
|
sampleProviders.push({provide: Options.PREPARE, useValue: prepare});
|
||||||
|
}
|
||||||
|
if (isPresent(microMetrics)) {
|
||||||
|
sampleProviders.push({provide: Options.MICRO_METRICS, useValue: microMetrics});
|
||||||
|
}
|
||||||
|
if (isPresent(userMetrics)) {
|
||||||
|
sampleProviders.push({provide: Options.USER_METRICS, useValue: userMetrics});
|
||||||
|
}
|
||||||
|
if (isPresent(providers)) {
|
||||||
|
sampleProviders.push(providers);
|
||||||
|
}
|
||||||
|
|
||||||
|
const inj = ReflectiveInjector.resolveAndCreate(sampleProviders);
|
||||||
|
const adapter: WebDriverAdapter = inj.get(WebDriverAdapter);
|
||||||
|
|
||||||
|
return Promise
|
||||||
|
.all([adapter.capabilities(), adapter.executeScript('return window.navigator.userAgent;')])
|
||||||
|
.then((args) => {
|
||||||
|
const capabilities = args[0];
|
||||||
|
const userAgent = args[1];
|
||||||
|
|
||||||
|
// This might still create instances twice. We are creating a new injector with all the
|
||||||
|
// providers.
|
||||||
|
// Only WebDriverAdapter is reused.
|
||||||
|
// TODO vsavkin consider changing it when toAsyncFactory is added back or when child
|
||||||
|
// injectors are handled better.
|
||||||
|
const injector = ReflectiveInjector.resolveAndCreate([
|
||||||
|
sampleProviders, {provide: Options.CAPABILITIES, useValue: capabilities},
|
||||||
|
{provide: Options.USER_AGENT, useValue: userAgent},
|
||||||
|
{provide: WebDriverAdapter, useValue: adapter}
|
||||||
|
]);
|
||||||
|
|
||||||
|
const sampler = injector.get(Sampler);
|
||||||
|
return sampler.sample();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _DEFAULT_PROVIDERS = [
|
||||||
|
Options.DEFAULT_PROVIDERS,
|
||||||
|
Sampler.PROVIDERS,
|
||||||
|
ConsoleReporter.PROVIDERS,
|
||||||
|
RegressionSlopeValidator.PROVIDERS,
|
||||||
|
SizeValidator.PROVIDERS,
|
||||||
|
ChromeDriverExtension.PROVIDERS,
|
||||||
|
FirefoxDriverExtension.PROVIDERS,
|
||||||
|
IOsDriverExtension.PROVIDERS,
|
||||||
|
PerflogMetric.PROVIDERS,
|
||||||
|
UserMetric.PROVIDERS,
|
||||||
|
SampleDescription.PROVIDERS,
|
||||||
|
MultiReporter.provideWith([ConsoleReporter]),
|
||||||
|
MultiMetric.provideWith([PerflogMetric, UserMetric]),
|
||||||
|
{provide: Reporter, useExisting: MultiReporter},
|
||||||
|
{provide: Validator, useExisting: RegressionSlopeValidator},
|
||||||
|
WebDriverExtension.provideFirstSupported(
|
||||||
|
[ChromeDriverExtension, FirefoxDriverExtension, IOsDriverExtension]),
|
||||||
|
{provide: Metric, useExisting: MultiMetric},
|
||||||
|
];
|
49
modules/@angular/benchpress/src/sample_description.ts
Normal file
49
modules/@angular/benchpress/src/sample_description.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {InjectionToken} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from './common_options';
|
||||||
|
import {Metric} from './metric';
|
||||||
|
import {Validator} from './validator';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SampleDescription merges all available descriptions about a sample
|
||||||
|
*/
|
||||||
|
export class SampleDescription {
|
||||||
|
static PROVIDERS = [{
|
||||||
|
provide: SampleDescription,
|
||||||
|
useFactory:
|
||||||
|
(metric: Metric, id: string, forceGc: boolean, userAgent: string, validator: Validator,
|
||||||
|
defaultDesc: {[key: string]: string}, userDesc: {[key: string]: string}) =>
|
||||||
|
new SampleDescription(
|
||||||
|
id,
|
||||||
|
[
|
||||||
|
{'forceGc': forceGc, 'userAgent': userAgent}, validator.describe(), defaultDesc,
|
||||||
|
userDesc
|
||||||
|
],
|
||||||
|
metric.describe()),
|
||||||
|
deps: [
|
||||||
|
Metric, Options.SAMPLE_ID, Options.FORCE_GC, Options.USER_AGENT, Validator,
|
||||||
|
Options.DEFAULT_DESCRIPTION, Options.SAMPLE_DESCRIPTION
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
description: {[key: string]: any};
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public id: string, descriptions: Array<{[key: string]: any}>,
|
||||||
|
public metrics: {[key: string]: any}) {
|
||||||
|
this.description = {};
|
||||||
|
descriptions.forEach(description => {
|
||||||
|
Object.keys(description).forEach(prop => { this.description[prop] = description[prop]; });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toJson() { return {'id': this.id, 'description': this.description, 'metrics': this.metrics}; }
|
||||||
|
}
|
81
modules/@angular/benchpress/src/sampler.ts
Normal file
81
modules/@angular/benchpress/src/sampler.ts
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from './common_options';
|
||||||
|
import {isPresent} from './facade/lang';
|
||||||
|
import {MeasureValues} from './measure_values';
|
||||||
|
import {Metric} from './metric';
|
||||||
|
import {Reporter} from './reporter';
|
||||||
|
import {Validator} from './validator';
|
||||||
|
import {WebDriverAdapter} from './web_driver_adapter';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Sampler owns the sample loop:
|
||||||
|
* 1. calls the prepare/execute callbacks,
|
||||||
|
* 2. gets data from the metric
|
||||||
|
* 3. asks the validator for a valid sample
|
||||||
|
* 4. reports the new data to the reporter
|
||||||
|
* 5. loop until there is a valid sample
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class Sampler {
|
||||||
|
static PROVIDERS = [Sampler];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private _driver: WebDriverAdapter, private _metric: Metric, private _reporter: Reporter,
|
||||||
|
private _validator: Validator, @Inject(Options.PREPARE) private _prepare: Function,
|
||||||
|
@Inject(Options.EXECUTE) private _execute: Function,
|
||||||
|
@Inject(Options.NOW) private _now: Function) {}
|
||||||
|
|
||||||
|
sample(): Promise<SampleState> {
|
||||||
|
const loop = (lastState: SampleState): Promise<SampleState> => {
|
||||||
|
return this._iterate(lastState).then((newState) => {
|
||||||
|
if (isPresent(newState.validSample)) {
|
||||||
|
return newState;
|
||||||
|
} else {
|
||||||
|
return loop(newState);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return loop(new SampleState([], null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _iterate(lastState: SampleState): Promise<SampleState> {
|
||||||
|
let resultPromise: Promise<SampleState>;
|
||||||
|
if (this._prepare !== Options.NO_PREPARE) {
|
||||||
|
resultPromise = this._driver.waitFor(this._prepare);
|
||||||
|
} else {
|
||||||
|
resultPromise = Promise.resolve(null);
|
||||||
|
}
|
||||||
|
if (this._prepare !== Options.NO_PREPARE || lastState.completeSample.length === 0) {
|
||||||
|
resultPromise = resultPromise.then((_) => this._metric.beginMeasure());
|
||||||
|
}
|
||||||
|
return resultPromise.then((_) => this._driver.waitFor(this._execute))
|
||||||
|
.then((_) => this._metric.endMeasure(this._prepare === Options.NO_PREPARE))
|
||||||
|
.then((measureValues) => this._report(lastState, measureValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
private _report(state: SampleState, metricValues: {[key: string]: any}): Promise<SampleState> {
|
||||||
|
const measureValues = new MeasureValues(state.completeSample.length, this._now(), metricValues);
|
||||||
|
const completeSample = state.completeSample.concat([measureValues]);
|
||||||
|
const validSample = this._validator.validate(completeSample);
|
||||||
|
let resultPromise = this._reporter.reportMeasureValues(measureValues);
|
||||||
|
if (isPresent(validSample)) {
|
||||||
|
resultPromise =
|
||||||
|
resultPromise.then((_) => this._reporter.reportSample(completeSample, validSample));
|
||||||
|
}
|
||||||
|
return resultPromise.then((_) => new SampleState(completeSample, validSample));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SampleState {
|
||||||
|
constructor(public completeSample: MeasureValues[], public validSample: MeasureValues[]) {}
|
||||||
|
}
|
41
modules/@angular/benchpress/src/statistic.ts
Normal file
41
modules/@angular/benchpress/src/statistic.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class Statistic {
|
||||||
|
static calculateCoefficientOfVariation(sample: number[], mean: number) {
|
||||||
|
return Statistic.calculateStandardDeviation(sample, mean) / mean * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
static calculateMean(samples: number[]) {
|
||||||
|
let total = 0;
|
||||||
|
// TODO: use reduce
|
||||||
|
samples.forEach(x => total += x);
|
||||||
|
return total / samples.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static calculateStandardDeviation(samples: number[], mean: number) {
|
||||||
|
let deviation = 0;
|
||||||
|
// TODO: use reduce
|
||||||
|
samples.forEach(x => deviation += Math.pow(x - mean, 2));
|
||||||
|
deviation = deviation / (samples.length);
|
||||||
|
deviation = Math.sqrt(deviation);
|
||||||
|
return deviation;
|
||||||
|
}
|
||||||
|
|
||||||
|
static calculateRegressionSlope(
|
||||||
|
xValues: number[], xMean: number, yValues: number[], yMean: number) {
|
||||||
|
// See http://en.wikipedia.org/wiki/Simple_linear_regression
|
||||||
|
let dividendSum = 0;
|
||||||
|
let divisorSum = 0;
|
||||||
|
for (let i = 0; i < xValues.length; i++) {
|
||||||
|
dividendSum += (xValues[i] - xMean) * (yValues[i] - yMean);
|
||||||
|
divisorSum += Math.pow(xValues[i] - xMean, 2);
|
||||||
|
}
|
||||||
|
return dividendSum / divisorSum;
|
||||||
|
}
|
||||||
|
}
|
27
modules/@angular/benchpress/src/validator.ts
Normal file
27
modules/@angular/benchpress/src/validator.ts
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {MeasureValues} from './measure_values';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Validator calculates a valid sample out of the complete sample.
|
||||||
|
* A valid sample is a sample that represents the population that should be observed
|
||||||
|
* in the correct way.
|
||||||
|
*/
|
||||||
|
export abstract class Validator {
|
||||||
|
/**
|
||||||
|
* Calculates a valid sample out of the complete sample
|
||||||
|
*/
|
||||||
|
validate(completeSample: MeasureValues[]): MeasureValues[] { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Map that describes the properties of the validator
|
||||||
|
* (e.g. sample size, ...)
|
||||||
|
*/
|
||||||
|
describe(): {[key: string]: any} { throw new Error('NYI'); }
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable, InjectionToken} from '@angular/core';
|
||||||
|
|
||||||
|
import {MeasureValues} from '../measure_values';
|
||||||
|
import {Statistic} from '../statistic';
|
||||||
|
import {Validator} from '../validator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A validator that checks the regression slope of a specific metric.
|
||||||
|
* Waits for the regression slope to be >=0.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class RegressionSlopeValidator extends Validator {
|
||||||
|
static SAMPLE_SIZE = new InjectionToken('RegressionSlopeValidator.sampleSize');
|
||||||
|
static METRIC = new InjectionToken('RegressionSlopeValidator.metric');
|
||||||
|
static PROVIDERS = [
|
||||||
|
RegressionSlopeValidator, {provide: RegressionSlopeValidator.SAMPLE_SIZE, useValue: 10},
|
||||||
|
{provide: RegressionSlopeValidator.METRIC, useValue: 'scriptTime'}
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
@Inject(RegressionSlopeValidator.SAMPLE_SIZE) private _sampleSize: number,
|
||||||
|
@Inject(RegressionSlopeValidator.METRIC) private _metric: string) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe(): {[key: string]: any} {
|
||||||
|
return {'sampleSize': this._sampleSize, 'regressionSlopeMetric': this._metric};
|
||||||
|
}
|
||||||
|
|
||||||
|
validate(completeSample: MeasureValues[]): MeasureValues[] {
|
||||||
|
if (completeSample.length >= this._sampleSize) {
|
||||||
|
const latestSample =
|
||||||
|
completeSample.slice(completeSample.length - this._sampleSize, completeSample.length);
|
||||||
|
const xValues: number[] = [];
|
||||||
|
const yValues: number[] = [];
|
||||||
|
for (let i = 0; i < latestSample.length; i++) {
|
||||||
|
// For now, we only use the array index as x value.
|
||||||
|
// TODO(tbosch): think about whether we should use time here instead
|
||||||
|
xValues.push(i);
|
||||||
|
yValues.push(latestSample[i].values[this._metric]);
|
||||||
|
}
|
||||||
|
const regressionSlope = Statistic.calculateRegressionSlope(
|
||||||
|
xValues, Statistic.calculateMean(xValues), yValues, Statistic.calculateMean(yValues));
|
||||||
|
return regressionSlope >= 0 ? latestSample : null;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
modules/@angular/benchpress/src/validator/size_validator.ts
Normal file
33
modules/@angular/benchpress/src/validator/size_validator.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable, InjectionToken} from '@angular/core';
|
||||||
|
|
||||||
|
import {MeasureValues} from '../measure_values';
|
||||||
|
import {Validator} from '../validator';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A validator that waits for the sample to have a certain size.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class SizeValidator extends Validator {
|
||||||
|
static SAMPLE_SIZE = new InjectionToken('SizeValidator.sampleSize');
|
||||||
|
static PROVIDERS = [SizeValidator, {provide: SizeValidator.SAMPLE_SIZE, useValue: 10}];
|
||||||
|
|
||||||
|
constructor(@Inject(SizeValidator.SAMPLE_SIZE) private _sampleSize: number) { super(); }
|
||||||
|
|
||||||
|
describe(): {[key: string]: any} { return {'sampleSize': this._sampleSize}; }
|
||||||
|
|
||||||
|
validate(completeSample: MeasureValues[]): MeasureValues[] {
|
||||||
|
if (completeSample.length >= this._sampleSize) {
|
||||||
|
return completeSample.slice(completeSample.length - this._sampleSize, completeSample.length);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
modules/@angular/benchpress/src/web_driver_adapter.ts
Normal file
22
modules/@angular/benchpress/src/web_driver_adapter.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A WebDriverAdapter bridges API differences between different WebDriver clients,
|
||||||
|
* e.g. JS vs Dart Async vs Dart Sync webdriver.
|
||||||
|
* Needs one implementation for every supported WebDriver client.
|
||||||
|
*/
|
||||||
|
export abstract class WebDriverAdapter {
|
||||||
|
waitFor(callback: Function): Promise<any> { throw new Error('NYI'); }
|
||||||
|
executeScript(script: string): Promise<any> { throw new Error('NYI'); }
|
||||||
|
executeAsyncScript(script: string): Promise<any> { throw new Error('NYI'); }
|
||||||
|
capabilities(): Promise<{[key: string]: any}> { throw new Error('NYI'); }
|
||||||
|
logs(type: string): Promise<any[]> { throw new Error('NYI'); }
|
||||||
|
}
|
104
modules/@angular/benchpress/src/web_driver_extension.ts
Normal file
104
modules/@angular/benchpress/src/web_driver_extension.ts
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {InjectionToken, Injector} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from './common_options';
|
||||||
|
|
||||||
|
export type PerfLogEvent = {
|
||||||
|
[key: string]: any
|
||||||
|
} & {
|
||||||
|
ph?: 'X' | 'B' | 'E' | 'I',
|
||||||
|
ts?: number,
|
||||||
|
dur?: number,
|
||||||
|
name?: string,
|
||||||
|
pid?: string,
|
||||||
|
args?: {
|
||||||
|
encodedDataLength?: number,
|
||||||
|
usedHeapSize?: number,
|
||||||
|
majorGc?: boolean,
|
||||||
|
url?: string,
|
||||||
|
method?: string
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A WebDriverExtension implements extended commands of the webdriver protocol
|
||||||
|
* for a given browser, independent of the WebDriverAdapter.
|
||||||
|
* Needs one implementation for every supported Browser.
|
||||||
|
*/
|
||||||
|
export abstract class WebDriverExtension {
|
||||||
|
static provideFirstSupported(childTokens: any[]): any[] {
|
||||||
|
const res = [
|
||||||
|
{
|
||||||
|
provide: _CHILDREN,
|
||||||
|
useFactory: (injector: Injector) => childTokens.map(token => injector.get(token)),
|
||||||
|
deps: [Injector]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: WebDriverExtension,
|
||||||
|
useFactory: (children: WebDriverExtension[], capabilities: {[key: string]: any}) => {
|
||||||
|
let delegate: WebDriverExtension;
|
||||||
|
children.forEach(extension => {
|
||||||
|
if (extension.supports(capabilities)) {
|
||||||
|
delegate = extension;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!delegate) {
|
||||||
|
throw new Error('Could not find a delegate for given capabilities!');
|
||||||
|
}
|
||||||
|
return delegate;
|
||||||
|
},
|
||||||
|
deps: [_CHILDREN, Options.CAPABILITIES]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
gc(): Promise<any> { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
timeBegin(name: string): Promise<any> { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
timeEnd(name: string, restartName: string): Promise<any> { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format:
|
||||||
|
* - cat: category of the event
|
||||||
|
* - name: event name: 'script', 'gc', 'render', ...
|
||||||
|
* - ph: phase: 'B' (begin), 'E' (end), 'X' (Complete event), 'I' (Instant event)
|
||||||
|
* - ts: timestamp in ms, e.g. 12345
|
||||||
|
* - pid: process id
|
||||||
|
* - args: arguments, e.g. {heapSize: 1234}
|
||||||
|
*
|
||||||
|
* Based on [Chrome Trace Event
|
||||||
|
*Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit)
|
||||||
|
**/
|
||||||
|
readPerfLog(): Promise<PerfLogEvent[]> { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
perfLogFeatures(): PerfLogFeatures { throw new Error('NYI'); }
|
||||||
|
|
||||||
|
supports(capabilities: {[key: string]: any}): boolean { return true; }
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PerfLogFeatures {
|
||||||
|
render: boolean;
|
||||||
|
gc: boolean;
|
||||||
|
frameCapture: boolean;
|
||||||
|
userTiming: boolean;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
{render = false, gc = false, frameCapture = false, userTiming = false}:
|
||||||
|
{render?: boolean, gc?: boolean, frameCapture?: boolean, userTiming?: boolean} = {}) {
|
||||||
|
this.render = render;
|
||||||
|
this.gc = gc;
|
||||||
|
this.frameCapture = frameCapture;
|
||||||
|
this.userTiming = userTiming;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const _CHILDREN = new InjectionToken('WebDriverExtension.children');
|
@ -0,0 +1,208 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Inject, Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
import {Options} from '../common_options';
|
||||||
|
import {WebDriverAdapter} from '../web_driver_adapter';
|
||||||
|
import {PerfLogEvent, PerfLogFeatures, WebDriverExtension} from '../web_driver_extension';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the following 'traceCategories' to collect metrics in Chrome:
|
||||||
|
* 'v8,blink.console,disabled-by-default-devtools.timeline,devtools.timeline,blink.user_timing'
|
||||||
|
*
|
||||||
|
* In order to collect the frame rate related metrics, add 'benchmark'
|
||||||
|
* to the list above.
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class ChromeDriverExtension extends WebDriverExtension {
|
||||||
|
static PROVIDERS = [ChromeDriverExtension];
|
||||||
|
|
||||||
|
private _majorChromeVersion: number;
|
||||||
|
|
||||||
|
constructor(private _driver: WebDriverAdapter, @Inject(Options.USER_AGENT) userAgent: string) {
|
||||||
|
super();
|
||||||
|
this._majorChromeVersion = this._parseChromeVersion(userAgent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _parseChromeVersion(userAgent: string): number {
|
||||||
|
if (!userAgent) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
let v = userAgent.split(/Chrom(e|ium)\//g)[2];
|
||||||
|
if (!v) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
v = v.split('.')[0];
|
||||||
|
if (!v) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return parseInt(v, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
gc() { return this._driver.executeScript('window.gc()'); }
|
||||||
|
|
||||||
|
timeBegin(name: string): Promise<any> {
|
||||||
|
return this._driver.executeScript(`console.time('${name}');`);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeEnd(name: string, restartName: string = null): Promise<any> {
|
||||||
|
let script = `console.timeEnd('${name}');`;
|
||||||
|
if (restartName) {
|
||||||
|
script += `console.time('${restartName}');`;
|
||||||
|
}
|
||||||
|
return this._driver.executeScript(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See [Chrome Trace Event
|
||||||
|
// Format](https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit)
|
||||||
|
readPerfLog(): Promise<PerfLogEvent[]> {
|
||||||
|
// TODO(tbosch): Chromedriver bug https://code.google.com/p/chromedriver/issues/detail?id=1098
|
||||||
|
// Need to execute at least one command so that the browser logs can be read out!
|
||||||
|
return this._driver.executeScript('1+1')
|
||||||
|
.then((_) => this._driver.logs('performance'))
|
||||||
|
.then((entries) => {
|
||||||
|
const events: PerfLogEvent[] = [];
|
||||||
|
entries.forEach(entry => {
|
||||||
|
const message = JSON.parse(entry['message'])['message'];
|
||||||
|
if (message['method'] === 'Tracing.dataCollected') {
|
||||||
|
events.push(message['params']);
|
||||||
|
}
|
||||||
|
if (message['method'] === 'Tracing.bufferUsage') {
|
||||||
|
throw new Error('The DevTools trace buffer filled during the test!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return this._convertPerfRecordsToEvents(events);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private _convertPerfRecordsToEvents(
|
||||||
|
chromeEvents: Array<{[key: string]: any}>, normalizedEvents: PerfLogEvent[] = null) {
|
||||||
|
if (!normalizedEvents) {
|
||||||
|
normalizedEvents = [];
|
||||||
|
}
|
||||||
|
chromeEvents.forEach((event) => {
|
||||||
|
const categories = this._parseCategories(event['cat']);
|
||||||
|
const normalizedEvent = this._convertEvent(event, categories);
|
||||||
|
if (normalizedEvent != null) normalizedEvents.push(normalizedEvent);
|
||||||
|
});
|
||||||
|
return normalizedEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _convertEvent(event: {[key: string]: any}, categories: string[]) {
|
||||||
|
const name = event['name'];
|
||||||
|
const args = event['args'];
|
||||||
|
if (this._isEvent(categories, name, ['blink.console'])) {
|
||||||
|
return normalizeEvent(event, {'name': name});
|
||||||
|
} else if (this._isEvent(
|
||||||
|
categories, name, ['benchmark'],
|
||||||
|
'BenchmarkInstrumentation::ImplThreadRenderingStats')) {
|
||||||
|
// TODO(goderbauer): Instead of BenchmarkInstrumentation::ImplThreadRenderingStats the
|
||||||
|
// following events should be used (if available) for more accurate measurments:
|
||||||
|
// 1st choice: vsync_before - ground truth on Android
|
||||||
|
// 2nd choice: BenchmarkInstrumentation::DisplayRenderingStats - available on systems with
|
||||||
|
// new surfaces framework (not broadly enabled yet)
|
||||||
|
// 3rd choice: BenchmarkInstrumentation::ImplThreadRenderingStats - fallback event that is
|
||||||
|
// always available if something is rendered
|
||||||
|
const frameCount = event['args']['data']['frame_count'];
|
||||||
|
if (frameCount > 1) {
|
||||||
|
throw new Error('multi-frame render stats not supported');
|
||||||
|
}
|
||||||
|
if (frameCount == 1) {
|
||||||
|
return normalizeEvent(event, {'name': 'frame'});
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
this._isEvent(categories, name, ['disabled-by-default-devtools.timeline'], 'Rasterize') ||
|
||||||
|
this._isEvent(
|
||||||
|
categories, name, ['disabled-by-default-devtools.timeline'], 'CompositeLayers')) {
|
||||||
|
return normalizeEvent(event, {'name': 'render'});
|
||||||
|
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MajorGC')) {
|
||||||
|
const normArgs = {
|
||||||
|
'majorGc': true,
|
||||||
|
'usedHeapSize': args['usedHeapSizeAfter'] !== undefined ? args['usedHeapSizeAfter'] :
|
||||||
|
args['usedHeapSizeBefore']
|
||||||
|
};
|
||||||
|
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
|
||||||
|
} else if (this._isEvent(categories, name, ['devtools.timeline', 'v8'], 'MinorGC')) {
|
||||||
|
const normArgs = {
|
||||||
|
'majorGc': false,
|
||||||
|
'usedHeapSize': args['usedHeapSizeAfter'] !== undefined ? args['usedHeapSizeAfter'] :
|
||||||
|
args['usedHeapSizeBefore']
|
||||||
|
};
|
||||||
|
return normalizeEvent(event, {'name': 'gc', 'args': normArgs});
|
||||||
|
} else if (
|
||||||
|
this._isEvent(categories, name, ['devtools.timeline'], 'FunctionCall') &&
|
||||||
|
(!args || !args['data'] ||
|
||||||
|
(args['data']['scriptName'] !== 'InjectedScript' && args['data']['scriptName'] !== ''))) {
|
||||||
|
return normalizeEvent(event, {'name': 'script'});
|
||||||
|
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'EvaluateScript')) {
|
||||||
|
return normalizeEvent(event, {'name': 'script'});
|
||||||
|
} else if (this._isEvent(
|
||||||
|
categories, name, ['devtools.timeline', 'blink'], 'UpdateLayoutTree')) {
|
||||||
|
return normalizeEvent(event, {'name': 'render'});
|
||||||
|
} else if (
|
||||||
|
this._isEvent(categories, name, ['devtools.timeline'], 'UpdateLayerTree') ||
|
||||||
|
this._isEvent(categories, name, ['devtools.timeline'], 'Layout') ||
|
||||||
|
this._isEvent(categories, name, ['devtools.timeline'], 'Paint')) {
|
||||||
|
return normalizeEvent(event, {'name': 'render'});
|
||||||
|
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'ResourceReceivedData')) {
|
||||||
|
const normArgs = {'encodedDataLength': args['data']['encodedDataLength']};
|
||||||
|
return normalizeEvent(event, {'name': 'receivedData', 'args': normArgs});
|
||||||
|
} else if (this._isEvent(categories, name, ['devtools.timeline'], 'ResourceSendRequest')) {
|
||||||
|
const data = args['data'];
|
||||||
|
const normArgs = {'url': data['url'], 'method': data['requestMethod']};
|
||||||
|
return normalizeEvent(event, {'name': 'sendRequest', 'args': normArgs});
|
||||||
|
} else if (this._isEvent(categories, name, ['blink.user_timing'], 'navigationStart')) {
|
||||||
|
return normalizeEvent(event, {'name': 'navigationStart'});
|
||||||
|
}
|
||||||
|
return null; // nothing useful in this event
|
||||||
|
}
|
||||||
|
|
||||||
|
private _parseCategories(categories: string): string[] { return categories.split(','); }
|
||||||
|
|
||||||
|
private _isEvent(
|
||||||
|
eventCategories: string[], eventName: string, expectedCategories: string[],
|
||||||
|
expectedName: string = null): boolean {
|
||||||
|
const hasCategories = expectedCategories.reduce(
|
||||||
|
(value, cat) => value && eventCategories.indexOf(cat) !== -1, true);
|
||||||
|
return !expectedName ? hasCategories : hasCategories && eventName === expectedName;
|
||||||
|
}
|
||||||
|
|
||||||
|
perfLogFeatures(): PerfLogFeatures {
|
||||||
|
return new PerfLogFeatures({render: true, gc: true, frameCapture: true, userTiming: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
supports(capabilities: {[key: string]: any}): boolean {
|
||||||
|
return this._majorChromeVersion >= 44 && capabilities['browserName'].toLowerCase() === 'chrome';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeEvent(chromeEvent: {[key: string]: any}, data: PerfLogEvent): PerfLogEvent {
|
||||||
|
let ph = chromeEvent['ph'].toUpperCase();
|
||||||
|
if (ph === 'S') {
|
||||||
|
ph = 'B';
|
||||||
|
} else if (ph === 'F') {
|
||||||
|
ph = 'E';
|
||||||
|
} else if (ph === 'R') {
|
||||||
|
// mark events from navigation timing
|
||||||
|
ph = 'I';
|
||||||
|
}
|
||||||
|
const result: {[key: string]: any} =
|
||||||
|
{'pid': chromeEvent['pid'], 'ph': ph, 'cat': 'timeline', 'ts': chromeEvent['ts'] / 1000};
|
||||||
|
if (ph === 'X') {
|
||||||
|
let dur = chromeEvent['dur'];
|
||||||
|
if (dur === undefined) {
|
||||||
|
dur = chromeEvent['tdur'];
|
||||||
|
}
|
||||||
|
result['dur'] = !dur ? 0.0 : dur / 1000;
|
||||||
|
}
|
||||||
|
for (const prop in data) {
|
||||||
|
result[prop] = data[prop];
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user