Compare commits
516
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a4dc8de41 | ||
|
|
18595b01b6 | ||
|
|
f7215fc685 | ||
|
|
08521d4651 | ||
|
|
00b177d75f | ||
|
|
a89a071049 | ||
|
|
f9dc8a091a | ||
|
|
944299ed6c | ||
|
|
0e1441155c | ||
|
|
7bf5dfe4e4 | ||
|
|
d4c34fc9f7 | ||
|
|
6811005551 | ||
|
|
464cefa127 | ||
|
|
c94a1ab5d3 | ||
|
|
8aa5b35605 | ||
|
|
25dd1fb31a | ||
|
|
d8cf2c8b44 | ||
|
|
938c5d08d4 | ||
|
|
7fca2b8de3 | ||
|
|
ef19ad3ffd | ||
|
|
ab88527fe6 | ||
|
|
6c0ff1881a | ||
|
|
1e7f4c8474 | ||
|
|
fdf491d4ec | ||
|
|
1f4cceca43 | ||
|
|
542eaca577 | ||
|
|
1cb6f56418 | ||
|
|
a503e883d9 | ||
|
|
347681c219 | ||
|
|
2984237f4f | ||
|
|
1c4a73de71 | ||
|
|
d27df4d88f | ||
|
|
9562888e77 | ||
|
|
5536b38401 | ||
|
|
c011b271a1 | ||
|
|
c21fb81d3e | ||
|
|
5a3dcf5939 | ||
|
|
1d709fe942 | ||
|
|
e55c16146f | ||
|
|
997a9a3e13 | ||
|
|
008f38579c | ||
|
|
d943e86b28 | ||
|
|
3f2d707a83 | ||
|
|
b145a93ad6 | ||
|
|
3056028db4 | ||
|
|
b4dac14720 | ||
|
|
76694b956f | ||
|
|
9fab5b3e3c | ||
|
|
d54491fdd0 | ||
|
|
00c3c3a546 | ||
|
|
1da5c344be | ||
|
|
76d66b5dad | ||
|
|
e502735eb2 | ||
|
|
edfebe1b99 | ||
|
|
250e4f75da | ||
|
|
53f1bdd9c2 | ||
|
|
ade298d0a7 | ||
|
|
387b01ce14 | ||
|
|
47d2094329 | ||
|
|
43f9a8e1f0 | ||
|
|
30e287371f | ||
|
|
a9246d7b28 | ||
|
|
db1d73f05d | ||
|
|
72b14ea177 | ||
|
|
430c4a3f79 | ||
|
|
93ed92f63b | ||
|
|
4a1312c060 | ||
|
|
303e1ecf34 | ||
|
|
57b0e4a65b | ||
|
|
804a301068 | ||
|
|
aedb8a4d08 | ||
|
|
93072ab51e | ||
|
|
ca11a325bd | ||
|
|
3b088af0b1 | ||
|
|
09e52646e9 | ||
|
|
26ca6f4fcc | ||
|
|
b467d710ac | ||
|
|
f4f11fada8 | ||
|
|
43b3b47426 | ||
|
|
77f8cae06e | ||
|
|
daa31cfd59 | ||
|
|
b4ad4b7293 | ||
|
|
a2947909e8 | ||
|
|
bc2d0521e7 | ||
|
|
95ca42dd06 | ||
|
|
0c0dfca015 | ||
|
|
17cd2e4d07 | ||
|
|
f305547835 | ||
|
|
5ee86104a8 | ||
|
|
0ab247bee9 | ||
|
|
5370edc560 | ||
|
|
f27b6cbd21 | ||
|
|
de3485ed67 | ||
|
|
7f8489bc11 | ||
|
|
8c1cf4cc02 | ||
|
|
b8fbac6365 | ||
|
|
c7cc4ef650 | ||
|
|
9d1789b62f | ||
|
|
9a1c99e1a2 | ||
|
|
abc435f18e | ||
|
|
2e6dab8672 | ||
|
|
e0b95b12da | ||
|
|
722ecd0d97 | ||
|
|
e72cc38641 | ||
|
|
ae227b8743 | ||
|
|
a268e57967 | ||
|
|
9f05dad78c | ||
|
|
ba0112d574 | ||
|
|
5b449bc031 | ||
|
|
b823c130c1 | ||
|
|
437d9da605 | ||
|
|
f49a57006f | ||
|
|
18096194f5 | ||
|
|
8ca0f22841 | ||
|
|
b4e9888d91 | ||
|
|
30b01396b4 | ||
|
|
9343129fbb | ||
|
|
e79ddda9de | ||
|
|
f84c92881d | ||
|
|
aeafa7fef8 | ||
|
|
ff3db332fe | ||
|
|
68d53612af | ||
|
|
0fb9b4abbf | ||
|
|
ab442f72b9 | ||
|
|
b85d16b615 | ||
|
|
cc7d9550bc | ||
|
|
bc2d2edbef | ||
|
|
bc5c6c7563 | ||
|
|
0d971f0c5a | ||
|
|
99d225ae7f | ||
|
|
4bb7951324 | ||
|
|
20c29f74b4 | ||
|
|
d9a4414ef0 | ||
|
|
56be1ceaef | ||
|
|
fd0ddefa03 | ||
|
|
00e3d12e1d | ||
|
|
3a81d02c0f | ||
|
|
5fbb929250 | ||
|
|
4cb28647fe | ||
|
|
002240592a | ||
|
|
8f95d938d5 | ||
|
|
c66294c51a | ||
|
|
abc96cf444 | ||
|
|
a3019dddc1 | ||
|
|
bd03f965a3 | ||
|
|
358d39d4bf | ||
|
|
77571794a3 | ||
|
|
a935ef810c | ||
|
|
eb731d1377 | ||
|
|
c275325fbf | ||
|
|
84da3d4817 | ||
|
|
c868ea1f58 | ||
|
|
d5e385dc73 | ||
|
|
d49758ace1 | ||
|
|
f3ee6e294f | ||
|
|
dea96fe9d3 | ||
|
|
29a5e8df12 | ||
|
|
51941fd085 | ||
|
|
64ea5dd93a | ||
|
|
a42d420ee5 | ||
|
|
060995dfff | ||
|
|
991bd7b460 | ||
|
|
db503078d0 | ||
|
|
8ee58d2591 | ||
|
|
c340a1dcd2 | ||
|
|
774a6aa4dd | ||
|
|
b2566429fc | ||
|
|
f66bcb4f23 | ||
|
|
0e7430735e | ||
|
|
905c7e8785 | ||
|
|
9d91a43142 | ||
|
|
53bac56f36 | ||
|
|
e85fff2f10 | ||
|
|
839236c912 | ||
|
|
1e3fddbe14 | ||
|
|
b5576d1485 | ||
|
|
524b466197 | ||
|
|
7d1b245754 | ||
|
|
64a0846a1c | ||
|
|
118bd414d4 | ||
|
|
3f319c5f29 | ||
|
|
8b06eaa8fc | ||
|
|
e62bd7c533 | ||
|
|
0839a82f80 | ||
|
|
4cbaf927d9 | ||
|
|
b4f364c385 | ||
|
|
6ede629146 | ||
|
|
c684599599 | ||
|
|
c9bfd79ae0 | ||
|
|
6d3f71d200 | ||
|
|
620e391be7 | ||
|
|
532a1355ce | ||
|
|
03367d9c41 | ||
|
|
6ebd205c8e | ||
|
|
7276ea00a7 | ||
|
|
7a5c56bc58 | ||
|
|
9e064c7045 | ||
|
|
6933bfe783 | ||
|
|
5e81fb065a | ||
|
|
f08b4276ea | ||
|
|
45d7dda330 | ||
|
|
a8f1878ff3 | ||
|
|
d0ec80aa86 | ||
|
|
a9257dea7d | ||
|
|
af5d12a154 | ||
|
|
fb4ebd7838 | ||
|
|
7ace23060a | ||
|
|
19504eed91 | ||
|
|
7c72b41e2c | ||
|
|
6fc971d8c0 | ||
|
|
a410f9e553 | ||
|
|
a00f48f894 | ||
|
|
699d64c8f3 | ||
|
|
c6bc9d5a8c | ||
|
|
e96431e1c1 | ||
|
|
773aa9dcc3 | ||
|
|
998086ca31 | ||
|
|
7abbbc6cf4 | ||
|
|
1873f5df88 | ||
|
|
f39980b4c7 | ||
|
|
40ac200988 | ||
|
|
4344b62a3a | ||
|
|
3267ae2ef7 | ||
|
|
1eb24b9f9c | ||
|
|
a9e11bdca7 | ||
|
|
02fb8a4ca3 | ||
|
|
d62f6b37bf | ||
|
|
aaae14d111 | ||
|
|
672c153d73 | ||
|
|
a1a2a6f9ce | ||
|
|
006caf963a | ||
|
|
b314539aa8 | ||
|
|
aac26aa7fa | ||
|
|
aefe484468 | ||
|
|
f9b633adcd | ||
|
|
a5f3d76fda | ||
|
|
2098629f2d | ||
|
|
c67dc90bb8 | ||
|
|
69945a779c | ||
|
|
f8de26bf0c | ||
|
|
603cc43e14 | ||
|
|
4b4d734897 | ||
|
|
cb629d38aa | ||
|
|
07b05ebc21 | ||
|
|
6debbcd228 | ||
|
|
6258c24c8c | ||
|
|
b5a5ea161a | ||
|
|
1462612e3c | ||
|
|
75d0cedb1a | ||
|
|
f660e617a3 | ||
|
|
a454e08683 | ||
|
|
5bbc63d590 | ||
|
|
b514d09a14 | ||
|
|
d828b69cd1 | ||
|
|
067ec2edd4 | ||
|
|
01719ee5c5 | ||
|
|
5e4e7df657 | ||
|
|
0c1671073e | ||
|
|
3a42d26c36 | ||
|
|
fb1a7e64b5 | ||
|
|
fa7638a731 | ||
|
|
d9228b5517 | ||
|
|
b9e6492480 | ||
|
|
28e6fad462 | ||
|
|
c2ae3266c2 | ||
|
|
195251fc12 | ||
|
|
9b52703451 | ||
|
|
84d42d8177 | ||
|
|
5de43abff5 | ||
|
|
8112ed2e6c | ||
|
|
25daa465a4 | ||
|
|
4302ad6302 | ||
|
|
9d1148e322 | ||
|
|
42bb4f8ec8 | ||
|
|
bc4751b2e9 | ||
|
|
046b73ad98 | ||
|
|
f12b423797 | ||
|
|
81767f49a9 | ||
|
|
cb7d1bff90 | ||
|
|
65655a7ac6 | ||
|
|
e61da23175 | ||
|
|
0065d53b4d | ||
|
|
179c73c90c | ||
|
|
1653009fe5 | ||
|
|
753dffd122 | ||
|
|
c05e5e4373 | ||
|
|
93883d5823 | ||
|
|
a22613d3e0 | ||
|
|
073378ec92 | ||
|
|
a00c890a9d | ||
|
|
8f57a215b5 | ||
|
|
12821ae90a | ||
|
|
112abdc25a | ||
|
|
627fdf8fe4 | ||
|
|
0f1faad9a3 | ||
|
|
66dbfca54a | ||
|
|
647a1ab5f0 | ||
|
|
e284ffab6c | ||
|
|
ef1532cab2 | ||
|
|
2ae8833092 | ||
|
|
e7cacf4642 | ||
|
|
6c7850482f | ||
|
|
f93d0fadf2 | ||
|
|
7ec3c640e7 | ||
|
|
97786271f9 | ||
|
|
c90df0c332 | ||
|
|
f5a3099344 | ||
|
|
fe7ca5276f | ||
|
|
b439067975 | ||
|
|
b2f2e54167 | ||
|
|
55285b1c50 | ||
|
|
af96fc79e1 | ||
|
|
1c9c79ef24 | ||
|
|
741604f78d | ||
|
|
5cb08bb658 | ||
|
|
969217dc2f | ||
|
|
fb438829b5 | ||
|
|
d7c1f4a6b4 | ||
|
|
e35267d62c | ||
|
|
1779669120 | ||
|
|
97a4baf4bf | ||
|
|
4aadf14fb0 | ||
|
|
64509fb557 | ||
|
|
91c979623c | ||
|
|
95240de023 | ||
|
|
7f3970cc2d | ||
|
|
fa40bd3d05 | ||
|
|
87ddc5d6bb | ||
|
|
d4fcc2899c | ||
|
|
95279d8e20 | ||
|
|
fc231d8c29 | ||
|
|
f8f288b1c6 | ||
|
|
f6b5a81bcf | ||
|
|
75cc3b1766 | ||
|
|
2f4b425613 | ||
|
|
97d35566cd | ||
|
|
ee673e2a51 | ||
|
|
a66233d638 | ||
|
|
a208d718cf | ||
|
|
9dae73cd9d | ||
|
|
fac94604c4 | ||
|
|
c64aa83a09 | ||
|
|
55db23f665 | ||
|
|
6d7da863a9 | ||
|
|
a559de3cc6 | ||
|
|
f48fc9774d | ||
|
|
0d1a0a4460 | ||
|
|
48310b0921 | ||
|
|
5a6008ba14 | ||
|
|
19832cc0dd | ||
|
|
70cb6fad3b | ||
|
|
1c12932f17 | ||
|
|
b8073ff355 | ||
|
|
ad45885155 | ||
|
|
7a3da8cc91 | ||
|
|
c88f57529b | ||
|
|
e140607d40 | ||
|
|
c7d76b16e1 | ||
|
|
42bd942380 | ||
|
|
b3f7187493 | ||
|
|
1e4d492d18 | ||
|
|
186f1531c7 | ||
|
|
513fc2034b | ||
|
|
b126de3dcd | ||
|
|
6aad65b27a | ||
|
|
7ac730f424 | ||
|
|
1c6748286c | ||
|
|
a3fea2c220 | ||
|
|
99691ee61a | ||
|
|
44e1b7c01b | ||
|
|
db4b354d9b | ||
|
|
105d703629 | ||
|
|
6ce83ee1f0 | ||
|
|
d4c1ffda76 | ||
|
|
0ec21adf21 | ||
|
|
7533c4ede0 | ||
|
|
0dc7782727 | ||
|
|
a17b54921c | ||
|
|
7dddd4282b | ||
|
|
4a4ddda621 | ||
|
|
74398ca61c | ||
|
|
02abee0980 | ||
|
|
e518f846b3 | ||
|
|
0ec89257db | ||
|
|
e2ddc59a8e | ||
|
|
0552fa9353 | ||
|
|
d7ae6c9f06 | ||
|
|
0c1afdf111 | ||
|
|
ccedf2d3cf | ||
|
|
ce7e4b4369 | ||
|
|
59ed319449 | ||
|
|
37a95044bc | ||
|
|
0e3a84fc2d | ||
|
|
45efa06dc8 | ||
|
|
af2315d588 | ||
|
|
c3c0d6f8c3 | ||
|
|
1100ea5eba | ||
|
|
eda712503e | ||
|
|
b4743e3a3a | ||
|
|
da8387e80a | ||
|
|
905b050aa1 | ||
|
|
349be237d7 | ||
|
|
b4fbbdc29a | ||
|
|
87bbdc0acd | ||
|
|
670b251652 | ||
|
|
49f4dad4fa | ||
|
|
da7dff0437 | ||
|
|
2c321e2baf | ||
|
|
8b9323b330 | ||
|
|
94959894ba | ||
|
|
3e88d97cbd | ||
|
|
75a1d79076 | ||
|
|
fe301ae7ff | ||
|
|
4c53908cd2 | ||
|
|
b19387b292 | ||
|
|
206afa0642 | ||
|
|
32be60a48f | ||
|
|
fd232c1468 | ||
|
|
bd475e1a66 | ||
|
|
2ae979cdc7 | ||
|
|
98abdcc2b3 | ||
|
|
155d5c2962 | ||
|
|
e944757741 | ||
|
|
ccb6e13fd4 | ||
|
|
d709575043 | ||
|
|
36a1957d0a | ||
|
|
723866726d | ||
|
|
4f9775b779 | ||
|
|
70a52e4c04 | ||
|
|
a1cf966815 | ||
|
|
6c08355e6a | ||
|
|
83a017f13d | ||
|
|
91a33538ab | ||
|
|
c82a4f147c | ||
|
|
fa27001ab2 | ||
|
|
ef7c0d6b46 | ||
|
|
63572780f1 | ||
|
|
dd0042fc70 | ||
|
|
1ff84675f8 | ||
|
|
de0eb45320 | ||
|
|
b2ddd84ac6 | ||
|
|
9e52953e54 | ||
|
|
a56f978f70 | ||
|
|
51e1650d42 | ||
|
|
f48c770701 | ||
|
|
1a415bb8ca | ||
|
|
3325b35f89 | ||
|
|
0621acfb57 | ||
|
|
73a1e5aec0 | ||
|
|
ad4823f53b | ||
|
|
a3918b822b | ||
|
|
9ae5534d5b | ||
|
|
76c9a8a09f | ||
|
|
5fccc6ec3d | ||
|
|
6e9501b7ae | ||
|
|
8ea6155ea1 | ||
|
|
1befbb4fbb | ||
|
|
1ff0a21ee9 | ||
|
|
39fd993c54 | ||
|
|
38686dbb00 | ||
|
|
f0ba16f55f | ||
|
|
aa564908c4 | ||
|
|
e33e98ff32 | ||
|
|
f5cd8b5417 | ||
|
|
ac9ed616b9 | ||
|
|
b156c32def | ||
|
|
dad41636ad | ||
|
|
2ba24302d9 | ||
|
|
618f62e753 | ||
|
|
a48b046c36 | ||
|
|
6298bfeb3d | ||
|
|
06a857bdb3 | ||
|
|
9b03c84201 | ||
|
|
073e3adb0c | ||
|
|
d8060a0296 | ||
|
|
3b29cd7f19 | ||
|
|
7c8591f911 | ||
|
|
caaa037d42 | ||
|
|
72f1715ba5 | ||
|
|
d866c8d5c7 | ||
|
|
02267e9a4a | ||
|
|
55254b80fd | ||
|
|
c4a6eba91d | ||
|
|
2b3ad2f082 | ||
|
|
ee06d385a2 | ||
|
|
04775c4123 | ||
|
|
3a6d7f624f | ||
|
|
e5146624ea | ||
|
|
038c5a95fc | ||
|
|
e82fa3450a | ||
|
|
5ef79e303f | ||
|
|
b1c19137ad | ||
|
|
047458a002 | ||
|
|
ebb0ae456c | ||
|
|
5fda071898 | ||
|
|
c3e12fe822 | ||
|
|
be7a231579 | ||
|
|
bc45ec4f57 | ||
|
|
202e354f87 | ||
|
|
211aa6d652 | ||
|
|
a91b385f68 | ||
|
|
253ec6706a | ||
|
|
8b579a0151 | ||
|
|
405182e8c6 | ||
|
|
d59ffe50bf | ||
|
|
7cd5d4c623 | ||
|
|
6f2ee41663 | ||
|
|
3654fa5444 | ||
|
|
1e7ca24d65 | ||
|
|
6b9556259e | ||
|
|
b8a6819b91 | ||
|
|
d4db7bf21b | ||
|
|
5c6e1a3416 | ||
|
|
485de4985c | ||
|
|
aab2c3f490 | ||
|
|
8605014f0d |
No files matched your search
@@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for NSS update
|
||||
Clobber for libvpx changes
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "Platform.h"
|
||||
|
||||
#include "nsIAccessibleEvent.h"
|
||||
#include "nsIGConfService.h"
|
||||
#include "nsIGSettingsService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsMai.h"
|
||||
#include "AtkSocketAccessible.h"
|
||||
@@ -360,13 +360,22 @@ dbus_done:
|
||||
return sShouldEnable;
|
||||
#endif
|
||||
|
||||
//check gconf-2 setting
|
||||
#define GCONF_A11Y_KEY "/desktop/gnome/interface/accessibility"
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIGConfService> gconf =
|
||||
do_GetService(NS_GCONFSERVICE_CONTRACTID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && gconf)
|
||||
gconf->GetBool(NS_LITERAL_CSTRING(GCONF_A11Y_KEY), &sShouldEnable);
|
||||
// check GSettings
|
||||
#define GSETINGS_A11Y_INTERFACE "org.gnome.desktop.interface"
|
||||
#define GSETINGS_A11Y_KEY "toolkit-accessibility"
|
||||
nsCOMPtr<nsIGSettingsService> gsettings =
|
||||
do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
|
||||
nsCOMPtr<nsIGSettingsCollection> a11y_settings;
|
||||
|
||||
if (gsettings) {
|
||||
gsettings->GetCollectionForSchema(NS_LITERAL_CSTRING(GSETINGS_A11Y_INTERFACE),
|
||||
getter_AddRefs(a11y_settings));
|
||||
|
||||
if (a11y_settings) {
|
||||
a11y_settings->GetBoolean(NS_LITERAL_CSTRING(GSETINGS_A11Y_KEY),
|
||||
&sShouldEnable);
|
||||
}
|
||||
}
|
||||
|
||||
return sShouldEnable;
|
||||
}
|
||||
Vendored
+3
@@ -982,6 +982,9 @@ EOF
|
||||
k1om:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
loongarch64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
m32r*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
|
||||
@@ -375,6 +375,9 @@ def split_triplet(triplet):
|
||||
elif cpu.startswith('aarch64'):
|
||||
canonical_cpu = 'aarch64'
|
||||
endianness = 'little'
|
||||
elif cpu.startswith('loongarch64'):
|
||||
canonical_cpu = 'loongarch64'
|
||||
endianness = 'little'
|
||||
else:
|
||||
die('Unknown CPU type: %s' % cpu)
|
||||
|
||||
|
||||
@@ -11,9 +11,14 @@ def moz_jemalloc4(value):
|
||||
|
||||
option('--enable-jemalloc', env='MOZ_MEMORY',
|
||||
help='Replace system memory allocator with jemalloc')
|
||||
option('--enable-mimalloc',
|
||||
help='Replace system memory allocator with mimalloc')
|
||||
|
||||
@depends('--enable-jemalloc', target, build_project, c_compiler)
|
||||
def jemalloc(value, target, build_project, c_compiler):
|
||||
@depends('--enable-jemalloc', '--enable-mimalloc', target, build_project,
|
||||
c_compiler)
|
||||
def jemalloc(value, mimalloc, target, build_project, c_compiler):
|
||||
if value and mimalloc:
|
||||
die('--enable-jemalloc and --enable-mimalloc cannot be used together')
|
||||
if value.origin != 'default':
|
||||
return bool(value) or None
|
||||
|
||||
@@ -30,11 +35,38 @@ def jemalloc(value, target, build_project, c_compiler):
|
||||
if target.kernel == 'Linux':
|
||||
return True
|
||||
|
||||
@depends('--enable-mimalloc', '--enable-jemalloc', target)
|
||||
def mimalloc(value, jemalloc, target):
|
||||
if value and jemalloc:
|
||||
die('--enable-jemalloc and --enable-mimalloc cannot be used together')
|
||||
if value.origin != 'default':
|
||||
if not value:
|
||||
return None
|
||||
if target.kernel not in ('Darwin', 'WINNT', 'Linux', 'kFreeBSD', 'FreeBSD',
|
||||
'NetBSD', 'OpenBSD', 'DragonFly'):
|
||||
die('--enable-mimalloc is not supported on %s', target.kernel)
|
||||
return True
|
||||
|
||||
@depends('--enable-mimalloc', '--enable-jemalloc')
|
||||
def mimalloc_requires_disable(mimalloc, jemalloc):
|
||||
if not mimalloc:
|
||||
return
|
||||
if jemalloc or jemalloc.origin not in ('command-line', 'mozconfig'):
|
||||
die('--enable-mimalloc requires --disable-jemalloc to be passed explicitly')
|
||||
|
||||
|
||||
set_config('MOZ_MEMORY', jemalloc)
|
||||
set_define('MOZ_MEMORY', jemalloc)
|
||||
add_old_configure_assignment('MOZ_MEMORY', jemalloc)
|
||||
|
||||
@depends(mimalloc)
|
||||
def mimalloc_config(mimalloc):
|
||||
return True if mimalloc else False
|
||||
|
||||
set_config('MOZ_MIMALLOC', mimalloc_config)
|
||||
set_define('MOZ_MIMALLOC', mimalloc)
|
||||
add_old_configure_assignment('MOZ_MIMALLOC', mimalloc_config)
|
||||
|
||||
|
||||
# Because --enable-jemalloc doesn't use a default because of the dependency
|
||||
# on the target, we can't use a js_option for it to propagate to js/src
|
||||
|
||||
@@ -127,7 +127,6 @@ def old_configure_options(*options):
|
||||
'--enable-alsa',
|
||||
'--enable-appcompat-guid',
|
||||
'--enable-av1',
|
||||
'--enable-jxl',
|
||||
'--enable-b2g-bt',
|
||||
'--enable-b2g-camera',
|
||||
'--enable-b2g-ril',
|
||||
@@ -153,10 +152,7 @@ def old_configure_options(*options):
|
||||
'--enable-faststripe',
|
||||
'--enable-feeds',
|
||||
'--enable-gamepad',
|
||||
'--enable-gconf',
|
||||
'--enable-gczeal',
|
||||
'--enable-gio',
|
||||
'--enable-gnomeui',
|
||||
'--enable-gold',
|
||||
'--enable-hardware-aec-ns',
|
||||
'--enable-icf',
|
||||
|
||||
@@ -464,6 +464,18 @@ nsPrincipal::Write(nsIObjectOutputStream* aStream)
|
||||
rv = aStream->WriteStringZ(suffix.get());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This is an ugly hack to prevent re-entrancy calls into nsPrincipal::Write()
|
||||
// because of repeat CSP processing.
|
||||
// We refcount the context and if found 3+ refcounts on the same, skip writing
|
||||
// the mCSP compound object.
|
||||
// TODO: figure out exactly why this happens and fix the root cause.
|
||||
nsCSPContext* CSPContext = static_cast<nsCSPContext*>(mCSP.get());
|
||||
if(CSPContext) {
|
||||
auto CSPDepth = CSPContext->AddRef();
|
||||
CSPContext->Release();
|
||||
if(CSPDepth > 2) return NS_OK;
|
||||
}
|
||||
|
||||
rv = NS_WriteOptionalCompoundObject(aStream, mCSP,
|
||||
NS_GET_IID(nsIContentSecurityPolicy),
|
||||
true);
|
||||
|
||||
+20
-1
@@ -18,20 +18,30 @@ sources = [
|
||||
'/intl/icu/source/common/dictionarydata.cpp',
|
||||
'/intl/icu/source/common/dtintrv.cpp',
|
||||
'/intl/icu/source/common/edits.cpp',
|
||||
'/intl/icu/source/common/emojiprops.cpp',
|
||||
'/intl/icu/source/common/errorcode.cpp',
|
||||
'/intl/icu/source/common/filteredbrk.cpp',
|
||||
'/intl/icu/source/common/filterednormalizer2.cpp',
|
||||
'/intl/icu/source/common/fixedstring.cpp',
|
||||
'/intl/icu/source/common/loadednormalizer2impl.cpp',
|
||||
'/intl/icu/source/common/localebuilder.cpp',
|
||||
'/intl/icu/source/common/localematcher.cpp',
|
||||
'/intl/icu/source/common/localeprioritylist.cpp',
|
||||
'/intl/icu/source/common/locavailable.cpp',
|
||||
'/intl/icu/source/common/locbased.cpp',
|
||||
'/intl/icu/source/common/locdispnames.cpp',
|
||||
'/intl/icu/source/common/locdistance.cpp',
|
||||
'/intl/icu/source/common/locdspnm.cpp',
|
||||
'/intl/icu/source/common/locid.cpp',
|
||||
'/intl/icu/source/common/loclikely.cpp',
|
||||
'/intl/icu/source/common/loclikelysubtags.cpp',
|
||||
'/intl/icu/source/common/locmap.cpp',
|
||||
'/intl/icu/source/common/locresdata.cpp',
|
||||
'/intl/icu/source/common/locutil.cpp',
|
||||
'/intl/icu/source/common/lsr.cpp',
|
||||
'/intl/icu/source/common/lstmbe.cpp',
|
||||
'/intl/icu/source/common/messagepattern.cpp',
|
||||
'/intl/icu/source/common/mlbe.cpp',
|
||||
'/intl/icu/source/common/normalizer2.cpp',
|
||||
'/intl/icu/source/common/normalizer2impl.cpp',
|
||||
'/intl/icu/source/common/normlzr.cpp',
|
||||
@@ -51,6 +61,7 @@ sources = [
|
||||
'/intl/icu/source/common/rbbitblb.cpp',
|
||||
'/intl/icu/source/common/resbund.cpp',
|
||||
'/intl/icu/source/common/resource.cpp',
|
||||
'/intl/icu/source/common/restrace.cpp',
|
||||
'/intl/icu/source/common/ruleiter.cpp',
|
||||
'/intl/icu/source/common/schriter.cpp',
|
||||
'/intl/icu/source/common/serv.cpp',
|
||||
@@ -110,6 +121,8 @@ sources = [
|
||||
'/intl/icu/source/common/uloc.cpp',
|
||||
'/intl/icu/source/common/uloc_keytype.cpp',
|
||||
'/intl/icu/source/common/uloc_tag.cpp',
|
||||
'/intl/icu/source/common/ulocale.cpp',
|
||||
'/intl/icu/source/common/ulocbuilder.cpp',
|
||||
'/intl/icu/source/common/umapfile.cpp',
|
||||
'/intl/icu/source/common/umath.cpp',
|
||||
'/intl/icu/source/common/umutablecptrie.cpp',
|
||||
@@ -151,6 +164,7 @@ sources = [
|
||||
'/intl/icu/source/common/utext.cpp',
|
||||
'/intl/icu/source/common/utf_impl.cpp',
|
||||
'/intl/icu/source/common/util.cpp',
|
||||
'/intl/icu/source/common/util_props.cpp',
|
||||
'/intl/icu/source/common/utrace.cpp',
|
||||
'/intl/icu/source/common/utrie.cpp',
|
||||
'/intl/icu/source/common/utrie2.cpp',
|
||||
@@ -190,7 +204,6 @@ other_sources = [
|
||||
'/intl/icu/source/common/usc_impl.cpp',
|
||||
'/intl/icu/source/common/ushape.cpp',
|
||||
'/intl/icu/source/common/ustr_wcs.cpp',
|
||||
'/intl/icu/source/common/util_props.cpp',
|
||||
]
|
||||
EXPORTS.unicode += [
|
||||
'/intl/icu/source/common/unicode/appendable.h',
|
||||
@@ -212,6 +225,8 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/common/unicode/icudataver.h',
|
||||
'/intl/icu/source/common/unicode/icuplug.h',
|
||||
'/intl/icu/source/common/unicode/idna.h',
|
||||
'/intl/icu/source/common/unicode/localebuilder.h',
|
||||
'/intl/icu/source/common/unicode/localematcher.h',
|
||||
'/intl/icu/source/common/unicode/localpointer.h',
|
||||
'/intl/icu/source/common/unicode/locdspnm.h',
|
||||
'/intl/icu/source/common/unicode/locid.h',
|
||||
@@ -259,6 +274,8 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/common/unicode/uiter.h',
|
||||
'/intl/icu/source/common/unicode/uldnames.h',
|
||||
'/intl/icu/source/common/unicode/uloc.h',
|
||||
'/intl/icu/source/common/unicode/ulocale.h',
|
||||
'/intl/icu/source/common/unicode/ulocbuilder.h',
|
||||
'/intl/icu/source/common/unicode/umachine.h',
|
||||
'/intl/icu/source/common/unicode/umisc.h',
|
||||
'/intl/icu/source/common/unicode/umutablecptrie.h',
|
||||
@@ -286,6 +303,8 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/common/unicode/utf32.h',
|
||||
'/intl/icu/source/common/unicode/utf8.h',
|
||||
'/intl/icu/source/common/unicode/utf_old.h',
|
||||
'/intl/icu/source/common/unicode/utfiterator.h',
|
||||
'/intl/icu/source/common/unicode/utfstring.h',
|
||||
'/intl/icu/source/common/unicode/utrace.h',
|
||||
'/intl/icu/source/common/unicode/utypes.h',
|
||||
'/intl/icu/source/common/unicode/uvernum.h',
|
||||
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
Vendored
+22
@@ -3,12 +3,15 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
# Also see <http://www.icu-project.org/repos/icu/tags/latest/icu4c/readme.html#RecBuild> for the
|
||||
# recommended build options when compiling ICU.
|
||||
DEFINES.update(
|
||||
# Don't use icu namespace automatically in client code.
|
||||
U_USING_ICU_NAMESPACE = 0,
|
||||
|
||||
# Don't include obsolete header files.
|
||||
U_NO_DEFAULT_INCLUDE_UTF_HEADERS = 1,
|
||||
U_HIDE_OBSOLETE_UTF_OLD_H = 1,
|
||||
|
||||
# Remove chunks of the library that we don't need (yet).
|
||||
UCONFIG_NO_LEGACY_CONVERSION = True,
|
||||
@@ -17,6 +20,13 @@ DEFINES.update(
|
||||
|
||||
# We don't need to pass data to and from legacy char* APIs.
|
||||
U_CHARSET_IS_UTF8 = True,
|
||||
|
||||
# Add 'explicit' keyword to UnicodeString constructors.
|
||||
UNISTR_FROM_CHAR_EXPLICIT = 'explicit',
|
||||
UNISTR_FROM_STRING_EXPLICIT = 'explicit',
|
||||
|
||||
# Disable dynamic loading of ICU data as a loadable library.
|
||||
U_ENABLE_DYLOAD = 0,
|
||||
)
|
||||
|
||||
if not CONFIG['HAVE_LANGINFO_CODESET']:
|
||||
@@ -38,12 +48,24 @@ ALLOW_COMPILER_WARNINGS = True
|
||||
# warnings that get triggered for every file.
|
||||
if CONFIG['CLANG_CL']:
|
||||
CFLAGS += [
|
||||
'-Wno-c++20-compat',
|
||||
'-Wno-comma',
|
||||
'-Wno-implicit-const-int-float-conversion',
|
||||
'-Wno-macro-redefined',
|
||||
'-Wno-microsoft-include',
|
||||
'-Wno-tautological-unsigned-enum-zero-compare',
|
||||
'-Wno-unreachable-code-loop-increment',
|
||||
'-Wno-unreachable-code-return',
|
||||
]
|
||||
CXXFLAGS += [
|
||||
'-Wno-c++20-compat',
|
||||
'-Wno-comma',
|
||||
'-Wno-implicit-const-int-float-conversion',
|
||||
'-Wno-macro-redefined',
|
||||
'-Wno-microsoft-include',
|
||||
'-Wno-tautological-unsigned-enum-zero-compare',
|
||||
'-Wno-unreachable-code-loop-increment',
|
||||
'-Wno-unreachable-code-return',
|
||||
]
|
||||
|
||||
if CONFIG['_MSC_VER'] and not CONFIG['CLANG_CL']:
|
||||
|
||||
+47
-5
@@ -42,13 +42,14 @@ sources = [
|
||||
'/intl/icu/source/i18n/decContext.cpp',
|
||||
'/intl/icu/source/i18n/decimfmt.cpp',
|
||||
'/intl/icu/source/i18n/decNumber.cpp',
|
||||
'/intl/icu/source/i18n/displayoptions.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-bignum-dtoa.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-bignum.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-cached-powers.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-diy-fp.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-double-to-string.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-fast-dtoa.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-string-to-double.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion-strtod.cpp',
|
||||
'/intl/icu/source/i18n/double-conversion.cpp',
|
||||
'/intl/icu/source/i18n/dtfmtsym.cpp',
|
||||
'/intl/icu/source/i18n/dtitvfmt.cpp',
|
||||
'/intl/icu/source/i18n/dtitvinf.cpp',
|
||||
@@ -58,6 +59,10 @@ sources = [
|
||||
'/intl/icu/source/i18n/ethpccal.cpp',
|
||||
'/intl/icu/source/i18n/fmtable.cpp',
|
||||
'/intl/icu/source/i18n/format.cpp',
|
||||
'/intl/icu/source/i18n/formatted_string_builder.cpp',
|
||||
'/intl/icu/source/i18n/formattedval_iterimpl.cpp',
|
||||
'/intl/icu/source/i18n/formattedval_sbimpl.cpp',
|
||||
'/intl/icu/source/i18n/formattedvalue.cpp',
|
||||
'/intl/icu/source/i18n/fphdlimp.cpp',
|
||||
'/intl/icu/source/i18n/fpositer.cpp',
|
||||
'/intl/icu/source/i18n/gregocal.cpp',
|
||||
@@ -65,16 +70,28 @@ sources = [
|
||||
'/intl/icu/source/i18n/hebrwcal.cpp',
|
||||
'/intl/icu/source/i18n/indiancal.cpp',
|
||||
'/intl/icu/source/i18n/islamcal.cpp',
|
||||
'/intl/icu/source/i18n/iso8601cal.cpp',
|
||||
'/intl/icu/source/i18n/japancal.cpp',
|
||||
'/intl/icu/source/i18n/listformatter.cpp',
|
||||
'/intl/icu/source/i18n/measfmt.cpp',
|
||||
'/intl/icu/source/i18n/measunit.cpp',
|
||||
'/intl/icu/source/i18n/measunit_extra.cpp',
|
||||
'/intl/icu/source/i18n/measure.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_arguments.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_checker.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_data_model.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_errors.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_evaluation.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_formattable.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_formatter.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_function_registry.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_parser.cpp',
|
||||
'/intl/icu/source/i18n/messageformat2_serializer.cpp',
|
||||
'/intl/icu/source/i18n/msgfmt.cpp',
|
||||
'/intl/icu/source/i18n/nfrs.cpp',
|
||||
'/intl/icu/source/i18n/nfrule.cpp',
|
||||
'/intl/icu/source/i18n/nfsubs.cpp',
|
||||
'/intl/icu/source/i18n/nounit.cpp',
|
||||
'/intl/icu/source/i18n/number_affixutils.cpp',
|
||||
'/intl/icu/source/i18n/number_asformat.cpp',
|
||||
'/intl/icu/source/i18n/number_capi.cpp',
|
||||
@@ -91,13 +108,16 @@ sources = [
|
||||
'/intl/icu/source/i18n/number_modifiers.cpp',
|
||||
'/intl/icu/source/i18n/number_multiplier.cpp',
|
||||
'/intl/icu/source/i18n/number_notation.cpp',
|
||||
'/intl/icu/source/i18n/number_output.cpp',
|
||||
'/intl/icu/source/i18n/number_padding.cpp',
|
||||
'/intl/icu/source/i18n/number_patternmodifier.cpp',
|
||||
'/intl/icu/source/i18n/number_patternstring.cpp',
|
||||
'/intl/icu/source/i18n/number_rounding.cpp',
|
||||
'/intl/icu/source/i18n/number_scientific.cpp',
|
||||
'/intl/icu/source/i18n/number_simple.cpp',
|
||||
'/intl/icu/source/i18n/number_skeletons.cpp',
|
||||
'/intl/icu/source/i18n/number_stringbuilder.cpp',
|
||||
'/intl/icu/source/i18n/number_symbolswrapper.cpp',
|
||||
'/intl/icu/source/i18n/number_usageprefs.cpp',
|
||||
'/intl/icu/source/i18n/number_utils.cpp',
|
||||
'/intl/icu/source/i18n/numfmt.cpp',
|
||||
'/intl/icu/source/i18n/numparse_affixes.cpp',
|
||||
@@ -107,14 +127,15 @@ sources = [
|
||||
'/intl/icu/source/i18n/numparse_impl.cpp',
|
||||
'/intl/icu/source/i18n/numparse_parsednumber.cpp',
|
||||
'/intl/icu/source/i18n/numparse_scientific.cpp',
|
||||
'/intl/icu/source/i18n/numparse_stringsegment.cpp',
|
||||
'/intl/icu/source/i18n/numparse_symbols.cpp',
|
||||
'/intl/icu/source/i18n/numparse_validators.cpp',
|
||||
'/intl/icu/source/i18n/numrange_capi.cpp',
|
||||
'/intl/icu/source/i18n/numrange_fluent.cpp',
|
||||
'/intl/icu/source/i18n/numrange_impl.cpp',
|
||||
'/intl/icu/source/i18n/numsys.cpp',
|
||||
'/intl/icu/source/i18n/olsontz.cpp',
|
||||
'/intl/icu/source/i18n/persncal.cpp',
|
||||
'/intl/icu/source/i18n/pluralranges.cpp',
|
||||
'/intl/icu/source/i18n/plurfmt.cpp',
|
||||
'/intl/icu/source/i18n/plurrule.cpp',
|
||||
'/intl/icu/source/i18n/quantityformatter.cpp',
|
||||
@@ -133,6 +154,7 @@ sources = [
|
||||
'/intl/icu/source/i18n/smpdtfst.cpp',
|
||||
'/intl/icu/source/i18n/sortkey.cpp',
|
||||
'/intl/icu/source/i18n/standardplural.cpp',
|
||||
'/intl/icu/source/i18n/string_segment.cpp',
|
||||
'/intl/icu/source/i18n/stsearch.cpp',
|
||||
'/intl/icu/source/i18n/taiwncal.cpp',
|
||||
'/intl/icu/source/i18n/timezone.cpp',
|
||||
@@ -157,6 +179,10 @@ sources = [
|
||||
'/intl/icu/source/i18n/uitercollationiterator.cpp',
|
||||
'/intl/icu/source/i18n/ulistformatter.cpp',
|
||||
'/intl/icu/source/i18n/umsg.cpp',
|
||||
'/intl/icu/source/i18n/units_complexconverter.cpp',
|
||||
'/intl/icu/source/i18n/units_converter.cpp',
|
||||
'/intl/icu/source/i18n/units_data.cpp',
|
||||
'/intl/icu/source/i18n/units_router.cpp',
|
||||
'/intl/icu/source/i18n/unum.cpp',
|
||||
'/intl/icu/source/i18n/unumsys.cpp',
|
||||
'/intl/icu/source/i18n/upluralrules.cpp',
|
||||
@@ -245,6 +271,7 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/i18n/unicode/datefmt.h',
|
||||
'/intl/icu/source/i18n/unicode/dcfmtsym.h',
|
||||
'/intl/icu/source/i18n/unicode/decimfmt.h',
|
||||
'/intl/icu/source/i18n/unicode/displayoptions.h',
|
||||
'/intl/icu/source/i18n/unicode/dtfmtsym.h',
|
||||
'/intl/icu/source/i18n/unicode/dtitvfmt.h',
|
||||
'/intl/icu/source/i18n/unicode/dtitvinf.h',
|
||||
@@ -253,6 +280,8 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/i18n/unicode/fieldpos.h',
|
||||
'/intl/icu/source/i18n/unicode/fmtable.h',
|
||||
'/intl/icu/source/i18n/unicode/format.h',
|
||||
'/intl/icu/source/i18n/unicode/formattednumber.h',
|
||||
'/intl/icu/source/i18n/unicode/formattedvalue.h',
|
||||
'/intl/icu/source/i18n/unicode/fpositer.h',
|
||||
'/intl/icu/source/i18n/unicode/gender.h',
|
||||
'/intl/icu/source/i18n/unicode/gregocal.h',
|
||||
@@ -260,6 +289,12 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/i18n/unicode/measfmt.h',
|
||||
'/intl/icu/source/i18n/unicode/measunit.h',
|
||||
'/intl/icu/source/i18n/unicode/measure.h',
|
||||
'/intl/icu/source/i18n/unicode/messageformat2.h',
|
||||
'/intl/icu/source/i18n/unicode/messageformat2_arguments.h',
|
||||
'/intl/icu/source/i18n/unicode/messageformat2_data_model.h',
|
||||
'/intl/icu/source/i18n/unicode/messageformat2_data_model_names.h',
|
||||
'/intl/icu/source/i18n/unicode/messageformat2_formattable.h',
|
||||
'/intl/icu/source/i18n/unicode/messageformat2_function_registry.h',
|
||||
'/intl/icu/source/i18n/unicode/msgfmt.h',
|
||||
'/intl/icu/source/i18n/unicode/nounit.h',
|
||||
'/intl/icu/source/i18n/unicode/numberformatter.h',
|
||||
@@ -276,6 +311,7 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/i18n/unicode/scientificnumberformatter.h',
|
||||
'/intl/icu/source/i18n/unicode/search.h',
|
||||
'/intl/icu/source/i18n/unicode/selfmt.h',
|
||||
'/intl/icu/source/i18n/unicode/simplenumberformatter.h',
|
||||
'/intl/icu/source/i18n/unicode/simpletz.h',
|
||||
'/intl/icu/source/i18n/unicode/smpdtfmt.h',
|
||||
'/intl/icu/source/i18n/unicode/sortkey.h',
|
||||
@@ -297,8 +333,11 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/i18n/unicode/udat.h',
|
||||
'/intl/icu/source/i18n/unicode/udateintervalformat.h',
|
||||
'/intl/icu/source/i18n/unicode/udatpg.h',
|
||||
'/intl/icu/source/i18n/unicode/udisplayoptions.h',
|
||||
'/intl/icu/source/i18n/unicode/ufieldpositer.h',
|
||||
'/intl/icu/source/i18n/unicode/uformattable.h',
|
||||
'/intl/icu/source/i18n/unicode/uformattednumber.h',
|
||||
'/intl/icu/source/i18n/unicode/uformattedvalue.h',
|
||||
'/intl/icu/source/i18n/unicode/ugender.h',
|
||||
'/intl/icu/source/i18n/unicode/ulistformatter.h',
|
||||
'/intl/icu/source/i18n/unicode/ulocdata.h',
|
||||
@@ -306,12 +345,15 @@ EXPORTS.unicode += [
|
||||
'/intl/icu/source/i18n/unicode/unirepl.h',
|
||||
'/intl/icu/source/i18n/unicode/unum.h',
|
||||
'/intl/icu/source/i18n/unicode/unumberformatter.h',
|
||||
'/intl/icu/source/i18n/unicode/unumberoptions.h',
|
||||
'/intl/icu/source/i18n/unicode/unumberrangeformatter.h',
|
||||
'/intl/icu/source/i18n/unicode/unumsys.h',
|
||||
'/intl/icu/source/i18n/unicode/upluralrules.h',
|
||||
'/intl/icu/source/i18n/unicode/uregex.h',
|
||||
'/intl/icu/source/i18n/unicode/uregion.h',
|
||||
'/intl/icu/source/i18n/unicode/ureldatefmt.h',
|
||||
'/intl/icu/source/i18n/unicode/usearch.h',
|
||||
'/intl/icu/source/i18n/unicode/usimplenumberformatter.h',
|
||||
'/intl/icu/source/i18n/unicode/uspoof.h',
|
||||
'/intl/icu/source/i18n/unicode/utmscale.h',
|
||||
'/intl/icu/source/i18n/unicode/utrans.h',
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
# Referenced by milestone.py.
|
||||
#--------------------------------------------------------
|
||||
|
||||
6.8.0
|
||||
6.8.1
|
||||
@@ -348,11 +348,7 @@ ifdef SHARED_LIBRARY
|
||||
ifdef IS_COMPONENT
|
||||
EXTRA_DSO_LDOPTS += -bundle
|
||||
else
|
||||
ifdef MOZ_IOS
|
||||
_LOADER_PATH := @rpath
|
||||
else
|
||||
_LOADER_PATH := @executable_path
|
||||
endif
|
||||
EXTRA_DSO_LDOPTS += -dynamiclib -install_name $(_LOADER_PATH)/$(SHARED_LIBRARY) -compatibility_version 1 -current_version 1 -single_module
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -424,7 +424,6 @@ fstream
|
||||
fstream.h
|
||||
ft2build.h
|
||||
fts.h
|
||||
gconf/gconf-client.h
|
||||
Gdiplus.h
|
||||
gdk/gdk.h
|
||||
gdk/gdkkeysyms.h
|
||||
@@ -1050,9 +1049,7 @@ hunspell.hxx
|
||||
#if MOZ_SYSTEM_BZ2==1
|
||||
bzlib.h
|
||||
#endif
|
||||
#ifdef MOZ_ENABLE_GIO
|
||||
gio/gio.h
|
||||
#endif
|
||||
sys/event.h
|
||||
#ifdef MOZ_ENABLE_LIBPROXY
|
||||
proxy.h
|
||||
|
||||
@@ -37,8 +37,6 @@ const {AutocompletePopup} = require("devtools/client/shared/autocomplete-popup")
|
||||
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
const PREF_UA_STYLES = "devtools.inspector.showUserAgentStyles";
|
||||
const PREF_DEFAULT_COLOR_UNIT = "devtools.defaultColorUnit";
|
||||
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
|
||||
"devtools.inspector.mdnDocsTooltip.enabled";
|
||||
const FILTER_CHANGED_TIMEOUT = 150;
|
||||
|
||||
// This is used to parse user input when filtering.
|
||||
@@ -157,11 +155,8 @@ function CssRuleView(inspector, document, store, pageStyle) {
|
||||
this._prefObserver.on(PREF_ORIG_SOURCES, this._onSourcePrefChanged);
|
||||
this._prefObserver.on(PREF_UA_STYLES, this._handlePrefChange);
|
||||
this._prefObserver.on(PREF_DEFAULT_COLOR_UNIT, this._handlePrefChange);
|
||||
this._prefObserver.on(PREF_ENABLE_MDN_DOCS_TOOLTIP, this._handlePrefChange);
|
||||
|
||||
this.showUserAgentStyles = Services.prefs.getBoolPref(PREF_UA_STYLES);
|
||||
this.enableMdnDocsTooltip =
|
||||
Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
|
||||
|
||||
// The popup will be attached to the toolbox document.
|
||||
this.popup = new AutocompletePopup(inspector._toolbox.doc, {
|
||||
|
||||
@@ -85,9 +85,6 @@ support-files =
|
||||
[browser_rules_content_01.js]
|
||||
[browser_rules_content_02.js]
|
||||
skip-if = e10s && debug # Bug 1250058 - Docshell leak on debug e10s
|
||||
[browser_rules_context-menu-show-mdn-docs-01.js]
|
||||
[browser_rules_context-menu-show-mdn-docs-02.js]
|
||||
[browser_rules_context-menu-show-mdn-docs-03.js]
|
||||
[browser_rules_copy_styles.js]
|
||||
subsuite = clipboard
|
||||
[browser_rules_cssom.js]
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This file tests the code that integrates the Style Inspector's rule view
|
||||
* with the MDN docs tooltip.
|
||||
*
|
||||
* If you display the context click on a property name in the rule view, you
|
||||
* should see a menu item "Show MDN Docs". If you click that item, the MDN
|
||||
* docs tooltip should be shown, containing docs from MDN for that property.
|
||||
*
|
||||
* This file tests that the context menu item is shown when it should be
|
||||
* shown and hidden when it should be hidden.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The test document tries to confuse the context menu
|
||||
* code by having a tag called "padding" and a property
|
||||
* value called "margin".
|
||||
*/
|
||||
|
||||
const { PrefObserver } = require("devtools/client/shared/prefs");
|
||||
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
|
||||
"devtools.inspector.mdnDocsTooltip.enabled";
|
||||
|
||||
const TEST_URI = `
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
padding {font-family: margin;}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<padding>MDN tooltip testing</padding>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
info("Ensure the pref is true to begin with");
|
||||
let initial = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
|
||||
if (initial != true) {
|
||||
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
|
||||
}
|
||||
|
||||
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_URI));
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield selectNode("padding", inspector);
|
||||
yield testMdnContextMenuItemVisibility(view);
|
||||
|
||||
info("Ensure the pref is reset to its initial value");
|
||||
let eventual = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
|
||||
if (eventual != initial) {
|
||||
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, initial);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Set a boolean pref, and wait for the pref observer to
|
||||
* trigger, so that code listening for the pref change
|
||||
* has had a chance to update itself.
|
||||
*
|
||||
* @param pref {string} Name of the pref to change
|
||||
* @param state {boolean} Desired value of the pref.
|
||||
*
|
||||
* Note that if the pref already has the value in `state`,
|
||||
* then the prefObserver will not trigger. So you should only
|
||||
* call this function if you know the pref's current value is
|
||||
* not `state`.
|
||||
*/
|
||||
function* setBooleanPref(pref, state) {
|
||||
let oncePrefChanged = defer();
|
||||
let prefObserver = new PrefObserver("devtools.");
|
||||
prefObserver.on(pref, oncePrefChanged.resolve);
|
||||
|
||||
info("Set the pref " + pref + " to: " + state);
|
||||
Services.prefs.setBoolPref(pref, state);
|
||||
|
||||
info("Wait for prefObserver to call back so the UI can update");
|
||||
yield oncePrefChanged.promise;
|
||||
prefObserver.off(pref, oncePrefChanged.resolve);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the MDN context menu item is shown when it should be,
|
||||
* and hidden when it should be.
|
||||
* - iterate through every node in the rule view
|
||||
* - set that node as popupNode (the node that the context menu
|
||||
* is shown for)
|
||||
* - update the context menu's state
|
||||
* - test that the MDN context menu item is hidden, or not,
|
||||
* depending on popupNode
|
||||
*/
|
||||
function* testMdnContextMenuItemVisibility(view) {
|
||||
info("Test that MDN context menu item is shown only when it should be.");
|
||||
|
||||
let root = rootElement(view);
|
||||
for (let node of iterateNodes(root)) {
|
||||
info("Setting " + node + " as popupNode");
|
||||
info("Creating context menu with " + node + " as popupNode");
|
||||
let allMenuItems = openStyleContextMenuAndGetAllItems(view, node);
|
||||
let menuitemShowMdnDocs = allMenuItems.find(item => item.label ===
|
||||
STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"));
|
||||
|
||||
let isVisible = menuitemShowMdnDocs.visible;
|
||||
let shouldBeVisible = isPropertyNameNode(node);
|
||||
let message = shouldBeVisible ? "shown" : "hidden";
|
||||
is(isVisible, shouldBeVisible,
|
||||
"The MDN context menu item is " + message + " ; content : " +
|
||||
node.textContent + " ; type : " + node.nodeType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a node is a property name.
|
||||
*/
|
||||
function isPropertyNameNode(node) {
|
||||
return node.textContent === "font-family";
|
||||
}
|
||||
|
||||
/**
|
||||
* A generator that iterates recursively through all child nodes of baseNode.
|
||||
*/
|
||||
function* iterateNodes(baseNode) {
|
||||
yield baseNode;
|
||||
|
||||
for (let child of baseNode.childNodes) {
|
||||
yield* iterateNodes(child);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root element for the rule view.
|
||||
*/
|
||||
var rootElement = view => (view.element) ? view.element : view.styleDocument;
|
||||
@@ -1,60 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This file tests the code that integrates the Style Inspector's rule view
|
||||
* with the MDN docs tooltip.
|
||||
*
|
||||
* If you display the context click on a property name in the rule view, you
|
||||
* should see a menu item "Show MDN Docs". If you click that item, the MDN
|
||||
* docs tooltip should be shown, containing docs from MDN for that property.
|
||||
*
|
||||
* This file tests that:
|
||||
* - clicking the context menu item shows the tooltip
|
||||
* - the tooltip content matches the property name for which the context menu was opened
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const {setBaseCssDocsUrl} =
|
||||
require("devtools/client/shared/widgets/MdnDocsWidget");
|
||||
|
||||
const PROPERTYNAME = "color";
|
||||
|
||||
const TEST_DOC = `
|
||||
<html>
|
||||
<body>
|
||||
<div style="color: red">
|
||||
Test "Show MDN Docs" context menu option
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_DOC));
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield selectNode("div", inspector);
|
||||
|
||||
setBaseCssDocsUrl(URL_ROOT);
|
||||
|
||||
info("Setting the popupNode for the MDN docs tooltip");
|
||||
|
||||
let {nameSpan} = getRuleViewProperty(view, "element", PROPERTYNAME);
|
||||
|
||||
let allMenuItems = openStyleContextMenuAndGetAllItems(view, nameSpan.firstChild);
|
||||
let menuitemShowMdnDocs = allMenuItems.find(item => item.label ===
|
||||
STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"));
|
||||
|
||||
let cssDocs = view.tooltips.cssDocs;
|
||||
|
||||
info("Showing the MDN docs tooltip");
|
||||
let onShown = cssDocs.tooltip.once("shown");
|
||||
menuitemShowMdnDocs.click();
|
||||
yield onShown;
|
||||
ok(true, "The MDN docs tooltip was shown");
|
||||
|
||||
info("Quick check that the tooltip contents are set");
|
||||
let h1 = cssDocs.tooltip.container.querySelector(".mdn-property-name");
|
||||
is(h1.textContent, PROPERTYNAME, "The MDN docs tooltip h1 is correct");
|
||||
});
|
||||
@@ -1,117 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This file tests the "devtools.inspector.mdnDocsTooltip.enabled" preference,
|
||||
* that we use to enable/disable the MDN tooltip in the Inspector.
|
||||
*
|
||||
* The desired behavior is:
|
||||
* - if the preference is true, show the "Show MDN Docs" context menu item
|
||||
* - if the preference is false, don't show the item
|
||||
* - listen for changes to the pref, so we can show/hide the item dynamically
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const { PrefObserver } = require("devtools/client/styleeditor/utils");
|
||||
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
|
||||
"devtools.inspector.mdnDocsTooltip.enabled";
|
||||
const PROPERTY_NAME_CLASS = "ruleview-propertyname";
|
||||
|
||||
const TEST_DOC = `
|
||||
<html>
|
||||
<body>
|
||||
<div style="color: red">
|
||||
Test the pref to enable/disable the "Show MDN Docs" context menu option
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
add_task(function* () {
|
||||
info("Ensure the pref is true to begin with");
|
||||
let initial = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
|
||||
if (initial != true) {
|
||||
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
|
||||
}
|
||||
|
||||
yield addTab("data:text/html;charset=utf8," + encodeURIComponent(TEST_DOC));
|
||||
|
||||
let {inspector, view} = yield openRuleView();
|
||||
yield selectNode("div", inspector);
|
||||
yield testMdnContextMenuItemVisibility(view, true);
|
||||
|
||||
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, false);
|
||||
yield testMdnContextMenuItemVisibility(view, false);
|
||||
|
||||
info("Close the Inspector");
|
||||
let target = TargetFactory.forTab(gBrowser.selectedTab);
|
||||
yield gDevTools.closeToolbox(target);
|
||||
|
||||
({inspector, view} = yield openRuleView());
|
||||
yield selectNode("div", inspector);
|
||||
yield testMdnContextMenuItemVisibility(view, false);
|
||||
|
||||
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, true);
|
||||
yield testMdnContextMenuItemVisibility(view, true);
|
||||
|
||||
info("Ensure the pref is reset to its initial value");
|
||||
let eventual = Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP);
|
||||
if (eventual != initial) {
|
||||
yield setBooleanPref(PREF_ENABLE_MDN_DOCS_TOOLTIP, initial);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Set a boolean pref, and wait for the pref observer to
|
||||
* trigger, so that code listening for the pref change
|
||||
* has had a chance to update itself.
|
||||
*
|
||||
* @param pref {string} Name of the pref to change
|
||||
* @param state {boolean} Desired value of the pref.
|
||||
*
|
||||
* Note that if the pref already has the value in `state`,
|
||||
* then the prefObserver will not trigger. So you should only
|
||||
* call this function if you know the pref's current value is
|
||||
* not `state`.
|
||||
*/
|
||||
function* setBooleanPref(pref, state) {
|
||||
let oncePrefChanged = defer();
|
||||
let prefObserver = new PrefObserver("devtools.");
|
||||
prefObserver.on(pref, oncePrefChanged.resolve);
|
||||
|
||||
info("Set the pref " + pref + " to: " + state);
|
||||
Services.prefs.setBoolPref(pref, state);
|
||||
|
||||
info("Wait for prefObserver to call back so the UI can update");
|
||||
yield oncePrefChanged.promise;
|
||||
prefObserver.off(pref, oncePrefChanged.resolve);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the MDN tooltip context menu item is visible when it should be.
|
||||
*
|
||||
* @param view The rule view
|
||||
* @param shouldBeVisible {boolean} Whether we expect the context
|
||||
* menu item to be visible or not.
|
||||
*/
|
||||
function* testMdnContextMenuItemVisibility(view, shouldBeVisible) {
|
||||
let message = shouldBeVisible ? "shown" : "hidden";
|
||||
info("Test that MDN context menu item is " + message);
|
||||
|
||||
info("Set a CSS property name as popupNode");
|
||||
let root = rootElement(view);
|
||||
let node = root.querySelector("." + PROPERTY_NAME_CLASS).firstChild;
|
||||
let allMenuItems = openStyleContextMenuAndGetAllItems(view, node);
|
||||
let menuitemShowMdnDocs = allMenuItems.find(item => item.label ===
|
||||
STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"));
|
||||
|
||||
let isVisible = menuitemShowMdnDocs.visible;
|
||||
is(isVisible, shouldBeVisible,
|
||||
"The MDN context menu item is " + message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root element for the rule view.
|
||||
*/
|
||||
var rootElement = view => (view.element) ? view.element : view.styleDocument;
|
||||
@@ -25,9 +25,6 @@ const STYLE_INSPECTOR_PROPERTIES = "devtools/shared/locales/styleinspector.prope
|
||||
const {LocalizationHelper} = require("devtools/shared/l10n");
|
||||
const STYLE_INSPECTOR_L10N = new LocalizationHelper(STYLE_INSPECTOR_PROPERTIES);
|
||||
|
||||
const PREF_ENABLE_MDN_DOCS_TOOLTIP =
|
||||
"devtools.inspector.mdnDocsTooltip.enabled";
|
||||
|
||||
/**
|
||||
* Style inspector context menu
|
||||
*
|
||||
@@ -56,7 +53,6 @@ function StyleInspectorMenu(view, options) {
|
||||
this._onCopySelector = this._onCopySelector.bind(this);
|
||||
this._onCopyUrl = this._onCopyUrl.bind(this);
|
||||
this._onSelectAll = this._onSelectAll.bind(this);
|
||||
this._onShowMdnDocs = this._onShowMdnDocs.bind(this);
|
||||
this._onToggleOrigSources = this._onToggleOrigSources.bind(this);
|
||||
}
|
||||
|
||||
@@ -229,19 +225,6 @@ StyleInspectorMenu.prototype = {
|
||||
});
|
||||
menu.append(menuitemAddRule);
|
||||
|
||||
// Show MDN Docs
|
||||
let mdnDocsAccessKey = "styleinspector.contextmenu.showMdnDocs.accessKey";
|
||||
let menuitemShowMdnDocs = new MenuItem({
|
||||
label: STYLE_INSPECTOR_L10N.getStr("styleinspector.contextmenu.showMdnDocs"),
|
||||
accesskey: STYLE_INSPECTOR_L10N.getStr(mdnDocsAccessKey),
|
||||
click: () => {
|
||||
this._onShowMdnDocs();
|
||||
},
|
||||
visible: (Services.prefs.getBoolPref(PREF_ENABLE_MDN_DOCS_TOOLTIP) &&
|
||||
this._isPropertyName()),
|
||||
});
|
||||
menu.append(menuitemShowMdnDocs);
|
||||
|
||||
// Show Original Sources
|
||||
let sourcesAccessKey = "styleinspector.contextmenu.toggleOrigSources.accessKey";
|
||||
let menuitemSources = new MenuItem({
|
||||
@@ -407,16 +390,6 @@ StyleInspectorMenu.prototype = {
|
||||
clipboardHelper.copyString(message);
|
||||
}),
|
||||
|
||||
/**
|
||||
* Show docs from MDN for a CSS property.
|
||||
*/
|
||||
_onShowMdnDocs: function () {
|
||||
let cssPropertyName = this.styleDocument.popupNode.textContent;
|
||||
let anchor = this.styleDocument.popupNode.parentNode;
|
||||
let cssDocsTooltip = this.view.tooltips.cssDocs;
|
||||
cssDocsTooltip.show(anchor, cssPropertyName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a new rule to the current element.
|
||||
*/
|
||||
|
||||
@@ -18,7 +18,6 @@ const {
|
||||
} = require("devtools/client/inspector/shared/node-types");
|
||||
const { getColor } = require("devtools/client/shared/theme");
|
||||
const { getCssProperties } = require("devtools/shared/fronts/css-properties");
|
||||
const CssDocsTooltip = require("devtools/client/shared/widgets/tooltip/CssDocsTooltip");
|
||||
const { HTMLTooltip } = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
|
||||
const {
|
||||
getImageDimensions,
|
||||
@@ -82,9 +81,6 @@ TooltipsOverlay.prototype = {
|
||||
this.previewTooltip.startTogglingOnHover(this.view.element,
|
||||
this._onPreviewTooltipTargetHover.bind(this));
|
||||
|
||||
// MDN CSS help tooltip
|
||||
this.cssDocs = new CssDocsTooltip(toolbox.doc);
|
||||
|
||||
if (this.isRuleView) {
|
||||
// Color picker tooltip
|
||||
this.colorPicker = new SwatchColorPickerTooltip(toolbox.doc,
|
||||
@@ -120,10 +116,6 @@ TooltipsOverlay.prototype = {
|
||||
this.cubicBezier.destroy();
|
||||
}
|
||||
|
||||
if (this.cssDocs) {
|
||||
this.cssDocs.destroy();
|
||||
}
|
||||
|
||||
if (this.filterEditor) {
|
||||
this.filterEditor.destroy();
|
||||
}
|
||||
@@ -191,10 +183,6 @@ TooltipsOverlay.prototype = {
|
||||
this.cubicBezier.hide();
|
||||
}
|
||||
|
||||
if (this.isRuleView && this.cssDocs.tooltip.isVisible()) {
|
||||
this.cssDocs.hide();
|
||||
}
|
||||
|
||||
if (this.isRuleView && this.filterEditor.tooltip.isVisible()) {
|
||||
this.filterEditor.revert();
|
||||
this.filterEdtior.hide();
|
||||
@@ -295,10 +283,6 @@ TooltipsOverlay.prototype = {
|
||||
this.cubicBezier.hide();
|
||||
}
|
||||
|
||||
if (this.cssDocs) {
|
||||
this.cssDocs.hide();
|
||||
}
|
||||
|
||||
if (this.filterEditor) {
|
||||
this.filterEditor.hide();
|
||||
}
|
||||
|
||||
@@ -117,7 +117,6 @@ devtools.jar:
|
||||
content/framework/connect/connect.js (framework/connect/connect.js)
|
||||
content/shared/widgets/graphs-frame.xhtml (shared/widgets/graphs-frame.xhtml)
|
||||
content/shared/widgets/cubic-bezier.css (shared/widgets/cubic-bezier.css)
|
||||
content/shared/widgets/mdn-docs.css (shared/widgets/mdn-docs.css)
|
||||
content/shared/widgets/filter-widget.css (shared/widgets/filter-widget.css)
|
||||
content/shared/widgets/spectrum.css (shared/widgets/spectrum.css)
|
||||
content/aboutdebugging/aboutdebugging.xhtml (aboutdebugging/aboutdebugging.xhtml)
|
||||
|
||||
@@ -48,14 +48,6 @@ eyedropper.disabled.title=Unavailable in non-HTML documents
|
||||
#LOCALIZATION NOTE: Used in the image preview tooltip when the image could not be loaded
|
||||
eventsTooltip.openInDebugger=Open in Debugger
|
||||
|
||||
# LOCALIZATION NOTE (docsTooltip.visitMDN): Shown in the tooltip that displays
|
||||
# help from MDN. This is a link to the complete MDN documentation page.
|
||||
docsTooltip.visitMDN=Visit MDN page
|
||||
|
||||
# LOCALIZATION NOTE (docsTooltip.visitMDN): Shown in the docs tooltip when the MDN page
|
||||
# could not be loaded (for example, because of a connectivity problem).
|
||||
docsTooltip.loadDocsError=Could not load docs page.
|
||||
|
||||
# LOCALIZATION NOTE (inspector.collapsePane): This is the tooltip for the button
|
||||
# that collapses the right panel (rules, computed, box-model, etc...) in the
|
||||
# inspector UI.
|
||||
|
||||
@@ -47,8 +47,6 @@ pref("devtools.inspector.imagePreviewTooltipSize", 300);
|
||||
pref("devtools.inspector.showUserAgentStyles", false);
|
||||
// Show all native anonymous content (like controls in <video> tags)
|
||||
pref("devtools.inspector.showAllAnonymousContent", false);
|
||||
// Enable the MDN docs tooltip
|
||||
pref("devtools.inspector.mdnDocsTooltip.enabled", false);
|
||||
|
||||
// Enable the Font Inspector
|
||||
pref("devtools.fontinspector.enabled", true);
|
||||
|
||||
@@ -78,7 +78,7 @@ html, body {
|
||||
}
|
||||
|
||||
select {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: var(--theme-toolbar-background);
|
||||
background-image: var(--viewport-selection-arrow);
|
||||
background-position: 100% 50%;
|
||||
|
||||
@@ -427,7 +427,8 @@ const CurlUtils = {
|
||||
.replace(/[`$]/g, "\\$&")
|
||||
// Then escape all characters we are not sure about with ^ to ensure it
|
||||
// gets to the MS CRT parser safely.
|
||||
.replace(/[^a-zA-Z0-9\s_\-:=+~\/.',?;()*\$&\\{}\"`]/g, "^$&")
|
||||
// Note: Do not escape unicode control non-printable characters (0000-001f + 007f-009f)
|
||||
.replace(/[^a-zA-Z0-9\s_\-:=+~\/.',?;()*\$&\\{}\"`\u0000-\u001f\u007f-\u009f]/g, "^$&")
|
||||
// The % character is special because MS CRT parser will try and look for
|
||||
// ENV variables and fill them in its place. We cannot escape them with %
|
||||
// and cannot escape them with ^ (because it's cmd.exe's escape not MS CRT
|
||||
@@ -436,14 +437,17 @@ const CurlUtils = {
|
||||
// This ensures we do not try and double escape another ^ if it was placed
|
||||
// by the previous replace.
|
||||
.replace(/%(?=[a-zA-Z0-9_])/g, "%^")
|
||||
// We replace \r and \r\n with \n, this allows to consistently escape all new
|
||||
// lines in the next replace
|
||||
.replace(/\r\n?/g, "\n")
|
||||
// All other whitespace characters are replaced with a single space, as there
|
||||
// is no way to enter their literal values in a command line, and they do break
|
||||
// the command sequence, allowing for injection.
|
||||
// Since want to keep line breaks, we need to exclude them in the regex (`[^\r\n]`),
|
||||
// and use double negations to get the other whitespace chars (`[^\S]` translates
|
||||
// to "not not whitespace")
|
||||
.replace(/[^\S\r\n]/g, " ")
|
||||
// Lastly we replace new lines with ^ and TWO new lines because the first
|
||||
// new line is there to enact the escape command the second is the character
|
||||
// to escape (in this case new line).
|
||||
// The extra " enables escaping new lines with ^ within quotes in cmd.exe.
|
||||
.replace(/\n/g, '"^\r\n\r\n"')
|
||||
.replace(/\r?\n|\r/g, "^\n\n")
|
||||
+ encapsChars
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,11 +13,6 @@ support-files =
|
||||
helper_color_data.js
|
||||
helper_html_tooltip.js
|
||||
helper_inplace_editor.js
|
||||
html-mdn-css-basic-testing.html
|
||||
html-mdn-css-no-summary.html
|
||||
html-mdn-css-no-summary-or-syntax.html
|
||||
html-mdn-css-no-syntax.html
|
||||
html-mdn-css-syntax-old-style.html
|
||||
leakhunt.js
|
||||
test-actor.js
|
||||
test-actor-registry.js
|
||||
@@ -140,9 +135,6 @@ skip-if = e10s # Bug 1221911, bug 1222289, frequent e10s timeouts
|
||||
skip-if = e10s # Layouthelpers test should not run in a content page.
|
||||
[browser_layoutHelpers-getBoxQuads.js]
|
||||
skip-if = e10s # Layouthelpers test should not run in a content page.
|
||||
[browser_mdn-docs-01.js]
|
||||
[browser_mdn-docs-02.js]
|
||||
[browser_mdn-docs-03.js]
|
||||
[browser_num-l10n.js]
|
||||
[browser_options-view-01.js]
|
||||
[browser_outputparser.js]
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This file tests the MdnDocsWidget object, and specifically its
|
||||
* loadCssDocs() function.
|
||||
*
|
||||
* The MdnDocsWidget is initialized with a document which has a specific
|
||||
* structure. You then call loadCssDocs(), passing in a CSS property name.
|
||||
* MdnDocsWidget then fetches docs for that property by making an XHR to
|
||||
* a docs page, and loads the results into the document. While the XHR is
|
||||
* still not resolved the document is put into an "initializing" state in
|
||||
* which the devtools throbber is displayed.
|
||||
*
|
||||
* In this file we test:
|
||||
* - the initial state of the document before the docs have loaded
|
||||
* - the state of the document after the docs have loaded
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const {setBaseCssDocsUrl, MdnDocsWidget} = require("devtools/client/shared/widgets/MdnDocsWidget");
|
||||
|
||||
/**
|
||||
* Test properties
|
||||
*
|
||||
* In the real tooltip, a CSS property name is used to look up an MDN page
|
||||
* for that property.
|
||||
* In the test code, the names defined here is used to look up a page
|
||||
* served by the test server.
|
||||
*/
|
||||
const BASIC_TESTING_PROPERTY = "html-mdn-css-basic-testing.html";
|
||||
|
||||
const BASIC_EXPECTED_SUMMARY = "A summary of the property.";
|
||||
const BASIC_EXPECTED_SYNTAX = [{type: "comment", text: "/* The part we want */"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "this"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "is-the-part-we-want"},
|
||||
{type: "text", text: ";"}];
|
||||
|
||||
const URI_PARAMS =
|
||||
"?utm_source=mozilla&utm_medium=firefox-inspector&utm_campaign=default";
|
||||
|
||||
add_task(function* () {
|
||||
setBaseCssDocsUrl(TEST_URI_ROOT);
|
||||
|
||||
yield addTab("about:blank");
|
||||
let [host, win] = yield createHost("bottom", "data:text/html," +
|
||||
"<div class='mdn-container'></div>");
|
||||
let widget = new MdnDocsWidget(win.document.querySelector("div"));
|
||||
|
||||
yield testTheBasics(widget);
|
||||
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
/**
|
||||
* Test all the basics
|
||||
* - initial content, before docs have loaded, is as expected
|
||||
* - throbber is set before docs have loaded
|
||||
* - contents are as expected after docs have loaded
|
||||
* - throbber is gone after docs have loaded
|
||||
* - mdn link text is correct and onclick behavior is correct
|
||||
*/
|
||||
function* testTheBasics(widget) {
|
||||
info("Test all the basic functionality in the widget");
|
||||
|
||||
info("Get the widget state before docs have loaded");
|
||||
let promise = widget.loadCssDocs(BASIC_TESTING_PROPERTY);
|
||||
|
||||
info("Check initial contents before docs have loaded");
|
||||
checkTooltipContents(widget.elements, {
|
||||
propertyName: BASIC_TESTING_PROPERTY,
|
||||
summary: "",
|
||||
syntax: ""
|
||||
});
|
||||
|
||||
// throbber is set
|
||||
ok(widget.elements.info.classList.contains("devtools-throbber"),
|
||||
"Throbber is set");
|
||||
|
||||
info("Now let the widget finish loading");
|
||||
yield promise;
|
||||
|
||||
info("Check contents after docs have loaded");
|
||||
checkTooltipContents(widget.elements, {
|
||||
propertyName: BASIC_TESTING_PROPERTY,
|
||||
summary: BASIC_EXPECTED_SUMMARY,
|
||||
syntax: BASIC_EXPECTED_SYNTAX
|
||||
});
|
||||
|
||||
// throbber is gone
|
||||
ok(!widget.elements.info.classList.contains("devtools-throbber"),
|
||||
"Throbber is not set");
|
||||
|
||||
info("Check that MDN link text is correct and onclick behavior is correct");
|
||||
|
||||
let mdnLink = widget.elements.linkToMdn;
|
||||
let expectedHref = TEST_URI_ROOT + BASIC_TESTING_PROPERTY + URI_PARAMS;
|
||||
is(mdnLink.href, expectedHref, "MDN link href is correct");
|
||||
|
||||
let uri = yield checkLinkClick(mdnLink);
|
||||
is(uri, expectedHref, "New tab opened with the expected URI");
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicking the "Visit MDN Page" in the tooltip panel
|
||||
* should open a new browser tab with the page loaded.
|
||||
*
|
||||
* To test this we'll listen for a new tab opening, and
|
||||
* when it does, add a listener to that new tab to tell
|
||||
* us when it has loaded.
|
||||
*
|
||||
* Then we click the link.
|
||||
*
|
||||
* In the tab's load listener, we'll resolve the promise
|
||||
* with the URI, which is expected to match the href
|
||||
* in the orginal link.
|
||||
*
|
||||
* One complexity is that when you open a new tab,
|
||||
* "about:blank" is first loaded into the tab before the
|
||||
* actual page. So we ignore that first load event, and keep
|
||||
* listening until "load" is triggered for a different URI.
|
||||
*/
|
||||
function checkLinkClick(link) {
|
||||
function loadListener(tab) {
|
||||
let browser = getBrowser().getBrowserForTab(tab);
|
||||
let uri = browser.currentURI.spec;
|
||||
|
||||
info("New browser tab has loaded");
|
||||
gBrowser.removeTab(tab);
|
||||
info("Resolve promise with new tab URI");
|
||||
deferred.resolve(uri);
|
||||
}
|
||||
|
||||
function newTabListener(e) {
|
||||
gBrowser.tabContainer.removeEventListener("TabOpen", newTabListener);
|
||||
let tab = e.target;
|
||||
BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, url => url != "about:blank")
|
||||
.then(url => loadListener(tab));
|
||||
}
|
||||
|
||||
let deferred = defer();
|
||||
info("Check that clicking the link opens a new tab with the correct URI");
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", newTabListener, false);
|
||||
info("Click the link to MDN");
|
||||
link.click();
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to check content of the tooltip.
|
||||
*/
|
||||
function checkTooltipContents(doc, expected) {
|
||||
is(doc.heading.textContent,
|
||||
expected.propertyName,
|
||||
"Property name is correct");
|
||||
|
||||
is(doc.summary.textContent,
|
||||
expected.summary,
|
||||
"Summary is correct");
|
||||
|
||||
checkCssSyntaxHighlighterOutput(expected.syntax, doc.syntax);
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This file tests the MdnDocsWidget object, and specifically its
|
||||
* loadCssDocs() function.
|
||||
*
|
||||
* The MdnDocsWidget is initialized with a document which has a specific
|
||||
* structure. You then call loadCssDocs(), passing in a CSS property name.
|
||||
* MdnDocsWidget then fetches docs for that property by making an XHR to
|
||||
* a docs page, and loads the results into the document.
|
||||
*
|
||||
* In this file we test that the tooltip can properly handle the different
|
||||
* structures that the docs page might have, including variant structures and
|
||||
* error conditions like parts of the document being missing.
|
||||
*
|
||||
* We also test that the tooltip properly handles the case where the page
|
||||
* doesn't exist at all.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const {
|
||||
setBaseCssDocsUrl,
|
||||
MdnDocsWidget
|
||||
} = require("devtools/client/shared/widgets/MdnDocsWidget");
|
||||
|
||||
const BASIC_EXPECTED_SUMMARY = "A summary of the property.";
|
||||
const BASIC_EXPECTED_SYNTAX = [{type: "comment", text: "/* The part we want */"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "this"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "is-the-part-we-want"},
|
||||
{type: "text", text: ";"}];
|
||||
|
||||
const ERROR_MESSAGE = "Could not load docs page.";
|
||||
|
||||
/**
|
||||
* Test properties
|
||||
*
|
||||
* In the real tooltip, a CSS property name is used to look up an MDN page
|
||||
* for that property.
|
||||
* In the test code, the names defined here are used to look up a page
|
||||
* served by the test server. We have different properties to test
|
||||
* different ways that the docs pages might be constructed, including errors
|
||||
* like pages that don't include docs where we expect.
|
||||
*/
|
||||
const SYNTAX_OLD_STYLE = "html-mdn-css-syntax-old-style.html";
|
||||
const NO_SUMMARY = "html-mdn-css-no-summary.html";
|
||||
const NO_SYNTAX = "html-mdn-css-no-syntax.html";
|
||||
const NO_SUMMARY_OR_SYNTAX = "html-mdn-css-no-summary-or-syntax.html";
|
||||
|
||||
const TEST_DATA = [{
|
||||
desc: "Test a property for which we don't have a page",
|
||||
docsPageUrl: "i-dont-exist.html",
|
||||
expectedContents: {
|
||||
propertyName: "i-dont-exist.html",
|
||||
summary: ERROR_MESSAGE,
|
||||
syntax: []
|
||||
}
|
||||
}, {
|
||||
desc: "Test a property whose syntax section is specified using an old-style page",
|
||||
docsPageUrl: SYNTAX_OLD_STYLE,
|
||||
expectedContents: {
|
||||
propertyName: SYNTAX_OLD_STYLE,
|
||||
summary: BASIC_EXPECTED_SUMMARY,
|
||||
syntax: BASIC_EXPECTED_SYNTAX
|
||||
}
|
||||
}, {
|
||||
desc: "Test a property whose page doesn't have a summary",
|
||||
docsPageUrl: NO_SUMMARY,
|
||||
expectedContents: {
|
||||
propertyName: NO_SUMMARY,
|
||||
summary: "",
|
||||
syntax: BASIC_EXPECTED_SYNTAX
|
||||
}
|
||||
}, {
|
||||
desc: "Test a property whose page doesn't have a syntax",
|
||||
docsPageUrl: NO_SYNTAX,
|
||||
expectedContents: {
|
||||
propertyName: NO_SYNTAX,
|
||||
summary: BASIC_EXPECTED_SUMMARY,
|
||||
syntax: []
|
||||
}
|
||||
}, {
|
||||
desc: "Test a property whose page doesn't have a summary or a syntax",
|
||||
docsPageUrl: NO_SUMMARY_OR_SYNTAX,
|
||||
expectedContents: {
|
||||
propertyName: NO_SUMMARY_OR_SYNTAX,
|
||||
summary: ERROR_MESSAGE,
|
||||
syntax: []
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
add_task(function* () {
|
||||
setBaseCssDocsUrl(TEST_URI_ROOT);
|
||||
|
||||
yield addTab("about:blank");
|
||||
let [host, win] = yield createHost("bottom", "data:text/html," +
|
||||
"<div class='mdn-container'></div>");
|
||||
let widget = new MdnDocsWidget(win.document.querySelector("div"));
|
||||
|
||||
for (let {desc, docsPageUrl, expectedContents} of TEST_DATA) {
|
||||
info(desc);
|
||||
yield widget.loadCssDocs(docsPageUrl);
|
||||
checkTooltipContents(widget.elements, expectedContents);
|
||||
}
|
||||
host.destroy();
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
/*
|
||||
* Utility function to check content of the tooltip.
|
||||
*/
|
||||
function checkTooltipContents(doc, expected) {
|
||||
is(doc.heading.textContent,
|
||||
expected.propertyName,
|
||||
"Property name is correct");
|
||||
|
||||
is(doc.summary.textContent,
|
||||
expected.summary,
|
||||
"Summary is correct");
|
||||
|
||||
checkCssSyntaxHighlighterOutput(expected.syntax, doc.syntax);
|
||||
}
|
||||
@@ -1,276 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/**
|
||||
* This file tests the CSS syntax highlighter in the MdnDocsWidget object.
|
||||
*
|
||||
* The CSS syntax highlighter accepts:
|
||||
* - a string containing CSS
|
||||
* - a DOM node
|
||||
*
|
||||
* It parses the string and creates a collection of DOM nodes for different
|
||||
* CSS token types. These DOM nodes have CSS classes applied to them,
|
||||
* to apply the right style for that particular token type. The DOM nodes
|
||||
* are returned as children of the node that was passed to the function.
|
||||
*
|
||||
* This test code defines a number of different strings containing valid and
|
||||
* invalid CSS in various forms. For each string it defines the DOM nodes
|
||||
* that it expects to get from the syntax highlighter.
|
||||
*
|
||||
* It then calls the syntax highlighter, and checks that the resulting
|
||||
* collection of DOM nodes is what we expected.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const {appendSyntaxHighlightedCSS} = require("devtools/client/shared/widgets/MdnDocsWidget");
|
||||
|
||||
/**
|
||||
* An array containing the actual test cases.
|
||||
*
|
||||
* The test code tests every case in the array. If you want to add more
|
||||
* test cases, just add more items to the array.
|
||||
*
|
||||
* Each test case consists of:
|
||||
* - description: string describing the salient features of this test case
|
||||
* - example: the string to test
|
||||
* - expected: an array of objects, one for each DOM node we expect, that
|
||||
* captures the information about the node that we expect to test.
|
||||
*/
|
||||
const TEST_DATA = [{
|
||||
description: "Valid syntax, string value.",
|
||||
example: "name: stringValue;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, numeric value.",
|
||||
example: "name: 1;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "1"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, url value.",
|
||||
example: "name: url(./name);",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "url(./name)"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, space before ':'.",
|
||||
example: "name : stringValue;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: " "},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, space before ';'.",
|
||||
example: "name: stringValue ;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: " "},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, trailing space.",
|
||||
example: "name: stringValue; ",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"},
|
||||
{type: "text", text: " "}
|
||||
]}, {
|
||||
description: "Valid syntax, leading space.",
|
||||
example: " name: stringValue;",
|
||||
expected: [{type: "text", text: " "},
|
||||
{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, two spaces.",
|
||||
example: "name: stringValue;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, no spaces.",
|
||||
example: "name:stringValue;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, two-part value.",
|
||||
example: "name: stringValue 1;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "1"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, two declarations.",
|
||||
example: "name: stringValue;\n" +
|
||||
"name: 1;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "1"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, commented, numeric value.",
|
||||
example: "/* comment */\n" +
|
||||
"name: 1;",
|
||||
expected: [{type: "comment", text: "/* comment */"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "1"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, multiline commented, string value.",
|
||||
example: "/* multiline \n" +
|
||||
"comment */\n" +
|
||||
"name: stringValue;",
|
||||
expected: [{type: "comment", text: "/* multiline \ncomment */"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, commented, two declarations.",
|
||||
example: "/* comment 1 */\n" +
|
||||
"name: 1;\n" +
|
||||
"/* comment 2 */\n" +
|
||||
"name: stringValue;",
|
||||
expected: [{type: "comment", text: "/* comment 1 */"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "1"},
|
||||
{type: "text", text: ";"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "comment", text: "/* comment 2 */"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, multiline.",
|
||||
example: "name: \n" +
|
||||
"stringValue;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " \n"},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Valid syntax, multiline, two declarations.",
|
||||
example: "name: \n" +
|
||||
"stringValue \n" +
|
||||
"stringValue2;",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " \n"},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: " \n"},
|
||||
{type: "property-value", text: "stringValue2"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Invalid: not CSS at all.",
|
||||
example: "not CSS at all",
|
||||
expected: [{type: "property-name", text: "not"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-name", text: "CSS"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-name", text: "at"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-name", text: "all"}
|
||||
]}, {
|
||||
description: "Invalid: switched ':' and ';'.",
|
||||
example: "name; stringValue:",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ";"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-name", text: "stringValue"},
|
||||
{type: "text", text: ":"}
|
||||
]}, {
|
||||
description: "Invalid: unterminated comment.",
|
||||
example: "/* unterminated comment\n" +
|
||||
"name: stringValue;",
|
||||
expected: [{type: "comment", text: "/* unterminated comment\nname: stringValue;"}
|
||||
]}, {
|
||||
description: "Invalid: bad comment syntax.",
|
||||
example: "// invalid comment\n" +
|
||||
"name: stringValue;",
|
||||
expected: [{type: "text", text: "/"},
|
||||
{type: "text", text: "/"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-name", text: "invalid"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-name", text: "comment"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: ";"}
|
||||
]}, {
|
||||
description: "Invalid: no trailing ';'.",
|
||||
example: "name: stringValue\n" +
|
||||
"name: stringValue2",
|
||||
expected: [{type: "property-name", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue"},
|
||||
{type: "text", text: "\n"},
|
||||
{type: "property-value", text: "name"},
|
||||
{type: "text", text: ":"},
|
||||
{type: "text", text: " "},
|
||||
{type: "property-value", text: "stringValue2"},
|
||||
]}
|
||||
];
|
||||
|
||||
/**
|
||||
* Iterate through every test case, calling the syntax highlighter,
|
||||
* then calling a helper function to check the output.
|
||||
*/
|
||||
add_task(function* () {
|
||||
let doc = gBrowser.selectedTab.ownerDocument;
|
||||
let parent = doc.createElement("div");
|
||||
info("Testing all CSS syntax highlighter test cases");
|
||||
for (let {description, example, expected} of TEST_DATA) {
|
||||
info("Testing: " + description);
|
||||
appendSyntaxHighlightedCSS(example, parent);
|
||||
checkCssSyntaxHighlighterOutput(expected, parent);
|
||||
while (parent.firstChild) {
|
||||
parent.firstChild.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -242,105 +242,3 @@ Task.async(function* (widget, name, value) {
|
||||
|
||||
yield onRender;
|
||||
});
|
||||
|
||||
/**
|
||||
* Utility function for testing CSS code samples that have been
|
||||
* syntax-highlighted.
|
||||
*
|
||||
* The CSS syntax highlighter emits a collection of DOM nodes that have
|
||||
* CSS classes applied to them. This function checks that those nodes
|
||||
* are what we expect.
|
||||
*
|
||||
* @param {array} expectedNodes
|
||||
* A representation of the nodes we expect to see.
|
||||
* Each node is an object containing two properties:
|
||||
* - type: a string which can be one of:
|
||||
* - text, comment, property-name, property-value
|
||||
* - text: the textContent of the node
|
||||
*
|
||||
* For example, given a string like this:
|
||||
* "<comment> The part we want </comment>\n this: is-the-part-we-want;"
|
||||
*
|
||||
* we would represent the expected output like this:
|
||||
* [{type: "comment", text: "<comment> The part we want </comment>"},
|
||||
* {type: "text", text: "\n"},
|
||||
* {type: "property-name", text: "this"},
|
||||
* {type: "text", text: ":"},
|
||||
* {type: "text", text: " "},
|
||||
* {type: "property-value", text: "is-the-part-we-want"},
|
||||
* {type: "text", text: ";"}];
|
||||
*
|
||||
* @param {Node} parent
|
||||
* The DOM node whose children are the output of the syntax highlighter.
|
||||
*/
|
||||
function checkCssSyntaxHighlighterOutput(expectedNodes, parent) {
|
||||
/**
|
||||
* The classes applied to the output nodes by the syntax highlighter.
|
||||
* These must be same as the definitions in MdnDocsWidget.js.
|
||||
*/
|
||||
const PROPERTY_NAME_COLOR = "theme-fg-color5";
|
||||
const PROPERTY_VALUE_COLOR = "theme-fg-color1";
|
||||
const COMMENT_COLOR = "theme-comment";
|
||||
|
||||
/**
|
||||
* Check the type and content of a single node.
|
||||
*/
|
||||
function checkNode(expected, actual) {
|
||||
ok(actual.textContent == expected.text,
|
||||
"Check that node has the expected textContent");
|
||||
info("Expected text content: [" + expected.text + "]");
|
||||
info("Actual text content: [" + actual.textContent + "]");
|
||||
|
||||
info("Check that node has the expected type");
|
||||
if (expected.type == "text") {
|
||||
ok(actual.nodeType == 3, "Check that node is a text node");
|
||||
} else {
|
||||
ok(actual.tagName.toUpperCase() == "SPAN", "Check that node is a SPAN");
|
||||
}
|
||||
|
||||
info("Check that node has the expected className");
|
||||
|
||||
let expectedClassName = null;
|
||||
let actualClassName = null;
|
||||
|
||||
switch (expected.type) {
|
||||
case "property-name":
|
||||
expectedClassName = PROPERTY_NAME_COLOR;
|
||||
break;
|
||||
case "property-value":
|
||||
expectedClassName = PROPERTY_VALUE_COLOR;
|
||||
break;
|
||||
case "comment":
|
||||
expectedClassName = COMMENT_COLOR;
|
||||
break;
|
||||
default:
|
||||
ok(!actual.classList, "No className expected");
|
||||
return;
|
||||
}
|
||||
|
||||
ok(actual.classList.length == 1, "One className expected");
|
||||
actualClassName = actual.classList[0];
|
||||
|
||||
ok(expectedClassName == actualClassName, "Check className value");
|
||||
info("Expected className: " + expectedClassName);
|
||||
info("Actual className: " + actualClassName);
|
||||
}
|
||||
|
||||
info("Logging the actual nodes we have:");
|
||||
for (let j = 0; j < parent.childNodes.length; j++) {
|
||||
let n = parent.childNodes[j];
|
||||
info(j + " / " +
|
||||
"nodeType: " + n.nodeType + " / " +
|
||||
"textContent: " + n.textContent);
|
||||
}
|
||||
|
||||
ok(parent.childNodes.length == parent.childNodes.length,
|
||||
"Check we have the expected number of nodes");
|
||||
info("Expected node count " + expectedNodes.length);
|
||||
info("Actual node count " + expectedNodes.length);
|
||||
|
||||
for (let i = 0; i < expectedNodes.length; i++) {
|
||||
info("Check node " + i);
|
||||
checkNode(expectedNodes[i], parent.childNodes[i]);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h2 id="Summary">Summary</h2>
|
||||
|
||||
<p>A summary of the property.</p>
|
||||
|
||||
<h2 id="Syntax">Syntax</h2>
|
||||
|
||||
<pre>/* The part we want */
|
||||
this: is-the-part-we-want;</pre>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>This is not the summary or the syntax.</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,21 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>This is not the summary.</p>
|
||||
|
||||
<h2 id="Syntax">Syntax</h2>
|
||||
|
||||
<pre>To be ignored.</pre>
|
||||
|
||||
<pre>/* The part we want */
|
||||
this: is-the-part-we-want;</pre>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h2 id="Summary">Summary</h2>
|
||||
|
||||
<p>A summary of the property.</p>
|
||||
|
||||
<p>This is not the syntax.</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<h2 id="Summary">Summary</h2>
|
||||
|
||||
<p>A summary of the property.</p>
|
||||
|
||||
<h2 id="Syntax">Syntax</h2>
|
||||
|
||||
<pre>The part we should ignore</pre>
|
||||
|
||||
<pre>/* The part we want */
|
||||
this: is-the-part-we-want;</pre>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,510 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* This file contains functions to retrieve docs content from
|
||||
* MDN (developer.mozilla.org) for particular items, and to display
|
||||
* the content in a tooltip.
|
||||
*
|
||||
* At the moment it only supports fetching content for CSS properties,
|
||||
* but it might support other types of content in the future
|
||||
* (Web APIs, for example).
|
||||
*
|
||||
* It's split into two parts:
|
||||
*
|
||||
* - functions like getCssDocs that just fetch content from MDN,
|
||||
* without any constraints on what to do with the content. If you
|
||||
* want to embed the content in some custom way, use this.
|
||||
*
|
||||
* - the MdnDocsWidget class, that manages and updates a tooltip
|
||||
* document whose content is taken from MDN. If you want to embed
|
||||
* the content in a tooltip, use this in conjunction with Tooltip.js.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const Services = require("Services");
|
||||
const defer = require("devtools/shared/defer");
|
||||
const {getCSSLexer} = require("devtools/shared/css/lexer");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const {gDevTools} = require("devtools/client/framework/devtools");
|
||||
|
||||
const {LocalizationHelper} = require("devtools/shared/l10n");
|
||||
const L10N = new LocalizationHelper("devtools/client/locales/inspector.properties");
|
||||
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
// Parameters for the XHR request
|
||||
// see https://developer.mozilla.org/en-US/docs/MDN/Kuma/API#Document_parameters
|
||||
const XHR_PARAMS = "?raw¯os";
|
||||
// URL for the XHR request
|
||||
var XHR_CSS_URL = "https://developer.mozilla.org/en-US/docs/Web/CSS/";
|
||||
|
||||
// Parameters for the link to MDN in the tooltip, so
|
||||
// so we know which MDN visits come from this feature
|
||||
const PAGE_LINK_PARAMS =
|
||||
"?utm_source=mozilla&utm_medium=firefox-inspector&utm_campaign=default";
|
||||
// URL for the page link omits locale, so a locale-specific page will be loaded
|
||||
var PAGE_LINK_URL = "https://developer.mozilla.org/docs/Web/CSS/";
|
||||
exports.PAGE_LINK_URL = PAGE_LINK_URL;
|
||||
|
||||
const PROPERTY_NAME_COLOR = "theme-fg-color5";
|
||||
const PROPERTY_VALUE_COLOR = "theme-fg-color1";
|
||||
const COMMENT_COLOR = "theme-comment";
|
||||
|
||||
/**
|
||||
* Turns a string containing a series of CSS declarations into
|
||||
* a series of DOM nodes, with classes applied to provide syntax
|
||||
* highlighting.
|
||||
*
|
||||
* It uses the CSS tokenizer to generate a stream of CSS tokens.
|
||||
* https://dxr.mozilla.org/mozilla-central/source/dom/webidl/CSSLexer.webidl
|
||||
* lists all the token types.
|
||||
*
|
||||
* - "whitespace", "comment", and "symbol" tokens are appended as TEXT nodes,
|
||||
* and will inherit the default style for text.
|
||||
*
|
||||
* - "ident" tokens that we think are property names are considered to be
|
||||
* a property name, and are appended as SPAN nodes with a distinct color class.
|
||||
*
|
||||
* - "ident" nodes which we do not think are property names, and nodes
|
||||
* of all other types ("number", "url", "percentage", ...) are considered
|
||||
* to be part of a property value, and are appended as SPAN nodes with
|
||||
* a different color class.
|
||||
*
|
||||
* @param {Document} doc
|
||||
* Used to create nodes.
|
||||
*
|
||||
* @param {String} syntaxText
|
||||
* The CSS input. This is assumed to consist of a series of
|
||||
* CSS declarations, with trailing semicolons.
|
||||
*
|
||||
* @param {DOM node} syntaxSection
|
||||
* This is the parent for the output nodes. Generated nodes
|
||||
* are appended to this as children.
|
||||
*/
|
||||
function appendSyntaxHighlightedCSS(cssText, parentElement) {
|
||||
let doc = parentElement.ownerDocument;
|
||||
let identClass = PROPERTY_NAME_COLOR;
|
||||
let lexer = getCSSLexer(cssText);
|
||||
|
||||
/**
|
||||
* Create a SPAN node with the given text content and class.
|
||||
*/
|
||||
function createStyledNode(textContent, className) {
|
||||
let newNode = doc.createElementNS(XHTML_NS, "span");
|
||||
newNode.classList.add(className);
|
||||
newNode.textContent = textContent;
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the symbol is ":", we will expect the next
|
||||
* "ident" token to be part of a property value.
|
||||
*
|
||||
* If the symbol is ";", we will expect the next
|
||||
* "ident" token to be a property name.
|
||||
*/
|
||||
function updateIdentClass(tokenText) {
|
||||
if (tokenText === ":") {
|
||||
identClass = PROPERTY_VALUE_COLOR;
|
||||
} else if (tokenText === ";") {
|
||||
identClass = PROPERTY_NAME_COLOR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the appropriate node for this token type.
|
||||
*
|
||||
* If this token is a symbol, also update our expectations
|
||||
* for what the next "ident" token represents.
|
||||
*/
|
||||
function tokenToNode(token, tokenText) {
|
||||
switch (token.tokenType) {
|
||||
case "ident":
|
||||
return createStyledNode(tokenText, identClass);
|
||||
case "symbol":
|
||||
updateIdentClass(tokenText);
|
||||
return doc.createTextNode(tokenText);
|
||||
case "whitespace":
|
||||
return doc.createTextNode(tokenText);
|
||||
case "comment":
|
||||
return createStyledNode(tokenText, COMMENT_COLOR);
|
||||
default:
|
||||
return createStyledNode(tokenText, PROPERTY_VALUE_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
let token = lexer.nextToken();
|
||||
while (token) {
|
||||
let tokenText = cssText.slice(token.startOffset, token.endOffset);
|
||||
let newNode = tokenToNode(token, tokenText);
|
||||
parentElement.appendChild(newNode);
|
||||
token = lexer.nextToken();
|
||||
}
|
||||
}
|
||||
|
||||
exports.appendSyntaxHighlightedCSS = appendSyntaxHighlightedCSS;
|
||||
|
||||
/**
|
||||
* Fetch an MDN page.
|
||||
*
|
||||
* @param {string} pageUrl
|
||||
* URL of the page to fetch.
|
||||
*
|
||||
* @return {promise}
|
||||
* The promise is resolved with the page as an XML document.
|
||||
*
|
||||
* The promise is rejected with an error message if
|
||||
* we could not load the page.
|
||||
*/
|
||||
function getMdnPage(pageUrl) {
|
||||
let deferred = defer();
|
||||
|
||||
let xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.addEventListener("load", onLoaded, false);
|
||||
xhr.addEventListener("error", onError, false);
|
||||
|
||||
xhr.open("GET", pageUrl);
|
||||
xhr.responseType = "document";
|
||||
xhr.send();
|
||||
|
||||
function onLoaded(e) {
|
||||
if (xhr.status != 200) {
|
||||
deferred.reject({page: pageUrl, status: xhr.status});
|
||||
} else {
|
||||
deferred.resolve(xhr.responseXML);
|
||||
}
|
||||
}
|
||||
|
||||
function onError(e) {
|
||||
deferred.reject({page: pageUrl, status: xhr.status});
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets some docs for the given CSS property.
|
||||
* Loads an MDN page for the property and gets some
|
||||
* information about the property.
|
||||
*
|
||||
* @param {string} cssProperty
|
||||
* The property for which we want docs.
|
||||
*
|
||||
* @return {promise}
|
||||
* The promise is resolved with an object containing:
|
||||
* - summary: a short summary of the property
|
||||
* - syntax: some example syntax
|
||||
*
|
||||
* The promise is rejected with an error message if
|
||||
* we could not load the page.
|
||||
*/
|
||||
function getCssDocs(cssProperty) {
|
||||
let deferred = defer();
|
||||
let pageUrl = XHR_CSS_URL + cssProperty + XHR_PARAMS;
|
||||
|
||||
getMdnPage(pageUrl).then(parseDocsFromResponse, handleRejection);
|
||||
|
||||
function parseDocsFromResponse(responseDocument) {
|
||||
let theDocs = {};
|
||||
theDocs.summary = getSummary(responseDocument);
|
||||
theDocs.syntax = getSyntax(responseDocument);
|
||||
if (theDocs.summary || theDocs.syntax) {
|
||||
deferred.resolve(theDocs);
|
||||
} else {
|
||||
deferred.reject("Couldn't find the docs in the page.");
|
||||
}
|
||||
}
|
||||
|
||||
function handleRejection(e) {
|
||||
deferred.reject(e.status);
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
exports.getCssDocs = getCssDocs;
|
||||
|
||||
/**
|
||||
* The MdnDocsWidget is used by tooltip code that needs to display docs
|
||||
* from MDN in a tooltip.
|
||||
*
|
||||
* In the constructor, the widget does some general setup that's not
|
||||
* dependent on the particular item we need docs for.
|
||||
*
|
||||
* After that, when the tooltip code needs to display docs for an item, it
|
||||
* asks the widget to retrieve the docs and update the document with them.
|
||||
*
|
||||
* @param {Element} tooltipContainer
|
||||
* A DOM element where the MdnDocs widget markup should be created.
|
||||
*/
|
||||
function MdnDocsWidget(tooltipContainer) {
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
tooltipContainer.innerHTML =
|
||||
`<header>
|
||||
<h1 class="mdn-property-name theme-fg-color5"></h1>
|
||||
</header>
|
||||
<div class="mdn-property-info">
|
||||
<div class="mdn-summary"></div>
|
||||
<pre class="mdn-syntax devtools-monospace"></pre>
|
||||
</div>
|
||||
<footer>
|
||||
<a class="mdn-visit-page theme-link" href="#">Visit MDN (placeholder)</a>
|
||||
</footer>`;
|
||||
|
||||
// fetch all the bits of the document that we will manipulate later
|
||||
this.elements = {
|
||||
heading: tooltipContainer.querySelector(".mdn-property-name"),
|
||||
summary: tooltipContainer.querySelector(".mdn-summary"),
|
||||
syntax: tooltipContainer.querySelector(".mdn-syntax"),
|
||||
info: tooltipContainer.querySelector(".mdn-property-info"),
|
||||
linkToMdn: tooltipContainer.querySelector(".mdn-visit-page")
|
||||
};
|
||||
|
||||
// get the localized string for the link text
|
||||
this.elements.linkToMdn.textContent = L10N.getStr("docsTooltip.visitMDN");
|
||||
|
||||
// listen for clicks and open in the browser window instead
|
||||
let mainWindow = Services.wm.getMostRecentWindow(gDevTools.chromeWindowType);
|
||||
this.elements.linkToMdn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
mainWindow.openUILinkIn(e.target.href, "tab");
|
||||
this.emit("visitlink");
|
||||
});
|
||||
}
|
||||
|
||||
exports.MdnDocsWidget = MdnDocsWidget;
|
||||
|
||||
MdnDocsWidget.prototype = {
|
||||
/**
|
||||
* This is called just before the tooltip is displayed, and is
|
||||
* passed the CSS property for which we want to display help.
|
||||
*
|
||||
* Its job is to make sure the document contains the docs
|
||||
* content for that CSS property.
|
||||
*
|
||||
* First, it initializes the document, setting the things it can
|
||||
* set synchronously, resetting the things it needs to get
|
||||
* asynchronously, and making sure the throbber is throbbing.
|
||||
*
|
||||
* Then it tries to get the content asynchronously, updating
|
||||
* the document with the content or with an error message.
|
||||
*
|
||||
* It returns immediately, so the caller can display the tooltip
|
||||
* without waiting for the asynch operation to complete.
|
||||
*
|
||||
* @param {string} propertyName
|
||||
* The name of the CSS property for which we need to display help.
|
||||
*/
|
||||
loadCssDocs: function (propertyName) {
|
||||
/**
|
||||
* Do all the setup we can do synchronously, and get the document in
|
||||
* a state where it can be displayed while we are waiting for the
|
||||
* MDN docs content to be retrieved.
|
||||
*/
|
||||
function initializeDocument(propName) {
|
||||
// set property name heading
|
||||
elements.heading.textContent = propName;
|
||||
|
||||
// set link target
|
||||
elements.linkToMdn.setAttribute("href",
|
||||
PAGE_LINK_URL + propName + PAGE_LINK_PARAMS);
|
||||
|
||||
// clear docs summary and syntax
|
||||
elements.summary.textContent = "";
|
||||
while (elements.syntax.firstChild) {
|
||||
elements.syntax.firstChild.remove();
|
||||
}
|
||||
|
||||
// reset the scroll position
|
||||
elements.info.scrollTop = 0;
|
||||
elements.info.scrollLeft = 0;
|
||||
|
||||
// show the throbber
|
||||
elements.info.classList.add("devtools-throbber");
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called if we successfully got the docs content.
|
||||
* Finishes setting up the tooltip content, and disables the throbber.
|
||||
*/
|
||||
function finalizeDocument({summary, syntax}) {
|
||||
// set docs summary and syntax
|
||||
elements.summary.textContent = summary;
|
||||
appendSyntaxHighlightedCSS(syntax, elements.syntax);
|
||||
|
||||
// hide the throbber
|
||||
elements.info.classList.remove("devtools-throbber");
|
||||
|
||||
deferred.resolve(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called if we failed to get the docs content.
|
||||
* Sets the content to contain an error message, and disables the throbber.
|
||||
*/
|
||||
function gotError(error) {
|
||||
// show error message
|
||||
elements.summary.textContent = L10N.getStr("docsTooltip.loadDocsError");
|
||||
|
||||
// hide the throbber
|
||||
elements.info.classList.remove("devtools-throbber");
|
||||
|
||||
// although gotError is called when there's an error, we have handled
|
||||
// the error, so call resolve not reject.
|
||||
deferred.resolve(this);
|
||||
}
|
||||
|
||||
let deferred = defer();
|
||||
let elements = this.elements;
|
||||
|
||||
initializeDocument(propertyName);
|
||||
getCssDocs(propertyName).then(finalizeDocument, gotError);
|
||||
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.elements = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Test whether a node is all whitespace.
|
||||
*
|
||||
* @return {boolean}
|
||||
* True if the node all whitespace, otherwise false.
|
||||
*/
|
||||
function isAllWhitespace(node) {
|
||||
return !(/[^\t\n\r ]/.test(node.textContent));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether a node is a comment or whitespace node.
|
||||
*
|
||||
* @return {boolean}
|
||||
* True if the node is a comment node or is all whitespace, otherwise false.
|
||||
*/
|
||||
function isIgnorable(node) {
|
||||
// Comment nodes (8), text nodes (3) or whitespace
|
||||
return (node.nodeType == 8) ||
|
||||
((node.nodeType == 3) && isAllWhitespace(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next node, skipping comments and whitespace.
|
||||
*
|
||||
* @return {node}
|
||||
* The next sibling node that is not a comment or whitespace, or null if
|
||||
* there isn't one.
|
||||
*/
|
||||
function nodeAfter(sib) {
|
||||
while ((sib = sib.nextSibling)) {
|
||||
if (!isIgnorable(sib)) {
|
||||
return sib;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the argument `node` is a node whose tag is `tagName`.
|
||||
*
|
||||
* @param {node} node
|
||||
* The code to test. May be null.
|
||||
*
|
||||
* @param {string} tagName
|
||||
* The tag name to test against.
|
||||
*
|
||||
* @return {boolean}
|
||||
* True if the node is not null and has the tag name `tagName`,
|
||||
* otherwise false.
|
||||
*/
|
||||
function hasTagName(node, tagName) {
|
||||
return node && node.tagName &&
|
||||
node.tagName.toLowerCase() == tagName.toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an MDN page, get the "summary" portion.
|
||||
*
|
||||
* This is the textContent of the first non-whitespace
|
||||
* element in the #Summary section of the document.
|
||||
*
|
||||
* It's expected to be a <P> element.
|
||||
*
|
||||
* @param {Document} mdnDocument
|
||||
* The document in which to look for the "summary" section.
|
||||
*
|
||||
* @return {string}
|
||||
* The summary section as a string, or null if it could not be found.
|
||||
*/
|
||||
function getSummary(mdnDocument) {
|
||||
let summary = mdnDocument.getElementById("Summary");
|
||||
if (!hasTagName(summary, "H2")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let firstParagraph = nodeAfter(summary);
|
||||
if (!hasTagName(firstParagraph, "P")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return firstParagraph.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an MDN page, get the "syntax" portion.
|
||||
*
|
||||
* First we get the #Syntax section of the document. The syntax
|
||||
* section we want is somewhere inside there.
|
||||
*
|
||||
* If the page is in the old structure, then the *first two*
|
||||
* non-whitespace elements in the #Syntax section will be <PRE>
|
||||
* nodes, and the second of these will be the syntax section.
|
||||
*
|
||||
* If the page is in the new structure, then the only the *first*
|
||||
* non-whitespace element in the #Syntax section will be a <PRE>
|
||||
* node, and it will be the syntax section.
|
||||
*
|
||||
* @param {Document} mdnDocument
|
||||
* The document in which to look for the "syntax" section.
|
||||
*
|
||||
* @return {string}
|
||||
* The syntax section as a string, or null if it could not be found.
|
||||
*/
|
||||
function getSyntax(mdnDocument) {
|
||||
let syntax = mdnDocument.getElementById("Syntax");
|
||||
if (!hasTagName(syntax, "H2")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let firstParagraph = nodeAfter(syntax);
|
||||
if (!hasTagName(firstParagraph, "PRE")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let secondParagraph = nodeAfter(firstParagraph);
|
||||
if (hasTagName(secondParagraph, "PRE")) {
|
||||
return secondParagraph.textContent;
|
||||
}
|
||||
return firstParagraph.textContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a different URL for CSS docs pages. Used only for testing.
|
||||
*
|
||||
* @param {string} baseUrl
|
||||
* The baseURL to use.
|
||||
*/
|
||||
function setBaseCssDocsUrl(baseUrl) {
|
||||
PAGE_LINK_URL = baseUrl;
|
||||
XHR_CSS_URL = baseUrl;
|
||||
}
|
||||
|
||||
exports.setBaseCssDocsUrl = setBaseCssDocsUrl;
|
||||
@@ -1,39 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
.mdn-container {
|
||||
height: 300px;
|
||||
margin: 4px;
|
||||
overflow: auto;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mdn-container header,
|
||||
.mdn-container footer {
|
||||
flex: 1;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.mdn-property-info {
|
||||
flex: 10;
|
||||
padding: 0 1em;
|
||||
overflow: auto;
|
||||
transition: opacity 400ms ease-in;
|
||||
}
|
||||
|
||||
.mdn-syntax {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.devtools-throbber {
|
||||
align-self: center;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.mdn-visit-page {
|
||||
display: inline-block;
|
||||
padding: 1em 0;
|
||||
}
|
||||
@@ -20,7 +20,6 @@ DevToolsModules(
|
||||
'Graphs.js',
|
||||
'GraphsWorker.js',
|
||||
'LineGraphWidget.js',
|
||||
'MdnDocsWidget.js',
|
||||
'MountainGraphWidget.js',
|
||||
'SideMenuWidget.jsm',
|
||||
'SimpleListWidget.jsm',
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {HTMLTooltip} = require("devtools/client/shared/widgets/tooltip/HTMLTooltip");
|
||||
const {MdnDocsWidget} = require("devtools/client/shared/widgets/MdnDocsWidget");
|
||||
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
|
||||
const XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||||
|
||||
const TOOLTIP_WIDTH = 418;
|
||||
const TOOLTIP_HEIGHT = 308;
|
||||
|
||||
/**
|
||||
* Tooltip for displaying docs for CSS properties from MDN.
|
||||
*
|
||||
* @param {Document} toolboxDoc
|
||||
* The toolbox document to attach the CSS docs tooltip.
|
||||
*/
|
||||
function CssDocsTooltip(toolboxDoc) {
|
||||
this.tooltip = new HTMLTooltip(toolboxDoc, {
|
||||
type: "arrow",
|
||||
consumeOutsideClicks: true,
|
||||
autofocus: true,
|
||||
useXulWrapper: true,
|
||||
stylesheet: "chrome://devtools/content/shared/widgets/mdn-docs.css",
|
||||
});
|
||||
this.widget = this.setMdnDocsContent();
|
||||
this._onVisitLink = this._onVisitLink.bind(this);
|
||||
this.widget.on("visitlink", this._onVisitLink);
|
||||
|
||||
// Initialize keyboard shortcuts
|
||||
this.shortcuts = new KeyShortcuts({ window: this.tooltip.topWindow });
|
||||
this._onShortcut = this._onShortcut.bind(this);
|
||||
|
||||
this.shortcuts.on("Escape", this._onShortcut);
|
||||
}
|
||||
|
||||
CssDocsTooltip.prototype = {
|
||||
/**
|
||||
* Load CSS docs for the given property,
|
||||
* then display the tooltip.
|
||||
*/
|
||||
show: function (anchor, propertyName) {
|
||||
this.tooltip.once("shown", () => {
|
||||
this.widget.loadCssDocs(propertyName);
|
||||
});
|
||||
this.tooltip.show(anchor);
|
||||
},
|
||||
|
||||
hide: function () {
|
||||
this.tooltip.hide();
|
||||
},
|
||||
|
||||
_onShortcut: function (shortcut, event) {
|
||||
if (!this.tooltip.isVisible()) {
|
||||
return;
|
||||
}
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
this.hide();
|
||||
},
|
||||
|
||||
_onVisitLink: function () {
|
||||
this.hide();
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the content of this tooltip to the MDN docs widget. This is called when the
|
||||
* tooltip is first constructed.
|
||||
* The caller can use the MdnDocsWidget to update the tooltip's UI with new content
|
||||
* each time the tooltip is shown.
|
||||
*
|
||||
* @return {MdnDocsWidget} the created MdnDocsWidget instance.
|
||||
*/
|
||||
setMdnDocsContent: function () {
|
||||
let container = this.tooltip.doc.createElementNS(XHTML_NS, "div");
|
||||
container.setAttribute("class", "mdn-container theme-body");
|
||||
this.tooltip.setContent(container, {width: TOOLTIP_WIDTH, height: TOOLTIP_HEIGHT});
|
||||
return new MdnDocsWidget(container);
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.widget.off("visitlink", this._onVisitLink);
|
||||
this.widget.destroy();
|
||||
|
||||
this.shortcuts.destroy();
|
||||
this.tooltip.destroy();
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = CssDocsTooltip;
|
||||
@@ -4,7 +4,6 @@
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DevToolsModules(
|
||||
'CssDocsTooltip.js',
|
||||
'EventTooltipHelper.js',
|
||||
'HTMLTooltip.js',
|
||||
'ImageTooltipHelper.js',
|
||||
|
||||
@@ -188,7 +188,7 @@ body {
|
||||
}
|
||||
|
||||
#timeline-rate select.devtools-button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
text-align: center;
|
||||
font-family: inherit;
|
||||
color: var(--theme-body-color);
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
}
|
||||
|
||||
#developer-toolbar {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
min-height: 32px;
|
||||
background-color: var(--gcli-background-color);
|
||||
@@ -42,7 +42,7 @@
|
||||
}
|
||||
|
||||
#developer-toolbar > toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
margin: 0;
|
||||
@@ -122,7 +122,7 @@ html|*#gcli-output-frame {
|
||||
#gcli-tooltip {
|
||||
border-width: 0;
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node,
|
||||
@@ -140,7 +140,7 @@ html|*#gcli-output-frame {
|
||||
}
|
||||
|
||||
.gclitoolbar-input-node {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
color: var(--gcli-input-color);
|
||||
background-color: var(--gcli-input-background);
|
||||
background-repeat: no-repeat;
|
||||
|
||||
@@ -70,7 +70,7 @@ html|button, html|select {
|
||||
}
|
||||
|
||||
.devtools-autocomplete-listbox {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
background-color: transparent;
|
||||
border-width: 0px !important;
|
||||
margin: 0;
|
||||
@@ -243,7 +243,7 @@ checkbox:-moz-focusring {
|
||||
.devtools-menulist,
|
||||
.devtools-toolbarbutton,
|
||||
.devtools-button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
min-height: 18px;
|
||||
text-shadow: none;
|
||||
@@ -334,7 +334,7 @@ checkbox:-moz-focusring {
|
||||
|
||||
/* Menu button styles (eg. web console filters) */
|
||||
.devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
color: inherit;
|
||||
border-width: 0;
|
||||
-moz-box-orient: horizontal;
|
||||
@@ -351,7 +351,7 @@ checkbox:-moz-focusring {
|
||||
}
|
||||
|
||||
.devtools-menulist > .menulist-dropmarker {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
display: -moz-box;
|
||||
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
|
||||
-moz-box-align: center;
|
||||
@@ -360,7 +360,7 @@ checkbox:-moz-focusring {
|
||||
|
||||
.devtools-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
|
||||
.devtools-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
|
||||
-moz-box-align: center;
|
||||
padding: 0 3px;
|
||||
@@ -491,7 +491,7 @@ checkbox:-moz-focusring {
|
||||
* @TODO : Fix when https://bugzilla.mozilla.org/show_bug.cgi?id=1255116 lands
|
||||
*/
|
||||
.menu-filter-button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background: rgba(128,128,128,0.1);
|
||||
border: none;
|
||||
border-radius: 2px;
|
||||
@@ -519,7 +519,7 @@ checkbox:-moz-focusring {
|
||||
.devtools-textinput,
|
||||
.devtools-searchinput,
|
||||
.devtools-filterinput {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
margin: 1px 3px;
|
||||
border: 1px solid;
|
||||
border-radius: 2px;
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
/* Firebug theme uses breakpoint icon istead of a checkbox */
|
||||
|
||||
.theme-firebug #sources-pane .dbg-breakpoint-checkbox .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: url(chrome://devtools/skin/images/firebug/breakpoint.svg) no-repeat 50% 50%;
|
||||
}
|
||||
@@ -326,7 +326,7 @@
|
||||
}
|
||||
|
||||
.dbg-expression-button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: none;
|
||||
text-decoration: underline;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
.devtools-eyedropper-panel {
|
||||
pointer-events: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
width: 156px;
|
||||
height: 120px;
|
||||
background-color: transparent;
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
well as any overflow: scroll elements within the page, while excluding
|
||||
<select>. */
|
||||
*|*:not(html|select) > scrollbar {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
@@ -37,14 +37,14 @@
|
||||
|
||||
*|*:not(html|select) > scrollbar thumb {
|
||||
background-color: rgba(170, 170, 170, .2) !important; /* --toolbar-tab-hover */
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
border-width: 0px !important;
|
||||
border-radius: 3px !important;
|
||||
}
|
||||
|
||||
*|*:root[platform="mac"] > scrollbar slider,
|
||||
*|*:root[platform="mac"] *|*:not(html|select) > scrollbar slider {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
}
|
||||
|
||||
*|*:root[platform="win"] > scrollbar scrollbarbutton,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
well as any overflow: scroll elements within the page, while excluding
|
||||
<select>. */
|
||||
*|*:not(html|select) > scrollbar {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
@@ -31,11 +31,11 @@
|
||||
}
|
||||
|
||||
*|*:not(html|select) > scrollbar slider {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
}
|
||||
|
||||
*|*:not(html|select) > scrollbar thumb {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
border-width: 0px !important;
|
||||
border-radius: 3px !important;
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
}
|
||||
|
||||
.requests-menu-header-button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: transparent;
|
||||
border-image: linear-gradient(transparent 15%,
|
||||
var(--theme-splitter-color) 15%,
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
}
|
||||
|
||||
.arrow {
|
||||
-moz-appearance: treetwisty;
|
||||
appearance: treetwisty;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.arrow[open] {
|
||||
-moz-appearance: treetwistyopen;
|
||||
appearance: treetwistyopen;
|
||||
}
|
||||
|
||||
.arrow[invisible] {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
}
|
||||
|
||||
.devtools-responsiveui-toolbar {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
/* text color is textColor from dark theme, since no theme is applied to
|
||||
* the responsive toolbar.
|
||||
@@ -29,7 +29,7 @@
|
||||
}
|
||||
|
||||
.devtools-responsiveui-textinput {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background: #333;
|
||||
color: #fff;
|
||||
border: 1px solid #111;
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
.devtools-responsiveui-menulist,
|
||||
.devtools-responsiveui-toolbarbutton {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
-moz-box-align: center;
|
||||
min-width: 32px;
|
||||
min-height: 22px;
|
||||
@@ -60,12 +60,12 @@
|
||||
}
|
||||
|
||||
.devtools-responsiveui-menulist .menulist-editable-box {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.devtools-responsiveui-menulist html|*.menulist-editable-input {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
color: inherit;
|
||||
text-align: center;
|
||||
}
|
||||
@@ -124,7 +124,7 @@
|
||||
}
|
||||
|
||||
.devtools-responsiveui-menulist > .menulist-dropmarker {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
display: -moz-box;
|
||||
background-color: transparent;
|
||||
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
|
||||
@@ -134,7 +134,7 @@
|
||||
}
|
||||
|
||||
.devtools-responsiveui-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
color: inherit;
|
||||
border-width: 0;
|
||||
border-inline-end: 1px solid hsla(210,8%,5%,.45);
|
||||
@@ -152,7 +152,7 @@
|
||||
|
||||
.devtools-responsiveui-toolbarbutton[type=menu] > .toolbarbutton-menu-dropmarker,
|
||||
.devtools-responsiveui-toolbarbutton[type=menu-button] > .toolbarbutton-menubutton-dropmarker {
|
||||
-moz-appearance: none !important;
|
||||
appearance: none !important;
|
||||
list-style-image: url("chrome://devtools/skin/images/dropmarker.svg");
|
||||
-moz-box-align: center;
|
||||
padding: 0 3px;
|
||||
@@ -266,7 +266,7 @@
|
||||
}
|
||||
|
||||
.devtools-responsiveui-hardware-buttons {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 20px;
|
||||
|
||||
border: 1px solid #FFFFFF;
|
||||
@@ -288,7 +288,7 @@
|
||||
|
||||
.devtools-responsiveui-sleep-button {
|
||||
-moz-user-focus: ignore;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
/* compensate browserStack top padding */
|
||||
margin-top: -67px;
|
||||
margin-right: 10px;
|
||||
@@ -316,7 +316,7 @@
|
||||
.devtools-responsiveui-volume-up-button,
|
||||
.devtools-responsiveui-volume-down-button {
|
||||
-moz-user-focus: ignore;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: 1px solid red;
|
||||
min-width: 8px;
|
||||
height: 40px;
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
opacity: 0;
|
||||
transition: opacity .15s ease-out 0s;
|
||||
}
|
||||
@@ -43,7 +43,7 @@
|
||||
}
|
||||
|
||||
.side-menu-widget-item-checkbox .checkbox-check {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-image: url(images/item-toggle.svg);
|
||||
background-color: transparent;
|
||||
width: 16px;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
.devtools-horizontal-splitter,
|
||||
.devtools-side-splitter {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-image: none;
|
||||
border: 0;
|
||||
border-style: solid;
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
/* Toolbars */
|
||||
.devtools-toolbar,
|
||||
.devtools-sidebar-tabs tabs {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
border-width: 0;
|
||||
border-bottom-width: 1px;
|
||||
@@ -91,13 +91,13 @@
|
||||
|
||||
/* In-tools sidebar */
|
||||
.devtools-sidebar-tabs {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs > tabpanels {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
@@ -116,7 +116,7 @@
|
||||
}
|
||||
|
||||
.devtools-sidebar-alltabs {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
padding: 0 4px;
|
||||
@@ -136,7 +136,7 @@
|
||||
}
|
||||
|
||||
.devtools-sidebar-tabs tabs > tab {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
/* We want to match the height of a toolbar with a toolbarbutton
|
||||
* First, we need to replicated the padding of toolbar (4px),
|
||||
* then we need to take the border of the buttons into account (1px).
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
/* Toolbox tabbar */
|
||||
|
||||
.devtools-tabbar {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
min-height: 24px;
|
||||
border: 0px solid;
|
||||
border-bottom-width: 1px;
|
||||
@@ -67,7 +67,7 @@
|
||||
/* Toolbox tabs */
|
||||
|
||||
.devtools-tab {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
-moz-binding: url("chrome://global/content/bindings/general.xml#control-item");
|
||||
-moz-box-align: center;
|
||||
min-width: 32px;
|
||||
@@ -224,7 +224,7 @@
|
||||
|
||||
#toolbox-controls > button,
|
||||
#toolbox-dock-buttons > button {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
border: none;
|
||||
margin: 0 4px;
|
||||
min-width: 16px;
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
}
|
||||
|
||||
.tooltip-xul-wrapper {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
overflow: visible;
|
||||
border-style: none;
|
||||
|
||||
@@ -125,7 +125,7 @@ text {
|
||||
.web-audio-inspector .error {
|
||||
background-image: url(images/alerticon-warning.png);
|
||||
background-size: 13px 12px;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
opacity: 0;
|
||||
transition: opacity .5s ease-out 0s;
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ a {
|
||||
padding: 0;
|
||||
padding-inline-start: 20px;
|
||||
margin: 0;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
.scrollbutton-up,
|
||||
.scrollbutton-down {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
border: none;
|
||||
@@ -133,7 +133,7 @@
|
||||
|
||||
.scrollbutton-up > .toolbarbutton-icon,
|
||||
.scrollbutton-down > .toolbarbutton-icon {
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
width: 7px;
|
||||
height: 16px;
|
||||
background-size: 14px 16px;
|
||||
@@ -190,7 +190,7 @@
|
||||
|
||||
.breadcrumbs-widget-item {
|
||||
background-color: transparent;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
min-height: 24px;
|
||||
min-width: 65px;
|
||||
margin: 0;
|
||||
|
||||
@@ -3381,7 +3381,9 @@ exports.CSS_PROPERTIES = {
|
||||
"word-spacing",
|
||||
"overflow-wrap",
|
||||
"writing-mode",
|
||||
"z-index"
|
||||
"z-index",
|
||||
"overflow-block",
|
||||
"overflow-inline"
|
||||
],
|
||||
"supports": [
|
||||
1,
|
||||
@@ -3411,7 +3413,6 @@ exports.CSS_PROPERTIES = {
|
||||
"-moz-grid-line",
|
||||
"-moz-groupbox",
|
||||
"-moz-gtk-info-bar",
|
||||
"clip",
|
||||
"-moz-image-rect",
|
||||
"-moz-inline-box",
|
||||
"-moz-inline-grid",
|
||||
@@ -3502,6 +3503,7 @@ exports.CSS_PROPERTIES = {
|
||||
"checkbox-container",
|
||||
"checkbox-label",
|
||||
"checkmenuitem",
|
||||
"clip",
|
||||
"clone",
|
||||
"collapse",
|
||||
"color",
|
||||
@@ -7221,6 +7223,26 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"inset-block": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"inset-block-start",
|
||||
"inset-block-end"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
8
|
||||
],
|
||||
"values": [
|
||||
"-moz-calc",
|
||||
"auto",
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"inset-block-end": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@@ -7259,6 +7281,26 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"inset-inline": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"inset-inline-start",
|
||||
"inset-inline-end"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
8
|
||||
],
|
||||
"values": [
|
||||
"-moz-calc",
|
||||
"auto",
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"inset-inline-end": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@@ -8568,6 +8610,42 @@ exports.CSS_PROPERTIES = {
|
||||
"visible"
|
||||
]
|
||||
},
|
||||
"overflow-block": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"overflow-block"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"clip",
|
||||
"hidden",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"scroll",
|
||||
"unset",
|
||||
"visible"
|
||||
]
|
||||
},
|
||||
"overflow-inline": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
"overflow-inline"
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"clip",
|
||||
"hidden",
|
||||
"inherit",
|
||||
"initial",
|
||||
"revert",
|
||||
"scroll",
|
||||
"unset",
|
||||
"visible"
|
||||
]
|
||||
},
|
||||
"overflow-wrap": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
|
||||
@@ -65,7 +65,6 @@ exports.devtoolsModules = [
|
||||
"devtools/shared/gcli/commands/inject",
|
||||
"devtools/shared/gcli/commands/jsb",
|
||||
"devtools/shared/gcli/commands/listen",
|
||||
"devtools/shared/gcli/commands/mdn",
|
||||
"devtools/shared/gcli/commands/measure",
|
||||
"devtools/shared/gcli/commands/media",
|
||||
"devtools/shared/gcli/commands/pagemod",
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const l10n = require("gcli/l10n");
|
||||
|
||||
var MdnDocsWidget;
|
||||
try {
|
||||
MdnDocsWidget = require("devtools/client/shared/widgets/MdnDocsWidget");
|
||||
} catch (e) {
|
||||
// DevTools MdnDocsWidget only available in Firefox Desktop
|
||||
}
|
||||
|
||||
exports.items = [{
|
||||
name: "mdn",
|
||||
description: l10n.lookup("mdnDesc")
|
||||
}, {
|
||||
item: "command",
|
||||
runAt: "client",
|
||||
name: "mdn css",
|
||||
description: l10n.lookup("mdnCssDesc"),
|
||||
returnType: "cssPropertyOutput",
|
||||
params: [{
|
||||
name: "property",
|
||||
type: { name: "string" },
|
||||
defaultValue: null,
|
||||
description: l10n.lookup("mdnCssProp")
|
||||
}],
|
||||
exec: function(args) {
|
||||
if (!MdnDocsWidget) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return MdnDocsWidget.getCssDocs(args.property).then(result => {
|
||||
return {
|
||||
data: result,
|
||||
url: MdnDocsWidget.PAGE_LINK_URL + args.property,
|
||||
property: args.property
|
||||
};
|
||||
}, error => {
|
||||
return { error, property: args.property };
|
||||
});
|
||||
}
|
||||
}, {
|
||||
item: "converter",
|
||||
from: "cssPropertyOutput",
|
||||
to: "dom",
|
||||
exec: function(result, context) {
|
||||
let propertyName = result.property;
|
||||
|
||||
let document = context.document;
|
||||
let root = document.createElement("div");
|
||||
|
||||
if (result.error) {
|
||||
// The css property specified doesn't exist.
|
||||
root.appendChild(document.createTextNode(
|
||||
l10n.lookupFormat("mdnCssPropertyNotFound", [ propertyName ]) +
|
||||
" (" + result.error + ")"));
|
||||
} else {
|
||||
let title = document.createElement("h2");
|
||||
title.textContent = propertyName;
|
||||
root.appendChild(title);
|
||||
|
||||
let link = document.createElement("p");
|
||||
link.classList.add("gcli-mdn-url");
|
||||
link.textContent = l10n.lookup("mdnCssVisitPage");
|
||||
root.appendChild(link);
|
||||
|
||||
link.addEventListener("click", () => {
|
||||
let mainWindow = context.environment.chromeWindow;
|
||||
mainWindow.openUILinkIn(result.url, "tab");
|
||||
});
|
||||
|
||||
let summary = document.createElement("p");
|
||||
summary.textContent = result.data.summary;
|
||||
root.appendChild(summary);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
}];
|
||||
@@ -16,7 +16,6 @@ DevToolsModules(
|
||||
'inject.js',
|
||||
'jsb.js',
|
||||
'listen.js',
|
||||
'mdn.js',
|
||||
'measure.js',
|
||||
'media.js',
|
||||
'pagemod.js',
|
||||
|
||||
@@ -1457,24 +1457,6 @@ folderInvalidPath=Please enter a valid path
|
||||
# The argument (%1$S) is the folder path.
|
||||
folderOpenDirResult=Opened %1$S
|
||||
|
||||
# LOCALIZATION NOTE (mdnDesc) A very short string used to describe the
|
||||
# use of 'mdn' command.
|
||||
mdnDesc=Retrieve documentation from MDN
|
||||
# LOCALIZATION NOTE (mdnCssDesc) A very short string used to describe the
|
||||
# result of the 'mdn css' command.
|
||||
mdnCssDesc=Retrieve documentation about a given CSS property name from MDN
|
||||
# LOCALIZATION NOTE (mdnCssProp) String used to describe the 'property name'
|
||||
# parameter used in the 'mdn css' command.
|
||||
mdnCssProp=Property name
|
||||
# LOCALIZATION NOTE (mdnCssPropertyNotFound) String used to display an error in
|
||||
# the result of the 'mdn css' command. Errors occur when a given CSS property
|
||||
# wasn't found on MDN. The %1$S parameter will be replaced with the name of the
|
||||
# CSS property.
|
||||
mdnCssPropertyNotFound=MDN documentation for the CSS property ‘%1$S’ was not found.
|
||||
# LOCALIZATION NOTE (mdnCssVisitPage) String used as the label of a link to the
|
||||
# MDN page for a given CSS property.
|
||||
mdnCssVisitPage=Visit MDN page
|
||||
|
||||
# LOCALIZATION NOTE (security)
|
||||
securityPrivacyDesc=Display supported security and privacy features
|
||||
securityManual=Commands to list and get suggestions about security features for the current domain.
|
||||
|
||||
@@ -130,14 +130,6 @@ styleinspector.contextmenu.toggleOrigSources=Show Original Sources
|
||||
# the rule view context menu "Show original sources" entry.
|
||||
styleinspector.contextmenu.toggleOrigSources.accessKey=O
|
||||
|
||||
# LOCALIZATION NOTE (styleinspector.contextmenu.showMdnDocs): Text displayed in the rule view
|
||||
# context menu to display docs from MDN for an item.
|
||||
styleinspector.contextmenu.showMdnDocs=Show MDN Docs
|
||||
|
||||
# LOCALIZATION NOTE (styleinspector.contextmenu.showMdnDocs.accessKey): Access key for
|
||||
# the rule view context menu "Show MDN docs" entry.
|
||||
styleinspector.contextmenu.showMdnDocs.accessKey=D
|
||||
|
||||
# LOCALIZATION NOTE (styleinspector.contextmenu.addNewRule): Text displayed in the
|
||||
# rule view context menu for adding a new rule to the element.
|
||||
# This should match inspector.addRule.tooltip in inspector.properties
|
||||
|
||||
@@ -838,6 +838,12 @@ EffectCompositor::AnimationStyleRuleProcessor::MediumFeaturesChanged(
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>*
|
||||
EffectCompositor::AnimationStyleRuleProcessor::GetChildRuleProcessors()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
EffectCompositor::AnimationStyleRuleProcessor::RulesMatching(
|
||||
ElementRuleProcessorData* aData)
|
||||
|
||||
@@ -278,6 +278,8 @@ private:
|
||||
AttributeRuleProcessorData* aData,
|
||||
RestyleHintData& aRestyleHintDataResult) override;
|
||||
bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
|
||||
nsTArray<nsCOMPtr<nsIStyleRuleProcessor>>* GetChildRuleProcessors()
|
||||
override;
|
||||
void RulesMatching(ElementRuleProcessorData* aData) override;
|
||||
void RulesMatching(PseudoElementRuleProcessorData* aData) override;
|
||||
void RulesMatching(AnonBoxRuleProcessorData* aData) override;
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
|
||||
#include "mozilla/css/Declaration.h"
|
||||
#include "nsCSSRuleProcessor.h"
|
||||
#include "nsCSSRuleUtils.h"
|
||||
#include "nsRuleProcessorData.h"
|
||||
#include "nsTextNode.h"
|
||||
|
||||
@@ -3424,9 +3424,9 @@ Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
|
||||
matchingContext.AddScopeElement(this);
|
||||
for (nsINode* node = this; node; node = node->GetParentNode()) {
|
||||
if (node->IsElement() &&
|
||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(node->AsElement(),
|
||||
matchingContext,
|
||||
selectorList)) {
|
||||
nsCSSRuleUtils::RestrictedSelectorListMatches(node->AsElement(),
|
||||
matchingContext,
|
||||
selectorList)) {
|
||||
return node->AsElement();
|
||||
}
|
||||
}
|
||||
@@ -3450,9 +3450,9 @@ Element::Matches(const nsAString& aSelector, ErrorResult& aError)
|
||||
TreeMatchContext::eNeverMatchVisited);
|
||||
matchingContext.SetHasSpecifiedScope();
|
||||
matchingContext.AddScopeElement(this);
|
||||
return nsCSSRuleProcessor::RestrictedSelectorListMatches(this,
|
||||
matchingContext,
|
||||
selectorList);
|
||||
return nsCSSRuleUtils::RestrictedSelectorListMatches(this,
|
||||
matchingContext,
|
||||
selectorList);
|
||||
}
|
||||
|
||||
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
|
||||
|
||||
@@ -1603,6 +1603,16 @@ private:
|
||||
|
||||
// Data members
|
||||
EventStates mState;
|
||||
|
||||
public:
|
||||
// Public helper to add or remove event states
|
||||
void SetEventState(mozilla::EventStates aState, bool aAdd) {
|
||||
if (aAdd) {
|
||||
this->AddStates(aState);
|
||||
} else {
|
||||
this->RemoveStates(aState);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class RemoveFromBindingManagerRunnable : public mozilla::Runnable
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "VisualViewport.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIDocShell.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
VisualViewport::VisualViewport(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
{
|
||||
}
|
||||
|
||||
VisualViewport::VisualViewport(nsIGlobalObject* aGlobal)
|
||||
: DOMEventTargetHelper(aGlobal)
|
||||
{
|
||||
}
|
||||
|
||||
VisualViewport::~VisualViewport()
|
||||
{
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
JSObject*
|
||||
VisualViewport::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return VisualViewportBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
/* XXXMC: We are effectively getting the size from the root scrollframe of the content
|
||||
* and the scale from our DPP resolution.
|
||||
* Since we are only on desktop, by definition have full view size (no "notch" or
|
||||
* other mobile "don't touch" areas), we are hard-coding:
|
||||
* - VisualViewportOffset = (0,0)
|
||||
* - PageLeft/PageTop = 0.0
|
||||
* - OffsetLeft/OffsetTop = 0.0
|
||||
*/
|
||||
|
||||
CSSSize
|
||||
VisualViewport::VisualViewportSize() const
|
||||
{
|
||||
CSSSize size = CSSSize(0,0);
|
||||
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
|
||||
if (sf) {
|
||||
size = CSSRect::FromAppUnits(sf->GetScrollPortRect().Size());
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
double
|
||||
VisualViewport::Width() const
|
||||
{
|
||||
CSSSize size = VisualViewportSize();
|
||||
return size.width;
|
||||
}
|
||||
|
||||
double
|
||||
VisualViewport::Height() const
|
||||
{
|
||||
CSSSize size = VisualViewportSize();
|
||||
return size.height;
|
||||
}
|
||||
|
||||
double
|
||||
VisualViewport::Scale() const
|
||||
{
|
||||
double scale = 1;
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
scale = presShell->GetResolution();
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
||||
CSSPoint
|
||||
VisualViewport::VisualViewportOffset() const
|
||||
{
|
||||
CSSPoint offset = CSSPoint(0,0);
|
||||
return offset;
|
||||
}
|
||||
|
||||
CSSPoint
|
||||
VisualViewport::LayoutViewportOffset() const
|
||||
{
|
||||
CSSPoint offset = CSSPoint(0,0);
|
||||
|
||||
nsIPresShell* presShell = GetPresShell();
|
||||
if (presShell) {
|
||||
nsIScrollableFrame* sf = presShell->GetRootScrollFrameAsScrollable();
|
||||
if (sf) {
|
||||
offset = CSSPoint::FromAppUnits(sf->GetScrollPosition());
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
double
|
||||
VisualViewport::PageLeft() const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double
|
||||
VisualViewport::PageTop() const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double
|
||||
VisualViewport::OffsetLeft() const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double
|
||||
VisualViewport::OffsetTop() const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
nsIPresShell*
|
||||
VisualViewport::GetPresShell() const
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
|
||||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIDocShell* docShell = window->GetDocShell();
|
||||
if (!docShell) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return docShell->GetPresShell();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#ifndef mozilla_dom_VisualViewport_h
|
||||
#define mozilla_dom_VisualViewport_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/dom/VisualViewportBinding.h"
|
||||
#include "Units.h"
|
||||
#include "nsIPresShell.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/* Visual Viewport API spec: https://wicg.github.io/visual-viewport/#the-visualviewport-interface */
|
||||
class VisualViewport final: public mozilla::DOMEventTargetHelper
|
||||
{
|
||||
|
||||
public:
|
||||
explicit VisualViewport(nsPIDOMWindowInner* aWindow);
|
||||
explicit VisualViewport(nsIGlobalObject* aGlobal);
|
||||
|
||||
double OffsetLeft() const;
|
||||
double OffsetTop() const;
|
||||
double PageLeft() const;
|
||||
double PageTop() const;
|
||||
double Width() const;
|
||||
double Height() const;
|
||||
double Scale() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
private:
|
||||
virtual ~VisualViewport();
|
||||
|
||||
CSSSize VisualViewportSize() const;
|
||||
CSSPoint VisualViewportOffset() const;
|
||||
CSSPoint LayoutViewportOffset() const;
|
||||
nsIPresShell* GetPresShell() const;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_VisualViewport_h
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "mozilla/dom/MessageEventBinding.h"
|
||||
#include "mozilla/dom/nsCSPContext.h"
|
||||
#include "mozilla/dom/nsCSPUtils.h"
|
||||
#include "mozilla/dom/nsMixedContentBlocker.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/WorkerPrivate.h"
|
||||
#include "mozilla/dom/WorkerRunnable.h"
|
||||
@@ -1604,10 +1605,10 @@ WebSocketImpl::Init(JSContext* aCx,
|
||||
mInnerWindowID);
|
||||
}
|
||||
|
||||
// Don't allow https:// to open ws://
|
||||
// Don't allow https:// to open ws://, except when explicitly preffed or a loopback address.
|
||||
if (!mIsServerSide && !mSecure &&
|
||||
!Preferences::GetBool("network.websocket.allowInsecureFromHTTPS",
|
||||
false)) {
|
||||
!Preferences::GetBool("network.websocket.allowInsecureFromHTTPS", false) &&
|
||||
!nsMixedContentBlocker::IsPotentiallyTrustworthyLoopbackHost(mAsciiHost)) {
|
||||
// Confirmed we are opening plain ws:// and want to prevent this from a
|
||||
// secure context (e.g. https).
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
|
||||
@@ -217,6 +217,7 @@ EXPORTS.mozilla.dom += [
|
||||
'Timeout.h',
|
||||
'TimeoutHandler.h',
|
||||
'TreeWalker.h',
|
||||
'VisualViewport.h',
|
||||
'WebKitCSSMatrix.h',
|
||||
'WebSocket.h',
|
||||
'WindowOrientationObserver.h',
|
||||
@@ -365,6 +366,7 @@ UNIFIED_SOURCES += [
|
||||
'TimeoutHandler.cpp',
|
||||
'TimerClamping.cpp',
|
||||
'TreeWalker.cpp',
|
||||
'VisualViewport.cpp',
|
||||
'WebKitCSSMatrix.cpp',
|
||||
'WebSocket.cpp',
|
||||
'WindowNamedPropertiesHandler.cpp',
|
||||
|
||||
@@ -4061,3 +4061,35 @@ nsTranslationNodeList::GetLength(uint32_t* aRetVal)
|
||||
*aRetVal = mLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::AddElementEventState(nsIDOMElement* aElement, uint64_t aState)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aElement);
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
if (!content) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
mozilla::dom::Element* element = static_cast<mozilla::dom::Element*>(content.get());
|
||||
if (!element) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
element->SetEventState(mozilla::EventStates(aState), true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::RemoveElementEventState(nsIDOMElement* aElement, uint64_t aState)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aElement);
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
|
||||
if (!content) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
mozilla::dom::Element* element = static_cast<mozilla::dom::Element*>(content.get());
|
||||
if (!element) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
element->SetEventState(mozilla::EventStates(aState), false);
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -101,6 +101,8 @@ GK_ATOM(animations, "animations")
|
||||
GK_ATOM(anonid, "anonid")
|
||||
GK_ATOM(anonlocation, "anonlocation")
|
||||
GK_ATOM(any, "any")
|
||||
GK_ATOM(any_hover, "any-hover")
|
||||
GK_ATOM(any_pointer, "any-pointer")
|
||||
GK_ATOM(applet, "applet")
|
||||
GK_ATOM(applyImports, "apply-imports")
|
||||
GK_ATOM(applyTemplates, "apply-templates")
|
||||
@@ -1533,6 +1535,7 @@ GK_ATOM(patternContentUnits, "patternContentUnits")
|
||||
GK_ATOM(patternTransform, "patternTransform")
|
||||
GK_ATOM(patternUnits, "patternUnits")
|
||||
GK_ATOM(pc, "pc")
|
||||
GK_ATOM(pointer, "pointer")
|
||||
GK_ATOM(pointer_events, "pointer-events")
|
||||
GK_ATOM(points, "points")
|
||||
GK_ATOM(pointsAtX, "pointsAtX")
|
||||
@@ -2240,6 +2243,7 @@ GK_ATOM(scrollbar_end_forward, "scrollbar-end-forward")
|
||||
GK_ATOM(scrollbar_thumb_proportional, "scrollbar-thumb-proportional")
|
||||
GK_ATOM(overlay_scrollbars, "overlay-scrollbars")
|
||||
GK_ATOM(prefers_color_scheme, "prefers-color-scheme")
|
||||
GK_ATOM(prefers_reduced_motion, "prefers-reduced-motion")
|
||||
GK_ATOM(windows_accent_color_applies, "windows-accent-color-applies")
|
||||
GK_ATOM(windows_accent_color_is_dark, "windows-accent-color-is-dark")
|
||||
GK_ATOM(windows_default_theme, "windows-default-theme")
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "mozilla/dom/StorageEventBinding.h"
|
||||
#include "mozilla/dom/Timeout.h"
|
||||
#include "mozilla/dom/TimeoutHandler.h"
|
||||
#include "mozilla/dom/VisualViewport.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
#include "nsDOMOfflineResourceList.h"
|
||||
#include "nsError.h"
|
||||
@@ -4154,6 +4155,16 @@ nsGlobalWindow::GetNavigator()
|
||||
return navigator;
|
||||
}
|
||||
|
||||
VisualViewport*
|
||||
nsGlobalWindow::VisualViewport()
|
||||
{
|
||||
if (!mVisualViewport) {
|
||||
mVisualViewport = new mozilla::dom::VisualViewport(this);
|
||||
}
|
||||
|
||||
return mVisualViewport;
|
||||
}
|
||||
|
||||
nsScreen*
|
||||
nsGlobalWindow::GetScreen(ErrorResult& aError)
|
||||
{
|
||||
|
||||
@@ -134,6 +134,7 @@ class SpeechSynthesis;
|
||||
class TabGroup;
|
||||
class Timeout;
|
||||
class U2F;
|
||||
class VisualViewport;
|
||||
class WakeLock;
|
||||
struct WindowPostMessageOptions;
|
||||
class Worklet;
|
||||
@@ -974,6 +975,7 @@ public:
|
||||
already_AddRefed<nsICSSDeclaration>
|
||||
GetComputedStyle(mozilla::dom::Element& aElt, const nsAString& aPseudoElt,
|
||||
mozilla::ErrorResult& aError) override;
|
||||
mozilla::dom::VisualViewport* VisualViewport();
|
||||
already_AddRefed<mozilla::dom::MediaQueryList> MatchMediaOuter(const nsAString& aQuery);
|
||||
already_AddRefed<mozilla::dom::MediaQueryList> MatchMedia(const nsAString& aQuery,
|
||||
mozilla::ErrorResult& aError);
|
||||
@@ -1854,6 +1856,8 @@ protected:
|
||||
RefPtr<nsHistory> mHistory;
|
||||
RefPtr<mozilla::dom::CustomElementRegistry> mCustomElements;
|
||||
|
||||
RefPtr<mozilla::dom::VisualViewport> mVisualViewport;
|
||||
|
||||
// These member variables are used on both inner and the outer windows.
|
||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "mozilla/HTMLEditor.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
@@ -91,7 +92,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "prprf.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsCSSRuleProcessor.h"
|
||||
#include "nsCSSRuleUtils.h"
|
||||
#include "nsCSSParser.h"
|
||||
#include "HTMLLegendElement.h"
|
||||
#include "nsWrapperCacheInlines.h"
|
||||
@@ -2912,9 +2913,9 @@ FindMatchingElementsWithId(const nsAString& aId, nsINode* aRoot,
|
||||
// We have an element with the right id and it's a strict descendant
|
||||
// of aRoot. Make sure it really matches the selector.
|
||||
if (!aMatchInfo ||
|
||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(element,
|
||||
aMatchInfo->mMatchContext,
|
||||
aMatchInfo->mSelectorList)) {
|
||||
nsCSSRuleUtils::RestrictedSelectorListMatches(element,
|
||||
aMatchInfo->mMatchContext,
|
||||
aMatchInfo->mSelectorList)) {
|
||||
aList.AppendElement(element);
|
||||
if (onlyFirstMatch) {
|
||||
return;
|
||||
@@ -2965,9 +2966,9 @@ FindMatchingElements(nsINode* aRoot, nsCSSSelectorList* aSelectorList, T &aList,
|
||||
cur;
|
||||
cur = cur->GetNextNode(aRoot)) {
|
||||
if (cur->IsElement() &&
|
||||
nsCSSRuleProcessor::RestrictedSelectorListMatches(cur->AsElement(),
|
||||
matchingContext,
|
||||
aSelectorList)) {
|
||||
nsCSSRuleUtils::RestrictedSelectorListMatches(cur->AsElement(),
|
||||
matchingContext,
|
||||
aSelectorList)) {
|
||||
if (onlyFirstMatch) {
|
||||
aList.AppendElement(cur->AsElement());
|
||||
return;
|
||||
|
||||
@@ -2336,28 +2336,31 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
}
|
||||
}
|
||||
|
||||
// Don't allow view-source scheme.
|
||||
// view-source is the only scheme to which this applies at the moment due to
|
||||
// potential timing attacks to read data from cross-origin documents. If this
|
||||
// widens we should add a protocol flag for whether the scheme is only allowed
|
||||
// in top and use something like nsNetUtil::NS_URIChainHasFlags.
|
||||
if (mType != eType_Null) {
|
||||
nsCOMPtr<nsIURI> tempURI = mURI;
|
||||
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(tempURI);
|
||||
while (nestedURI) {
|
||||
// view-source should always be an nsINestedURI, loop and check the
|
||||
// scheme on this and all inner URIs that are also nested URIs.
|
||||
bool isViewSource = false;
|
||||
rv = tempURI->SchemeIs("view-source", &isViewSource);
|
||||
if (NS_FAILED(rv) || isViewSource) {
|
||||
LOG(("OBJLC [%p]: Blocking as effective URI has view-source scheme",
|
||||
this));
|
||||
mType = eType_Null;
|
||||
// https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element
|
||||
// requires that `embed` and `object` go through `Fetch` with mode=navigate,
|
||||
// see 1.3.5. This will in https://fetch.spec.whatwg.org/#fetching plumb us
|
||||
// through to https://fetch.spec.whatwg.org/#concept-main-fetch where in step
|
||||
// 12 a switch is performed. Since `object` and `embed` have mode=navigate the
|
||||
// result of https://fetch.spec.whatwg.org/#concept-scheme-fetch will decide
|
||||
// if main fetch proceeds. We short-circuit that scheme-fetch here, inspecting
|
||||
// if the scheme of `mURI` is one that would return a network error. The
|
||||
// following schemes are allowed through in scheme fetch:
|
||||
// "about", "blob", "data", "file", "http", "https".
|
||||
//
|
||||
// Some accessibility tests use our internal "chrome" scheme.
|
||||
if (mType != eType_Null && mURI) {
|
||||
bool isCandidate = false;
|
||||
for (const auto& candidate :
|
||||
{"about", "blob", "chrome", "data", "file", "http", "https"}) {
|
||||
rv = mURI->SchemeIs(candidate, &isCandidate);
|
||||
if (NS_SUCCEEDED(rv) && isCandidate) {
|
||||
break;
|
||||
}
|
||||
|
||||
nestedURI->GetInnerURI(getter_AddRefs(tempURI));
|
||||
nestedURI = do_QueryInterface(tempURI);
|
||||
}
|
||||
if (!isCandidate) {
|
||||
LOG(("OBJLC [%p]: Blocking as effective URI does not have an allowed scheme",
|
||||
this));
|
||||
mType = eType_Null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1145,6 +1145,10 @@ DOMInterfaces = {
|
||||
'wrapperCache': False,
|
||||
},
|
||||
|
||||
'VisualViewport': {
|
||||
'nativeType': 'mozilla::dom::VisualViewport',
|
||||
},
|
||||
|
||||
'VTTCue': {
|
||||
'nativeType': 'mozilla::dom::TextTrackCue'
|
||||
},
|
||||
|
||||
@@ -111,3 +111,4 @@ MSG_DEF(MSG_PMO_INVALID_MEMBERS, 0, JSEXN_TYPEERR, "PerformanceMeasureOptions ca
|
||||
MSG_DEF(MSG_PMO_CONSTRUCTOR_INACCESSIBLE, 0, JSEXN_TYPEERR, "Can't access PerformanceMark constructor, performance is null.")
|
||||
MSG_DEF(MSG_PMO_UNEXPECTED_START_TIME, 0, JSEXN_TYPEERR, "Expected startTime >= 0.")
|
||||
MSG_DEF(MSG_PMO_INVALID_ATTR_FOR_NON_GLOBAL, 1, JSEXN_TYPEERR, "Cannot get PerformanceTiming attribute values for non-Window global object. Given: {0}.")
|
||||
MSG_DEF(MSG_NOT_SUBMIT_BUTTON, 0, JSEXN_TYPEERR, "The submitter is not a submit button.")
|
||||
@@ -308,6 +308,17 @@ TexUnpackBlob::ConvertIfNeeded(WebGLContext* webgl, const char* funcName,
|
||||
if (!rowLength || !rowCount)
|
||||
return true;
|
||||
|
||||
auto minSrcStride =
|
||||
CheckedInt<size_t>(WebGLTexelConversions::TexelBytesForFormat(srcFormat)) * rowLength;
|
||||
auto minDstStride =
|
||||
CheckedInt<size_t>(WebGLTexelConversions::TexelBytesForFormat(dstFormat)) * rowLength;
|
||||
if (srcStride <= 0 || dstStride <= 0 || !minSrcStride.isValid() ||
|
||||
!minDstStride.isValid() || size_t(srcStride) < minSrcStride.value() ||
|
||||
size_t(dstStride) < minDstStride.value()) {
|
||||
webgl->ErrorInvalidOperation("Invalid stride.");
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto& dstIsPremult = webgl->mPixelStore_PremultiplyAlpha;
|
||||
const auto srcOrigin = (webgl->mPixelStore_FlipY ? gl::OriginPos::TopLeft
|
||||
: gl::OriginPos::BottomLeft);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/UniquePtrExtensions.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "WebGLActiveInfo.h"
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
@@ -27,6 +28,30 @@ namespace mozilla {
|
||||
// For a Tegra workaround.
|
||||
static const int MAX_DRAW_CALLS_SINCE_FLUSH = 100;
|
||||
|
||||
static uint8_t
|
||||
NumUsedLocationsByElemTypeForDraw(GLenum elemType)
|
||||
{
|
||||
switch (elemType) {
|
||||
case LOCAL_GL_FLOAT_MAT2:
|
||||
case LOCAL_GL_FLOAT_MAT2x3:
|
||||
case LOCAL_GL_FLOAT_MAT2x4:
|
||||
return 2;
|
||||
|
||||
case LOCAL_GL_FLOAT_MAT3x2:
|
||||
case LOCAL_GL_FLOAT_MAT3:
|
||||
case LOCAL_GL_FLOAT_MAT3x4:
|
||||
return 3;
|
||||
|
||||
case LOCAL_GL_FLOAT_MAT4x2:
|
||||
case LOCAL_GL_FLOAT_MAT4x3:
|
||||
case LOCAL_GL_FLOAT_MAT4:
|
||||
return 4;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
class ScopedResolveTexturesForDraw
|
||||
@@ -331,6 +356,7 @@ class ScopedDrawHelper final
|
||||
{
|
||||
WebGLContext* const mWebGL;
|
||||
bool mDidFake;
|
||||
std::vector<GLuint> mDisabledUnusedAttribs;
|
||||
|
||||
public:
|
||||
ScopedDrawHelper(WebGLContext* webgl, const char* funcName, uint32_t firstVertex,
|
||||
@@ -367,11 +393,43 @@ public:
|
||||
}
|
||||
mDidFake = true;
|
||||
|
||||
const auto& linkInfo = mWebGL->mActiveProgramLinkInfo;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (mWebGL->gl->WorkAroundDriverBugs()) {
|
||||
std::vector<bool> isActiveAttrib(mWebGL->mBoundVertexArray->mAttribs.Length(),
|
||||
false);
|
||||
for (const auto& progAttrib : linkInfo->attribs) {
|
||||
const auto loc = progAttrib.mLoc;
|
||||
if (loc < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto usedLocs =
|
||||
NumUsedLocationsByElemTypeForDraw(progAttrib.mActiveInfo->mElemType);
|
||||
for (uint32_t i = 0; i < usedLocs; ++i) {
|
||||
const auto usedLoc = static_cast<uint32_t>(loc) + i;
|
||||
if (usedLoc < isActiveAttrib.size()) {
|
||||
isActiveAttrib[usedLoc] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mWebGL->mBoundVertexArray->mAttribs.Length(); ++i) {
|
||||
const auto& attrib = mWebGL->mBoundVertexArray->mAttribs[i];
|
||||
if (!attrib.mEnabled || isActiveAttrib[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mWebGL->gl->fDisableVertexAttribArray(i);
|
||||
mDisabledUnusedAttribs.push_back(i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
////
|
||||
// Check UBO sizes.
|
||||
|
||||
const auto& linkInfo = mWebGL->mActiveProgramLinkInfo;
|
||||
|
||||
for (const auto& cur : linkInfo->uniformBlocks) {
|
||||
const auto& dataSize = cur->mDataSize;
|
||||
const auto& binding = cur->mBinding;
|
||||
@@ -477,6 +535,10 @@ public:
|
||||
if (mDidFake) {
|
||||
mWebGL->UndoFakeVertexAttrib0();
|
||||
}
|
||||
|
||||
for (const auto loc : mDisabledUnusedAttribs) {
|
||||
mWebGL->gl->fEnableVertexAttribArray(loc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -607,12 +669,12 @@ WebGLContext::DrawArraysInstanced(GLenum mode, GLint first, GLsizei vertCount,
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
@@ -855,12 +917,12 @@ WebGLContext::DrawElementsInstanced(GLenum mode, GLsizei vertCount, GLenum type,
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
if (vertCount > mMaxVertIdsPerDraw) {
|
||||
ErrorOutOfMemory(
|
||||
"Context's max vertCount is %u, but %u requested. [webgl.max-vert-ids-per-draw]", mMaxVertIdsPerDraw, vertCount);
|
||||
return;
|
||||
}
|
||||
|
||||
bool error = false;
|
||||
ScopedResolveTexturesForDraw scopedResolve(this, funcName, &error);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "mozilla/dom/ScrollAreaEvent.h"
|
||||
#include "mozilla/dom/SimpleGestureEvent.h"
|
||||
#include "mozilla/dom/StorageEvent.h"
|
||||
#include "mozilla/dom/SubmitEvent.h"
|
||||
#include "mozilla/dom/TimeEvent.h"
|
||||
#include "mozilla/dom/TouchEvent.h"
|
||||
#include "mozilla/dom/TransitionEvent.h"
|
||||
@@ -1066,6 +1067,12 @@ EventDispatcher::CreateEvent(EventTarget* aOwner,
|
||||
case eAnimationEventClass:
|
||||
return NS_NewDOMAnimationEvent(aOwner, aPresContext,
|
||||
aEvent->AsAnimationEvent());
|
||||
case eFormEventClass:
|
||||
if (aEvent->mMessage == eFormSubmit) {
|
||||
return NS_NewDOMSubmitEvent(aOwner, aPresContext,
|
||||
aEvent->AsFormEvent());
|
||||
}
|
||||
return NS_NewDOMEvent(aOwner, aPresContext, aEvent);
|
||||
default:
|
||||
// For all other types of events, create a vanilla event object.
|
||||
return NS_NewDOMEvent(aOwner, aPresContext, aEvent);
|
||||
|
||||
@@ -293,6 +293,9 @@ private:
|
||||
// Modal <dialog> element
|
||||
#define NS_EVENT_STATE_MODAL_DIALOG NS_DEFINE_EVENT_STATE_MACRO(54)
|
||||
|
||||
// Autofilled input element (for :autofill pseudo-class)
|
||||
#define NS_EVENT_STATE_AUTOFILL NS_DEFINE_EVENT_STATE_MACRO(55)
|
||||
|
||||
#define DIR_ATTR_STATES (NS_EVENT_STATE_HAS_DIR_ATTR | \
|
||||
NS_EVENT_STATE_DIR_ATTR_LTR | \
|
||||
NS_EVENT_STATE_DIR_ATTR_RTL | \
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/SubmitEvent.h"
|
||||
|
||||
#include "mozilla/ContentEvents.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(SubmitEvent, Event, mSubmitter)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(SubmitEvent, Event)
|
||||
NS_IMPL_RELEASE_INHERITED(SubmitEvent, Event)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SubmitEvent)
|
||||
NS_INTERFACE_MAP_END_INHERITING(Event)
|
||||
|
||||
SubmitEvent::SubmitEvent(EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
InternalFormEvent* aEvent)
|
||||
: Event(aOwner, aPresContext, aEvent)
|
||||
{
|
||||
if (aEvent) {
|
||||
nsIContent* originator = aEvent->mOriginator;
|
||||
if (originator && originator->IsHTMLElement()) {
|
||||
mSubmitter = static_cast<::nsGenericHTMLElement*>(originator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<SubmitEvent>
|
||||
SubmitEvent::Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const SubmitEventInit& aParam,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
RefPtr<SubmitEvent> e = new SubmitEvent(t, nullptr, nullptr);
|
||||
bool trusted = e->Init(t);
|
||||
e->InitEvent(aType, aParam.mBubbles, aParam.mCancelable);
|
||||
e->mSubmitter = aParam.mSubmitter;
|
||||
e->SetTrusted(trusted);
|
||||
e->SetComposed(aParam.mComposed);
|
||||
return e.forget();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
already_AddRefed<SubmitEvent>
|
||||
NS_NewDOMSubmitEvent(EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
InternalFormEvent* aEvent)
|
||||
{
|
||||
RefPtr<SubmitEvent> it = new SubmitEvent(aOwner, aPresContext, aEvent);
|
||||
return it.forget();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_SubmitEvent_h_
|
||||
#define mozilla_dom_SubmitEvent_h_
|
||||
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/SubmitEventBinding.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
class nsGenericHTMLElement;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class SubmitEvent final : public Event
|
||||
{
|
||||
public:
|
||||
SubmitEvent(EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
InternalFormEvent* aEvent);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SubmitEvent, Event)
|
||||
|
||||
// Forward to base class
|
||||
NS_FORWARD_TO_EVENT
|
||||
|
||||
static already_AddRefed<SubmitEvent> Constructor(const GlobalObject& aGlobal,
|
||||
const nsAString& aType,
|
||||
const SubmitEventInit& aParam,
|
||||
ErrorResult& aRv);
|
||||
|
||||
::nsGenericHTMLElement* GetSubmitter() const
|
||||
{
|
||||
return mSubmitter;
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return SubmitEventBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
protected:
|
||||
~SubmitEvent() {}
|
||||
|
||||
private:
|
||||
RefPtr<::nsGenericHTMLElement> mSubmitter;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
already_AddRefed<mozilla::dom::SubmitEvent>
|
||||
NS_NewDOMSubmitEvent(mozilla::dom::EventTarget* aOwner,
|
||||
nsPresContext* aPresContext,
|
||||
mozilla::InternalFormEvent* aEvent);
|
||||
|
||||
#endif // mozilla_dom_SubmitEvent_h_
|
||||
@@ -65,6 +65,7 @@ EXPORTS.mozilla.dom += [
|
||||
'ScrollAreaEvent.h',
|
||||
'SimpleGestureEvent.h',
|
||||
'StorageEvent.h',
|
||||
'SubmitEvent.h',
|
||||
'TextClause.h',
|
||||
'Touch.h',
|
||||
'TouchEvent.h',
|
||||
@@ -115,6 +116,7 @@ UNIFIED_SOURCES += [
|
||||
'ScrollAreaEvent.cpp',
|
||||
'SimpleGestureEvent.cpp',
|
||||
'StorageEvent.cpp',
|
||||
'SubmitEvent.cpp',
|
||||
'TextClause.cpp',
|
||||
'TextComposition.cpp',
|
||||
'Touch.cpp',
|
||||
|
||||
@@ -170,6 +170,7 @@ skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
||||
skip-if = toolkit == 'android' #TIMED_OUT
|
||||
[test_eventctors.html]
|
||||
skip-if = toolkit == 'android' #CRASH_DUMP, RANDOM
|
||||
[test_submit_event.html]
|
||||
[test_eventhandler_scoping.html]
|
||||
[test_eventTimeStamp.html]
|
||||
[test_focus_disabled.html]
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for SubmitEvent and submitter</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
var hasSimpleTest = typeof SimpleTest !== "undefined";
|
||||
function finishIfPossible() {
|
||||
if (hasSimpleTest) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
function okMaybe(cond, msg) {
|
||||
if (hasSimpleTest) {
|
||||
ok(cond, msg);
|
||||
} else {
|
||||
console.log((cond ? "OK: " : "FAIL: ") + msg);
|
||||
}
|
||||
}
|
||||
function isMaybe(a, b, msg) {
|
||||
if (hasSimpleTest) {
|
||||
is(a, b, msg);
|
||||
} else {
|
||||
console.log((a === b ? "OK: " : "FAIL: ") + msg + " (got " + a + " expected " + b + ")");
|
||||
}
|
||||
}
|
||||
if (hasSimpleTest) {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
}
|
||||
|
||||
function testConstructor() {
|
||||
okMaybe("SubmitEvent" in window, "SubmitEvent constructor exists");
|
||||
|
||||
var button = document.createElement("button");
|
||||
var ev = new SubmitEvent("submit", { submitter: button, bubbles: true, cancelable: true });
|
||||
isMaybe(ev.type, "submit", "constructor type matches");
|
||||
okMaybe(!ev.isTrusted, "constructed SubmitEvent is not trusted");
|
||||
isMaybe(ev.submitter, button, "constructor submitter matches");
|
||||
|
||||
var ev2 = new SubmitEvent("submit");
|
||||
isMaybe(ev2.submitter, null, "default submitter is null");
|
||||
}
|
||||
|
||||
function testDispatch() {
|
||||
var form = document.createElement("form");
|
||||
var button = document.createElement("button");
|
||||
button.type = "submit";
|
||||
button.textContent = "Submit";
|
||||
form.appendChild(button);
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.addEventListener("submit", function(e) {
|
||||
okMaybe(e instanceof SubmitEvent, "submit event is SubmitEvent");
|
||||
isMaybe(e.submitter, button, "submitter is the clicked button");
|
||||
e.preventDefault();
|
||||
form.remove();
|
||||
finishIfPossible();
|
||||
});
|
||||
|
||||
if (hasSimpleTest) {
|
||||
SimpleTest.executeSoon(function() {
|
||||
button.click();
|
||||
});
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
button.click();
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
testConstructor();
|
||||
testDispatch();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -276,6 +276,41 @@ HTMLFormElement::Submit()
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit
|
||||
void
|
||||
HTMLFormElement::RequestSubmit(nsGenericHTMLElement* aSubmitter,
|
||||
ErrorResult& aRv) {
|
||||
// 1. If submitter is not null, then:
|
||||
if (aSubmitter) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryObject(aSubmitter);
|
||||
|
||||
// 1.1. If submitter is not a submit button, then throw a TypeError.
|
||||
if (!fc || !fc->IsSubmitControl()) {
|
||||
aRv.ThrowTypeError<MSG_NOT_SUBMIT_BUTTON>();
|
||||
return;
|
||||
}
|
||||
|
||||
// 1.2. If submitter's form owner is not this form element, then throw a
|
||||
// "NotFoundError" DOMException.
|
||||
if (fc->GetFormElement() != this) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Otherwise, set submitter to this form element.
|
||||
// 3. Submit this form element, from submitter.
|
||||
// We go through the presShell here for the corner case a submit event
|
||||
// is pending while the window is being destroyed.
|
||||
InternalFormEvent event(true, eFormSubmit);
|
||||
event.mOriginator = aSubmitter;
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
nsCOMPtr<nsIPresShell> presShell = GetComposedDoc()->GetShell();
|
||||
if (MOZ_LIKELY(presShell)) {
|
||||
presShell->HandleDOMEventWithTarget(this, &event, &status);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLFormElement::Reset()
|
||||
{
|
||||
|
||||
@@ -391,6 +391,19 @@ public:
|
||||
|
||||
void Submit(ErrorResult& aRv);
|
||||
|
||||
/**
|
||||
* Requests to submit the form. Unlike submit(), this method includes
|
||||
* interactive constraint validation and firing a submit event,
|
||||
* either of which can cancel submission.
|
||||
*
|
||||
* @param aSubmitter The submitter argument can be used to point to a specific
|
||||
* submit button.
|
||||
* @param aRv An ErrorResult.
|
||||
* @see
|
||||
* https://html.spec.whatwg.org/multipage/forms.html#dom-form-requestsubmit
|
||||
*/
|
||||
void RequestSubmit(nsGenericHTMLElement* aSubmitter, ErrorResult& aRv);
|
||||
|
||||
// XPCOM Reset() is OK
|
||||
|
||||
bool CheckValidity()
|
||||
|
||||
@@ -2832,6 +2832,20 @@ HTMLInputElement::SetUserInput(const nsAString& aValue)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::SetAutofilled(bool aAutofilled)
|
||||
{
|
||||
nsAutoString value;
|
||||
GetValueInternal(value);
|
||||
if (aAutofilled) {
|
||||
AddStates(NS_EVENT_STATE_AUTOFILL);
|
||||
mAutofilledValue = value;
|
||||
} else {
|
||||
RemoveStates(NS_EVENT_STATE_AUTOFILL);
|
||||
mAutofilledValue.Truncate();
|
||||
}
|
||||
}
|
||||
|
||||
nsIEditor*
|
||||
HTMLInputElement::GetEditor()
|
||||
{
|
||||
@@ -3562,7 +3576,18 @@ HTMLInputElement::Blur(ErrorResult& aError)
|
||||
}
|
||||
|
||||
nsGenericHTMLElement::Blur(aError);
|
||||
}
|
||||
|
||||
if (State().HasState(NS_EVENT_STATE_AUTOFILL)) {
|
||||
// Force a complete restyle to ensure autofill pseudo-classes are processed
|
||||
if (nsIDocument* doc = GetComposedDoc()) {
|
||||
if (nsIPresShell* shell = doc->GetShell()) {
|
||||
if (nsIFrame* frame = GetPrimaryFrame()) {
|
||||
shell->FrameNeedsReflow(frame, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::Focus(ErrorResult& aError)
|
||||
@@ -7060,6 +7085,13 @@ HTMLInputElement::IntrinsicState() const
|
||||
state |= NS_EVENT_STATE_MOZ_SUBMITINVALID;
|
||||
}
|
||||
|
||||
// Autofill highlight should persist as long as the value matches the autofilled value
|
||||
nsAutoString value;
|
||||
GetValueInternal(value);
|
||||
if (!mAutofilledValue.IsEmpty() && value == mAutofilledValue) {
|
||||
state |= NS_EVENT_STATE_AUTOFILL;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -8495,8 +8527,23 @@ HTMLInputElement::InitializeKeyboardEventListeners()
|
||||
NS_IMETHODIMP_(void)
|
||||
HTMLInputElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
|
||||
{
|
||||
nsAutoString value;
|
||||
GetValueInternal(value);
|
||||
mLastValueChangeWasInteractive = aWasInteractiveUserChange;
|
||||
|
||||
// Only remove autofilled state if the value actually changed from autofilled value
|
||||
if (aWasInteractiveUserChange && State().HasState(NS_EVENT_STATE_AUTOFILL)) {
|
||||
if (!mAutofilledValue.IsEmpty() && mAutofilledValue != value) {
|
||||
RemoveStates(NS_EVENT_STATE_AUTOFILL);
|
||||
mAutofilledValue.Truncate();
|
||||
}
|
||||
} else if (aWasInteractiveUserChange && !State().HasState(NS_EVENT_STATE_AUTOFILL)) {
|
||||
// If the value is changed back to the autofilled value, restore the state
|
||||
if (!mAutofilledValue.IsEmpty() && mAutofilledValue == value) {
|
||||
AddStates(NS_EVENT_STATE_AUTOFILL);
|
||||
}
|
||||
}
|
||||
|
||||
UpdateAllValidityStates(aNotify);
|
||||
|
||||
if (HasDirAuto()) {
|
||||
@@ -8527,6 +8574,24 @@ HTMLInputElement::HasCachedSelection()
|
||||
return isCached;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::BeginProgrammaticValueSet() {
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (state) {
|
||||
state->SettingValue(true);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLInputElement::EndProgrammaticValueSet() {
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (state) {
|
||||
state->SettingValue(false);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::FieldSetDisabledChanged(bool aNotify)
|
||||
{
|
||||
|
||||
@@ -160,6 +160,8 @@ public:
|
||||
}
|
||||
|
||||
NS_IMETHOD SetUserInput(const nsAString& aInput) override;
|
||||
NS_IMETHOD BeginProgrammaticValueSet() override;
|
||||
NS_IMETHOD EndProgrammaticValueSet() override;
|
||||
|
||||
// Overriden nsIFormControl methods
|
||||
NS_IMETHOD_(uint32_t) GetType() const override { return mType; }
|
||||
@@ -845,6 +847,15 @@ public:
|
||||
void SetUserInput(const nsAString& aInput,
|
||||
nsIPrincipal& aSubjectPrincipal);
|
||||
|
||||
/**
|
||||
* Sets or clears the autofilled state of this input element.
|
||||
* When setting, also stores the autofilled value for persistence.
|
||||
* When clearing, clears the stored autofilled value.
|
||||
*
|
||||
* @param aAutofilled Whether the element should be marked as autofilled
|
||||
*/
|
||||
void SetAutofilled(bool aAutofilled);
|
||||
|
||||
// XPCOM GetPhonetic() is OK
|
||||
|
||||
/**
|
||||
@@ -860,6 +871,8 @@ public:
|
||||
|
||||
void UpdateEntries(const nsTArray<OwningFileOrDirectory>& aFilesOrDirectories);
|
||||
|
||||
void SetAutofilledValue(const nsAString& aValue) { mAutofilledValue = aValue; }
|
||||
|
||||
protected:
|
||||
virtual ~HTMLInputElement();
|
||||
|
||||
@@ -1103,7 +1116,7 @@ protected:
|
||||
bool MinOrMaxLengthApplies() const { return IsSingleLineTextControl(false, mType); }
|
||||
|
||||
void FreeData();
|
||||
nsTextEditorState *GetEditorState() const;
|
||||
nsTextEditorState* GetEditorState() const;
|
||||
|
||||
/**
|
||||
* Manages the internal data storage across type changes.
|
||||
@@ -1629,6 +1642,11 @@ protected:
|
||||
bool mNumberControlSpinnerSpinsUp : 1;
|
||||
bool mPickerRunning : 1;
|
||||
bool mSelectionCached : 1;
|
||||
/**
|
||||
* The value that was autofilled by the browser. Used to persist the autofill
|
||||
* highlight as long as the value matches, regardless of focus/blur.
|
||||
*/
|
||||
nsString mAutofilledValue;
|
||||
|
||||
private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
@@ -1772,6 +1790,8 @@ private:
|
||||
nsCOMPtr<nsIFilePicker> mFilePicker;
|
||||
RefPtr<HTMLInputElement> mInput;
|
||||
};
|
||||
|
||||
void EnsureAutofillState();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -366,6 +366,46 @@ HTMLTextAreaElement::SetUserInput(const nsAString& aValue)
|
||||
return SetValueInternal(aValue, nsTextEditorState::eSetValue_BySetUserInput);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLTextAreaElement::SetAutofilled(bool aAutofilled)
|
||||
{
|
||||
if (aAutofilled) {
|
||||
AddStates(NS_EVENT_STATE_AUTOFILL);
|
||||
GetValueInternal(mAutofilledValue, true); // Store the autofilled value
|
||||
} else {
|
||||
RemoveStates(NS_EVENT_STATE_AUTOFILL);
|
||||
mAutofilledValue.Truncate();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
|
||||
{
|
||||
nsAutoString value;
|
||||
GetValueInternal(value, true);
|
||||
|
||||
// Only remove autofilled state if the value actually changed from autofilled value
|
||||
if (State().HasState(NS_EVENT_STATE_AUTOFILL) || !mAutofilledValue.IsEmpty()) {
|
||||
if (aWasInteractiveUserChange && mAutofilledValue != value) {
|
||||
RemoveStates(NS_EVENT_STATE_AUTOFILL);
|
||||
mAutofilledValue.Truncate();
|
||||
} else if (aWasInteractiveUserChange && mAutofilledValue == value) {
|
||||
AddStates(NS_EVENT_STATE_AUTOFILL);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the validity state
|
||||
bool validBefore = IsValid();
|
||||
UpdateTooLongValidityState();
|
||||
UpdateTooShortValidityState();
|
||||
UpdateValueMissingValidityState();
|
||||
|
||||
if (validBefore != IsValid() ||
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTextAreaElement::SetValueChanged(bool aValueChanged)
|
||||
{
|
||||
@@ -556,6 +596,19 @@ HTMLTextAreaElement::FireChangeEventIfNeeded()
|
||||
false);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLTextAreaElement::EnsureAutofillState()
|
||||
{
|
||||
nsAutoString value;
|
||||
GetValueInternal(value, true);
|
||||
if (!mAutofilledValue.IsEmpty() && mAutofilledValue == value) {
|
||||
if (!State().HasState(NS_EVENT_STATE_AUTOFILL)) {
|
||||
AddStates(NS_EVENT_STATE_AUTOFILL);
|
||||
UpdateState(true); // Force style system to re-evaluate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
{
|
||||
@@ -580,6 +633,9 @@ HTMLTextAreaElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
}
|
||||
|
||||
UpdateState(true);
|
||||
|
||||
// Defensive: re-apply autofill state if value is still autofilled value
|
||||
EnsureAutofillState();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@@ -1186,6 +1242,10 @@ HTMLTextAreaElement::IntrinsicState() const
|
||||
{
|
||||
EventStates state = nsGenericHTMLFormElementWithState::IntrinsicState();
|
||||
|
||||
if (!mAutofilledValue.IsEmpty()) {
|
||||
state |= NS_EVENT_STATE_AUTOFILL;
|
||||
}
|
||||
|
||||
if (HasAttr(kNameSpaceID_None, nsGkAtoms::required)) {
|
||||
state |= NS_EVENT_STATE_REQUIRED;
|
||||
} else {
|
||||
@@ -1628,23 +1688,6 @@ HTMLTextAreaElement::InitializeKeyboardEventListeners()
|
||||
mState.InitializeKeyboardEventListeners();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
HTMLTextAreaElement::OnValueChanged(bool aNotify, bool aWasInteractiveUserChange)
|
||||
{
|
||||
mLastValueChangeWasInteractive = aWasInteractiveUserChange;
|
||||
|
||||
// Update the validity state
|
||||
bool validBefore = IsValid();
|
||||
UpdateTooLongValidityState();
|
||||
UpdateTooShortValidityState();
|
||||
UpdateValueMissingValidityState();
|
||||
|
||||
if (validBefore != IsValid() ||
|
||||
HasAttr(kNameSpaceID_None, nsGkAtoms::placeholder)) {
|
||||
UpdateState(aNotify);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
HTMLTextAreaElement::HasCachedSelection()
|
||||
{
|
||||
@@ -1660,11 +1703,33 @@ HTMLTextAreaElement::FieldSetDisabledChanged(bool aNotify)
|
||||
nsGenericHTMLFormElementWithState::FieldSetDisabledChanged(aNotify);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTextAreaElement::BeginProgrammaticValueSet() {
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (state) {
|
||||
state->SettingValue(true);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLTextAreaElement::EndProgrammaticValueSet() {
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (state) {
|
||||
state->SettingValue(false);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
HTMLTextAreaElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return HTMLTextAreaElementBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsTextEditorState* HTMLTextAreaElement::GetEditorState() const {
|
||||
return const_cast<nsTextEditorState*>(&mState);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -69,6 +69,17 @@ public:
|
||||
return nsGenericHTMLElement::GetEditor(aEditor);
|
||||
}
|
||||
NS_IMETHOD SetUserInput(const nsAString& aInput) override;
|
||||
NS_IMETHOD BeginProgrammaticValueSet() override;
|
||||
NS_IMETHOD EndProgrammaticValueSet() override;
|
||||
|
||||
/**
|
||||
* Sets or clears the autofilled state of this textarea element.
|
||||
* This is used by the browser's autofill system to indicate when
|
||||
* a value has been automatically filled (e.g., from saved form data).
|
||||
*
|
||||
* @param aAutofilled Whether the element should be marked as autofilled
|
||||
*/
|
||||
void SetAutofilled(bool aAutofilled);
|
||||
|
||||
// nsIFormControl
|
||||
NS_IMETHOD_(uint32_t) GetType() const override { return NS_FORM_TEXTAREA; }
|
||||
@@ -293,6 +304,7 @@ public:
|
||||
{
|
||||
return mState.GetEditor();
|
||||
}
|
||||
nsTextEditorState* GetEditorState() const;
|
||||
|
||||
protected:
|
||||
virtual ~HTMLTextAreaElement() {}
|
||||
@@ -324,6 +336,7 @@ protected:
|
||||
void FireChangeEventIfNeeded();
|
||||
|
||||
nsString mFocusedValue;
|
||||
nsString mAutofilledValue;
|
||||
|
||||
/** The state of the text editor (selection controller and the editor) **/
|
||||
nsTextEditorState mState;
|
||||
@@ -397,6 +410,7 @@ protected:
|
||||
private:
|
||||
static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData);
|
||||
void EnsureAutofillState();
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -163,6 +163,7 @@ public:
|
||||
// or reconsider fixing bug 597525 to remove these.
|
||||
void EmptyValue() { if (mValue) mValue->Truncate(); }
|
||||
bool IsEmpty() const { return mValue ? mValue->IsEmpty() : true; }
|
||||
void SettingValue(bool aValue) { mSettingValue = aValue; }
|
||||
|
||||
nsresult CreatePlaceholderNode();
|
||||
|
||||
@@ -348,6 +349,7 @@ private:
|
||||
mutable bool mSelectionRestoreEagerInit; // Whether we're eager initing because of selection restore
|
||||
bool mPlaceholderVisibility;
|
||||
bool mIsCommittingComposition;
|
||||
bool mSettingValue;
|
||||
};
|
||||
|
||||
inline void
|
||||
|
||||
@@ -1945,6 +1945,20 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
const long MOUSE_BUTTONS_5TH_BUTTON = 0x10;
|
||||
// Buttons are not specified, will be calculated from |aButton|.
|
||||
const long MOUSE_BUTTONS_NOT_SPECIFIED = -1;
|
||||
|
||||
/**
|
||||
* Add an EventState bit to an element (privileged only).
|
||||
* @param element The element to modify.
|
||||
* @param state The EventState bit (see EventStates.h, e.g. NS_EVENT_STATE_AUTOFILL).
|
||||
*/
|
||||
void addElementEventState(in nsIDOMElement element, in unsigned long long state);
|
||||
|
||||
/**
|
||||
* Remove an EventState bit from an element (privileged only).
|
||||
* @param element The element to modify.
|
||||
* @param state The EventState bit.
|
||||
*/
|
||||
void removeElementEventState(in nsIDOMElement element, in unsigned long long state);
|
||||
};
|
||||
|
||||
[scriptable, uuid(c694e359-7227-4392-a138-33c0cc1f15a6)]
|
||||
|
||||
@@ -25,4 +25,10 @@ interface nsIDOMNSEditableElement : nsISupports
|
||||
// 'change' event for example will be dispatched when focusing out the
|
||||
// element.
|
||||
[noscript] void setUserInput(in DOMString input);
|
||||
/**
|
||||
* Call this before and after programmatically setting the value to prevent
|
||||
* OnValueChanged from treating it as a user edit.
|
||||
*/
|
||||
void beginProgrammaticValueSet();
|
||||
void endProgrammaticValueSet();
|
||||
};
|
||||
Loaded 100 of 8708 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user