mirror of
https://github.com/Basilisk-Development-Team/UXP-mirror.git
synced 2026-11-13 12:52:02 -05:00
Compare commits
515
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b18be917d | ||
|
|
037cc5f614 | ||
|
|
4a68bbbd53 | ||
|
|
5762097bc2 | ||
|
|
e86caa48f5 | ||
|
|
612a8991df | ||
|
|
5c991eadc0 | ||
|
|
38e09d2368 | ||
|
|
8fea2ad823 | ||
|
|
c4339b14dc | ||
|
|
bae7a6ec8f | ||
|
|
d42616bb12 | ||
|
|
5f290d1097 | ||
|
|
a0b10f4375 | ||
|
|
1d7ba07673 | ||
|
|
f51bc72a14 | ||
|
|
e8644b494f | ||
|
|
0acf5cb1a1 | ||
|
|
f2d027343a | ||
|
|
eaf2a4ac4b | ||
|
|
aa6a599aa4 | ||
|
|
f385a5e06c | ||
|
|
559e0dbdc5 | ||
|
|
e59e88bfd5 | ||
|
|
7e3d96909f | ||
|
|
d294c31da1 | ||
|
|
d699633e82 | ||
|
|
7079db6476 | ||
|
|
e938cb015b | ||
|
|
15893d9ebc | ||
|
|
0f45bf39af | ||
|
|
23398d176b | ||
|
|
7809ecf653 | ||
|
|
43d19989d4 | ||
|
|
81fce269f5 | ||
|
|
03bdba053e | ||
|
|
5088774087 | ||
|
|
c4d42aaeff | ||
|
|
5b5d7841a6 | ||
|
|
b5e48c5458 | ||
|
|
714c06d255 | ||
|
|
42c59e0781 | ||
|
|
a877a69089 | ||
|
|
98a7463135 | ||
|
|
6cdcc60623 | ||
|
|
c4e2909bdc | ||
|
|
8f1b4387b4 | ||
|
|
a7bc4e7c97 | ||
|
|
62e29a58b0 | ||
|
|
3ede95de79 | ||
|
|
fce465d3a6 | ||
|
|
71edc1fbf5 | ||
|
|
53e4ec00ef | ||
|
|
aa066876a0 | ||
|
|
ae54d6c3d2 | ||
|
|
f69237e99c | ||
|
|
a45c04623e | ||
|
|
8e2a07c696 | ||
|
|
9aa9d182c7 | ||
|
|
b4bb6051e9 | ||
|
|
53bf5b5a21 | ||
|
|
07b2881965 | ||
|
|
ca1b7c2595 | ||
|
|
a0d8eeb768 | ||
|
|
278ce9a272 | ||
|
|
9367b64f2a | ||
|
|
080247cf2f | ||
|
|
95bf9478c7 | ||
|
|
4ae3149d2e | ||
|
|
9bf01636f1 | ||
|
|
e48fe8e307 | ||
|
|
27c12ad698 | ||
|
|
612ddb64e5 | ||
|
|
c6c8421a2a | ||
|
|
f9859d226c | ||
|
|
7c0e60c4f1 | ||
|
|
e06ef010c4 | ||
|
|
3935cd9ed3 | ||
|
|
f781824676 | ||
|
|
5a231d5bf9 | ||
|
|
02302031dd | ||
|
|
b59b350424 | ||
|
|
99b8669d0a | ||
|
|
919fbff2ec | ||
|
|
4977713834 | ||
|
|
1f8bd8cf45 | ||
|
|
8f6bacf33e | ||
|
|
a79a1b55a1 | ||
|
|
fa4d389b91 | ||
|
|
36b884ff7f | ||
|
|
f3a7e60608 | ||
|
|
a8405c5667 | ||
|
|
829354fb65 | ||
|
|
4be7883908 | ||
|
|
2f77b246b3 | ||
|
|
ddf950f5ed | ||
|
|
ad98fe5130 | ||
|
|
659c690d5b | ||
|
|
f1dc542b0b | ||
|
|
0c5437c80b | ||
|
|
db9881b854 | ||
|
|
c5a37cad2e | ||
|
|
dd97244289 | ||
|
|
5372fed15c | ||
|
|
37a8909357 | ||
|
|
18f4069d8d | ||
|
|
78c01f1b3f | ||
|
|
f946c969a2 | ||
|
|
2dfa2b7c19 | ||
|
|
8b88dd736a | ||
|
|
b9fd964fec | ||
|
|
9c74a819e4 | ||
|
|
f700453cb1 | ||
|
|
4ea0375575 | ||
|
|
7071894a52 | ||
|
|
0f471cfde7 | ||
|
|
a8cc198e79 | ||
|
|
477b1010fe | ||
|
|
8722bc3693 | ||
|
|
e31e3802a0 | ||
|
|
723d95295e | ||
|
|
91b3b6fdc8 | ||
|
|
34a901430d | ||
|
|
83826f1f34 | ||
|
|
3562ba1235 | ||
|
|
1cc002018f | ||
|
|
352863cab4 | ||
|
|
d69570b62b | ||
|
|
26c44d4869 | ||
|
|
f10fc4489c | ||
|
|
3450ed2282 | ||
|
|
967e985c5f | ||
|
|
d6915b9014 | ||
|
|
304e6d045d | ||
|
|
4dea7f04dc | ||
|
|
7cc35f1195 | ||
|
|
afd0648631 | ||
|
|
6524bfee21 | ||
|
|
de8c2d1762 | ||
|
|
5309640d6c | ||
|
|
ddd016a6f8 | ||
|
|
e76fc5637a | ||
|
|
62110dcf7f | ||
|
|
c597f4de77 | ||
|
|
fe4b55154b | ||
|
|
d9f4319bfd | ||
|
|
ec7baced6c | ||
|
|
5ed591c3d7 | ||
|
|
32859868d6 | ||
|
|
4ab80fceb4 | ||
|
|
4e25cc130f | ||
|
|
f1b56f6512 | ||
|
|
b5d6c427ad | ||
|
|
9a900503ea | ||
|
|
f6296891bf | ||
|
|
bbd16ed644 | ||
|
|
8f6cd1cfcd | ||
|
|
70a3532f49 | ||
|
|
c160edb49b | ||
|
|
32f0e6d1e6 | ||
|
|
8c6098ed9e | ||
|
|
5f70302bfc | ||
|
|
f1cc25409a | ||
|
|
1bb67f87d1 | ||
|
|
6f89be191d | ||
|
|
f453aac0eb | ||
|
|
abc2e56e6a | ||
|
|
2f2c86599f | ||
|
|
a52e68f04d | ||
|
|
ee256eda09 | ||
|
|
adbedd87a3 | ||
|
|
4f94981ad9 | ||
|
|
fb15e11ef3 | ||
|
|
b0e1570535 | ||
|
|
b370042040 | ||
|
|
60daf77274 | ||
|
|
4f9ed77789 | ||
|
|
c819a0b3c8 | ||
|
|
104f493044 | ||
|
|
ccfb3fc5db | ||
|
|
9fa543c9f4 | ||
|
|
1d18178eda | ||
|
|
8a6b1f309b | ||
|
|
a60ab0def7 | ||
|
|
6276177e20 | ||
|
|
6c4e8f1466 | ||
|
|
19a4ae248b | ||
|
|
744212dbf3 | ||
|
|
a46fbd6ead | ||
|
|
bb39100caf | ||
|
|
a27a4e4b60 | ||
|
|
490cf03fba | ||
|
|
e93191409e | ||
|
|
5cfdaf4ad4 | ||
|
|
7664a83451 | ||
|
|
f449e1fd7d | ||
|
|
bbd4a99be2 | ||
|
|
4ae471baf9 | ||
|
|
4d41b5df11 | ||
|
|
01188c1465 | ||
|
|
7eac3090a5 | ||
|
|
e9bb602131 | ||
|
|
ddc8b21705 | ||
|
|
6209d33f4e | ||
|
|
cbaace24c0 | ||
|
|
051951ef00 | ||
|
|
a9062b8710 | ||
|
|
18c656ebba | ||
|
|
9220d05de2 | ||
|
|
fdd286d190 | ||
|
|
4fa8a8ce1d | ||
|
|
d5e853a25b | ||
|
|
6ea3635847 | ||
|
|
0ea3d42a38 | ||
|
|
a024df6124 | ||
|
|
11a80021f4 | ||
|
|
301873c751 | ||
|
|
90986caee8 | ||
|
|
778d93ac49 | ||
|
|
f9ba08fa11 | ||
|
|
95911aa2ce | ||
|
|
ccbea05142 | ||
|
|
867c957ceb | ||
|
|
0d2ff3ee65 | ||
|
|
14122475be | ||
|
|
d881e7ed56 | ||
|
|
9b0054c55f | ||
|
|
baeae97784 | ||
|
|
0324bfa219 | ||
|
|
b279fd025b | ||
|
|
f31546817a | ||
|
|
f272382a9c | ||
|
|
aa8af9d7f8 | ||
|
|
e1f03ae019 | ||
|
|
f316bc6535 | ||
|
|
82e4c66520 | ||
|
|
3c923e0467 | ||
|
|
866985ac88 | ||
|
|
ba772b40ad | ||
|
|
7a86f0e1b7 | ||
|
|
7e9286f2d8 | ||
|
|
b0d1e365ec | ||
|
|
dbd5a2cbf4 | ||
|
|
d60fb1d5c0 | ||
|
|
29c91fcdba | ||
|
|
fe65674f3f | ||
|
|
a3a6b5ed7e | ||
|
|
d2de8658a7 | ||
|
|
be785b4783 | ||
|
|
70e34941c4 | ||
|
|
545d52572d | ||
|
|
dfa0736b49 | ||
|
|
c7bb5664d9 | ||
|
|
6bbc6f3417 | ||
|
|
631169a312 | ||
|
|
427b3312a6 | ||
|
|
2287b0b57a | ||
|
|
56aaba09b1 | ||
|
|
332938fef3 | ||
|
|
13710f7a06 | ||
|
|
530693099b | ||
|
|
f68aa7ea88 | ||
|
|
5bdaee5e40 | ||
|
|
1b465bc2e2 | ||
|
|
e455021bea | ||
|
|
4fe1246bcc | ||
|
|
59b4ac4d5f | ||
|
|
de641fedfe | ||
|
|
cb99fabcc0 | ||
|
|
f996ea12c2 | ||
|
|
4e7fb3e0ea | ||
|
|
e7cbbbef0f | ||
|
|
a181078981 | ||
|
|
987a662b51 | ||
|
|
77e3e14e55 | ||
|
|
98ddf30155 | ||
|
|
83da5c58a2 | ||
|
|
7136ae45a7 | ||
|
|
97d3d61749 | ||
|
|
9c8bf1fe5d | ||
|
|
d1cc6ff3cb | ||
|
|
db76d74820 | ||
|
|
8fdd9d52f9 | ||
|
|
d42797f587 | ||
|
|
6b9c1f6ab8 | ||
|
|
4aedc96db2 | ||
|
|
234830da1e | ||
|
|
244b95968f | ||
|
|
810cd553b5 | ||
|
|
e52eaa961c | ||
|
|
b7827091b8 | ||
|
|
2e344377b5 | ||
|
|
15335ce39d | ||
|
|
14b03e1f8c | ||
|
|
0968b94e5c | ||
|
|
ba6b2258aa | ||
|
|
1e1715ff11 | ||
|
|
c93381fa79 | ||
|
|
65b0a59757 | ||
|
|
c785639043 | ||
|
|
512c259822 | ||
|
|
90fea6f0d4 | ||
|
|
d892468fd0 | ||
|
|
81ab98b329 | ||
|
|
3f1cacd3e6 | ||
|
|
6e41e01a29 | ||
|
|
9ce81488d4 | ||
|
|
25bc2630d9 | ||
|
|
e5b69418a0 | ||
|
|
229a69be5f | ||
|
|
7f2561312a | ||
|
|
93d11a07f9 | ||
|
|
8e5e24c4c6 | ||
|
|
517ee6754c | ||
|
|
47690c287c | ||
|
|
364b95170e | ||
|
|
407006d673 | ||
|
|
2d60605cc6 | ||
|
|
2d1129eb7e | ||
|
|
495b4980e7 | ||
|
|
ad480be112 | ||
|
|
a06001c022 | ||
|
|
6cbda74aeb | ||
|
|
576fbdf490 | ||
|
|
52b00c38ea | ||
|
|
8ec56f459b | ||
|
|
5cbe423461 | ||
|
|
369fbba750 | ||
|
|
8e3c35efc6 | ||
|
|
b3b852b877 | ||
|
|
d5c6e20e9e | ||
|
|
89b36775fb | ||
|
|
df16df5693 | ||
|
|
aa1fd576ac | ||
|
|
2512188ca7 | ||
|
|
89e88ca6a0 | ||
|
|
2697dd162f | ||
|
|
53a4179c4a | ||
|
|
a120731ddd | ||
|
|
bda611a41a | ||
|
|
5a02a4a1a4 | ||
|
|
e59f358b45 | ||
|
|
90c9535b39 | ||
|
|
ad778bbfdb | ||
|
|
8868552b24 | ||
|
|
66826eb487 | ||
|
|
39127b5ee9 | ||
|
|
80cff816a8 | ||
|
|
e9dda8dafa | ||
|
|
11fc818dfb | ||
|
|
84ed844e3f | ||
|
|
50af804f1c | ||
|
|
82ce93bce9 | ||
|
|
228abc8259 | ||
|
|
1692fa5291 | ||
|
|
bb58c6ae38 | ||
|
|
4f58dc27f9 | ||
|
|
fc5324b9f7 | ||
|
|
561f65aabf | ||
|
|
9acfe36b95 | ||
|
|
ce495cbd85 | ||
|
|
c44020f188 | ||
|
|
35e7a695af | ||
|
|
7a55055d22 | ||
|
|
061900b87f | ||
|
|
abe32f7309 | ||
|
|
7bfd4c7fe7 | ||
|
|
859d6a3e2c | ||
|
|
c2f05f99af | ||
|
|
55b33fb02b | ||
|
|
c247e40d41 | ||
|
|
05c58f159d | ||
|
|
67d5fefcf2 | ||
|
|
aad017be9e | ||
|
|
4543dbf3ff | ||
|
|
b1cb7e0a8f | ||
|
|
1c6d21c97d | ||
|
|
fc42fb38c9 | ||
|
|
618068c15b | ||
|
|
808516a0a8 | ||
|
|
7d6b806040 | ||
|
|
6b4e2c9d73 | ||
|
|
787883f6a4 | ||
|
|
7f02753c04 | ||
|
|
8fa38b3445 | ||
|
|
541c5f9f45 | ||
|
|
4b6bd4976a | ||
|
|
a0843d52b4 | ||
|
|
977a8cbed8 | ||
|
|
1e85085305 | ||
|
|
188f61505f | ||
|
|
a514d7f6a4 | ||
|
|
47c2c75ceb | ||
|
|
7082ec8a9a | ||
|
|
2907a84362 | ||
|
|
b8d1ee05c3 | ||
|
|
0b625e624a | ||
|
|
a4da712f91 | ||
|
|
185f124e87 | ||
|
|
8633077691 | ||
|
|
39a1899045 | ||
|
|
4dc011a187 | ||
|
|
ccb12e1dda | ||
|
|
63f0d3e295 | ||
|
|
09d598c496 | ||
|
|
7e60482d80 | ||
|
|
10b3237e52 | ||
|
|
99af7cc028 | ||
|
|
76b360b5d1 | ||
|
|
4001b58a3e | ||
|
|
134a8aac87 | ||
|
|
3e2e48872a | ||
|
|
622b43cbc5 | ||
|
|
75b44ef620 | ||
|
|
00084ea49c | ||
|
|
b6fae24296 | ||
|
|
13c6b7422d | ||
|
|
24f2e663cd | ||
|
|
f96b155988 | ||
|
|
d5cc24e916 | ||
|
|
8eba271c5f | ||
|
|
19955c82b3 | ||
|
|
80ae8aec7c | ||
|
|
d8441d7c81 | ||
|
|
c2446f2478 | ||
|
|
6efb7a1904 | ||
|
|
fa0b03a10f | ||
|
|
3ae2972950 | ||
|
|
2d48de9998 | ||
|
|
3b029cdfe4 | ||
|
|
ea9077a8a5 | ||
|
|
b4af6b6265 | ||
|
|
ae1d53ceb1 | ||
|
|
c3f4709d5e | ||
|
|
a7bb3fc175 | ||
|
|
6a0203f25f | ||
|
|
b0dfcb147f | ||
|
|
06fd4c9357 | ||
|
|
b9ea7fd9ee | ||
|
|
58308a5c7a | ||
|
|
88c7d54975 | ||
|
|
eadb5678b3 | ||
|
|
54e3e60796 | ||
|
|
2a05494abe | ||
|
|
bc89e58def | ||
|
|
3a009b97f6 | ||
|
|
a105f6d5e9 | ||
|
|
5db241c0c0 | ||
|
|
d38dca10e5 | ||
|
|
54fc723126 | ||
|
|
9b8ca17ee4 | ||
|
|
cddc95b39b | ||
|
|
5676529793 | ||
|
|
ce68156cf4 | ||
|
|
5032ad9593 | ||
|
|
b55f765f2e | ||
|
|
856078d435 | ||
|
|
c74c262d2f | ||
|
|
787e29e374 | ||
|
|
e439896c9b | ||
|
|
15b508f1fb | ||
|
|
5651ebfc76 | ||
|
|
593bfc1ce8 | ||
|
|
28953cda7a | ||
|
|
516f3f545d | ||
|
|
83aff65a42 | ||
|
|
5bd97df957 | ||
|
|
8772711181 | ||
|
|
dc9526f4c6 | ||
|
|
9ab36e7ae0 | ||
|
|
e8d30841e7 | ||
|
|
9faf29374e | ||
|
|
75e4818d36 | ||
|
|
a65144e9e0 | ||
|
|
4f29548526 | ||
|
|
528db2cbd8 | ||
|
|
84e6bcc1e6 | ||
|
|
0dc9ff518d | ||
|
|
a2e3bd44aa | ||
|
|
163a0e7caf | ||
|
|
49a86db5f3 | ||
|
|
2640953d8b | ||
|
|
7eb7d67f7a | ||
|
|
e28860ba7f | ||
|
|
49a96b1d91 | ||
|
|
3130812693 | ||
|
|
71ae69aea8 | ||
|
|
9e34d697c7 | ||
|
|
8fa9125d02 | ||
|
|
4b4488c3e4 | ||
|
|
248db7d301 | ||
|
|
e199f2949b | ||
|
|
456b5450a4 | ||
|
|
d8e629c4a3 | ||
|
|
4898c4f297 | ||
|
|
7cd578bbc6 | ||
|
|
1e91df628a | ||
|
|
b110549cbd | ||
|
|
971047835a | ||
|
|
dd4d9eb032 | ||
|
|
8b94f1e480 | ||
|
|
c89610a5c7 | ||
|
|
217963cbed | ||
|
|
c4f4e18340 | ||
|
|
8a7c0e7345 | ||
|
|
52e304d450 | ||
|
|
cfc0eeca53 | ||
|
|
ebd3dd9228 | ||
|
|
cb40e4e7ef | ||
|
|
662dba55fd | ||
|
|
8760ce023c | ||
|
|
b86e148bb7 | ||
|
|
9e83721e5e | ||
|
|
dc2d6c2e60 | ||
|
|
4ada6f6762 |
No files matched your search
@@ -276,6 +276,7 @@ NotificationController::DropMutationEvent(AccTreeMutationEvent* aEvent)
|
|||||||
MOZ_ASSERT(hideEvent);
|
MOZ_ASSERT(hideEvent);
|
||||||
|
|
||||||
if (hideEvent->NeedsShutdown()) {
|
if (hideEvent->NeedsShutdown()) {
|
||||||
|
mDocument->UncacheChildrenInSubtree(aEvent->GetAccessible());
|
||||||
mDocument->ShutdownChildrenInSubtree(aEvent->GetAccessible());
|
mDocument->ShutdownChildrenInSubtree(aEvent->GetAccessible());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1307,6 +1307,8 @@ DocAccessible::UnbindFromDocument(Accessible* aAccessible)
|
|||||||
{
|
{
|
||||||
NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()),
|
NS_ASSERTION(mAccessibleCache.GetWeak(aAccessible->UniqueID()),
|
||||||
"Unbinding the unbound accessible!");
|
"Unbinding the unbound accessible!");
|
||||||
|
MOZ_ASSERT(!mARIAOwnsHash.Contains(aAccessible),
|
||||||
|
"Container still lingering in mARIAOwnsHash");
|
||||||
|
|
||||||
// Fire focus event on accessible having DOM focus if active item was removed
|
// Fire focus event on accessible having DOM focus if active item was removed
|
||||||
// from the tree.
|
// from the tree.
|
||||||
|
|||||||
Vendored
+1
-1
@@ -26,6 +26,6 @@
|
|||||||
global DATA_SYMBOL
|
global DATA_SYMBOL
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
SECTION .rodata align=16
|
SECTION .rodata data readable align=16
|
||||||
DATA_SYMBOL:
|
DATA_SYMBOL:
|
||||||
incbin ICU_DATA_FILE
|
incbin ICU_DATA_FILE
|
||||||
+6
@@ -6,7 +6,13 @@
|
|||||||
.section .note.GNU-stack,"",%progbits
|
.section .note.GNU-stack,"",%progbits
|
||||||
#endif
|
#endif
|
||||||
.global ICU_DATA_SYMBOL
|
.global ICU_DATA_SYMBOL
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
.const
|
||||||
|
#elif defined(__GNUC__) && !defined(XP_SOLARIS)
|
||||||
|
.section .rodata
|
||||||
|
#else
|
||||||
.data
|
.data
|
||||||
|
#endif
|
||||||
.balign 16
|
.balign 16
|
||||||
ICU_DATA_SYMBOL:
|
ICU_DATA_SYMBOL:
|
||||||
.incbin ICU_DATA_FILE
|
.incbin ICU_DATA_FILE
|
||||||
Vendored
+2
@@ -17,6 +17,8 @@ DEFINES.update(
|
|||||||
UCONFIG_NO_LEGACY_CONVERSION = True,
|
UCONFIG_NO_LEGACY_CONVERSION = True,
|
||||||
UCONFIG_NO_TRANSLITERATION = True,
|
UCONFIG_NO_TRANSLITERATION = True,
|
||||||
UCONFIG_NO_REGULAR_EXPRESSIONS = True,
|
UCONFIG_NO_REGULAR_EXPRESSIONS = True,
|
||||||
|
UCONFIG_NO_BREAK_ITERATION = True,
|
||||||
|
UCONFIG_NO_MF2 = True,
|
||||||
|
|
||||||
# We don't need to pass data to and from legacy char* APIs.
|
# We don't need to pass data to and from legacy char* APIs.
|
||||||
U_CHARSET_IS_UTF8 = True,
|
U_CHARSET_IS_UTF8 = True,
|
||||||
|
|||||||
+17230
-8908
File diff suppressed because it is too large.
Load diff
+969
-295
File diff suppressed because it is too large.
Load diff
@@ -31,6 +31,7 @@ public:
|
|||||||
void
|
void
|
||||||
Unfollow();
|
Unfollow();
|
||||||
|
|
||||||
|
/* Should this be WeakRef? */
|
||||||
RefPtr<AbortSignal> mFollowingSignal;
|
RefPtr<AbortSignal> mFollowingSignal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,12 +40,14 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(Timeout)
|
|||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Timeout)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Timeout)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTimer)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrincipal)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrincipal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptHandler)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mScriptHandler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Timeout)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Timeout)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTimer)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrincipal)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrincipal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptHandler)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mScriptHandler)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|||||||
@@ -25,6 +25,22 @@ VisualViewport::~VisualViewport()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(VisualViewport)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(VisualViewport,
|
||||||
|
DOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(VisualViewport,
|
||||||
|
DOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(VisualViewport)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(VisualViewport, DOMEventTargetHelper)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(VisualViewport, DOMEventTargetHelper)
|
||||||
|
|
||||||
/* virtual */
|
/* virtual */
|
||||||
JSObject*
|
JSObject*
|
||||||
VisualViewport::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
VisualViewport::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ class VisualViewport final: public mozilla::DOMEventTargetHelper
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(VisualViewport, DOMEventTargetHelper)
|
||||||
|
|
||||||
explicit VisualViewport(nsPIDOMWindowInner* aWindow);
|
explicit VisualViewport(nsPIDOMWindowInner* aWindow);
|
||||||
explicit VisualViewport(nsIGlobalObject* aGlobal);
|
explicit VisualViewport(nsIGlobalObject* aGlobal);
|
||||||
|
|
||||||
|
|||||||
@@ -695,7 +695,7 @@ nsContentList::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
|
|||||||
!MayContainRelevantNodes(aContainer) ||
|
!MayContainRelevantNodes(aContainer) ||
|
||||||
(!aFirstNewContent->HasChildren() &&
|
(!aFirstNewContent->HasChildren() &&
|
||||||
!aFirstNewContent->GetNextSibling() &&
|
!aFirstNewContent->GetNextSibling() &&
|
||||||
!MatchSelf(aFirstNewContent))) {
|
!MatchSelf<MatchSelfMode::Insertion>(aFirstNewContent))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,7 +731,7 @@ nsContentList::ContentAppended(nsIDocument* aDocument, nsIContent* aContainer,
|
|||||||
// The new stuff is somewhere in the middle of our list; check
|
// The new stuff is somewhere in the middle of our list; check
|
||||||
// whether we need to invalidate
|
// whether we need to invalidate
|
||||||
for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
|
for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
|
||||||
if (MatchSelf(cur)) {
|
if (MatchSelf<MatchSelfMode::Insertion>(cur)) {
|
||||||
// Uh-oh. We're gonna have to add elements into the middle
|
// Uh-oh. We're gonna have to add elements into the middle
|
||||||
// of our list. That's not worth the effort.
|
// of our list. That's not worth the effort.
|
||||||
SetDirty();
|
SetDirty();
|
||||||
@@ -788,7 +788,7 @@ nsContentList::ContentInserted(nsIDocument *aDocument,
|
|||||||
if (mState != LIST_DIRTY &&
|
if (mState != LIST_DIRTY &&
|
||||||
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
||||||
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) &&
|
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) &&
|
||||||
MatchSelf(aChild)) {
|
MatchSelf<MatchSelfMode::Insertion>(aChild)) {
|
||||||
SetDirty();
|
SetDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,7 +808,7 @@ nsContentList::ContentRemoved(nsIDocument *aDocument,
|
|||||||
if (mState != LIST_DIRTY &&
|
if (mState != LIST_DIRTY &&
|
||||||
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
MayContainRelevantNodes(NODE_FROM(aContainer, aDocument)) &&
|
||||||
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) &&
|
nsContentUtils::IsInSameAnonymousTree(mRootNode, aChild) &&
|
||||||
MatchSelf(aChild)) {
|
MatchSelf<MatchSelfMode::Removal>(aChild)) {
|
||||||
SetDirty();
|
SetDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -853,6 +853,7 @@ nsContentList::Match(Element *aElement)
|
|||||||
ni->Equals(mXMLMatchAtom, mMatchNameSpaceId);
|
ni->Equals(mXMLMatchAtom, mMatchNameSpaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <nsContentList::MatchSelfMode Mode>
|
||||||
bool
|
bool
|
||||||
nsContentList::MatchSelf(nsIContent *aContent)
|
nsContentList::MatchSelf(nsIContent *aContent)
|
||||||
{
|
{
|
||||||
@@ -864,8 +865,20 @@ nsContentList::MatchSelf(nsIContent *aContent)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Match(aContent->AsElement()))
|
auto matches = [&](Element* aElement) {
|
||||||
|
if (Match(aElement)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if constexpr (Mode == MatchSelfMode::Removal) {
|
||||||
|
return mFunc == nsContentUtils::MatchClassNames &&
|
||||||
|
aElement->IsSVGElement() && aElement->MayHaveClass();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (matches(aContent->AsElement())) {
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!mDeep)
|
if (!mDeep)
|
||||||
return false;
|
return false;
|
||||||
@@ -873,7 +886,7 @@ nsContentList::MatchSelf(nsIContent *aContent)
|
|||||||
for (nsIContent* cur = aContent->GetFirstChild();
|
for (nsIContent* cur = aContent->GetFirstChild();
|
||||||
cur;
|
cur;
|
||||||
cur = cur->GetNextNode(aContent)) {
|
cur = cur->GetNextNode(aContent)) {
|
||||||
if (cur->IsElement() && Match(cur->AsElement())) {
|
if (cur->IsElement() && matches(cur->AsElement())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,6 +367,15 @@ protected:
|
|||||||
* @return whether we match
|
* @return whether we match
|
||||||
*/
|
*/
|
||||||
bool Match(mozilla::dom::Element *aElement);
|
bool Match(mozilla::dom::Element *aElement);
|
||||||
|
|
||||||
|
enum class MatchSelfMode : uint8_t {
|
||||||
|
Insertion,
|
||||||
|
// Also accept SVG elements that may have a class. SMIL can change their
|
||||||
|
// class without notification, so they can be in the list without
|
||||||
|
// matching now. Needed when aContent leaves the subtree.
|
||||||
|
Removal,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See if anything in the subtree rooted at aContent, including
|
* See if anything in the subtree rooted at aContent, including
|
||||||
* aContent itself, matches our criterion.
|
* aContent itself, matches our criterion.
|
||||||
@@ -374,6 +383,7 @@ protected:
|
|||||||
* @param aContent the root of the subtree to match against
|
* @param aContent the root of the subtree to match against
|
||||||
* @return whether we match something in the tree rooted at aContent
|
* @return whether we match something in the tree rooted at aContent
|
||||||
*/
|
*/
|
||||||
|
template <MatchSelfMode Mode>
|
||||||
bool MatchSelf(nsIContent *aContent);
|
bool MatchSelf(nsIContent *aContent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -2073,6 +2073,10 @@ public:
|
|||||||
aClasses);
|
aClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool MatchClassNames(mozilla::dom::Element* aElement,
|
||||||
|
int32_t aNamespaceID,
|
||||||
|
nsIAtom* aAtom, void* aData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a presshell for this document, if there is one. This will be
|
* Returns a presshell for this document, if there is one. This will be
|
||||||
* aDoc's direct presshell if there is one, otherwise we'll look at all
|
* aDoc's direct presshell if there is one, otherwise we'll look at all
|
||||||
@@ -3012,9 +3016,6 @@ private:
|
|||||||
|
|
||||||
static void DropFragmentParsers();
|
static void DropFragmentParsers();
|
||||||
|
|
||||||
static bool MatchClassNames(mozilla::dom::Element* aElement,
|
|
||||||
int32_t aNamespaceID,
|
|
||||||
nsIAtom* aAtom, void* aData);
|
|
||||||
static void DestroyClassNameArray(void* aData);
|
static void DestroyClassNameArray(void* aData);
|
||||||
static void* AllocClassMatchingInfo(nsINode* aRootNode,
|
static void* AllocClassMatchingInfo(nsINode* aRootNode,
|
||||||
const nsString* aClasses);
|
const nsString* aClasses);
|
||||||
|
|||||||
@@ -921,7 +921,7 @@ private:
|
|||||||
// List of nodes referred to by mEntryTable so we can sort them
|
// List of nodes referred to by mEntryTable so we can sort them
|
||||||
// For a specific pseudo element, we use its parent element as the
|
// For a specific pseudo element, we use its parent element as the
|
||||||
// batch target, so they will be put in the same EntryArray.
|
// batch target, so they will be put in the same EntryArray.
|
||||||
nsTArray<nsINode*> mBatchTargets;
|
nsTArray<nsCOMPtr<nsINode>> mBatchTargets;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline
|
inline
|
||||||
|
|||||||
@@ -2176,6 +2176,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
|
|||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocation)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHistory)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCustomElements)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVisualViewport)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStorage)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStorage)
|
||||||
@@ -2254,6 +2255,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
|
|||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocation)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHistory)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCustomElements)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mVisualViewport)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStorage)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStorage)
|
||||||
if (tmp->mApplicationCache) {
|
if (tmp->mApplicationCache) {
|
||||||
|
|||||||
@@ -682,16 +682,19 @@ DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
|
|||||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsAutoString format;
|
||||||
|
GetRealFormat(aFormat, format);
|
||||||
|
|
||||||
// Don't allow the custom type to be assigned.
|
// Don't allow the custom type to be assigned.
|
||||||
if (aFormat.EqualsLiteral(kCustomTypesMime)) {
|
if (format.EqualsLiteral(kCustomTypesMime)) {
|
||||||
return NS_ERROR_TYPE_ERR;
|
return NS_ERROR_TYPE_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PrincipalMaySetData(aFormat, aData, aSubjectPrincipal)) {
|
if (!PrincipalMaySetData(format, aData, aSubjectPrincipal)) {
|
||||||
return NS_ERROR_DOM_SECURITY_ERR;
|
return NS_ERROR_DOM_SECURITY_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SetDataWithPrincipal(aFormat, aData, aIndex, aSubjectPrincipal);
|
return SetDataWithPrincipal(format, aData, aIndex, aSubjectPrincipal);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -29,18 +29,19 @@ using namespace workers;
|
|||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Request)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(Request)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Request)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Request)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHeaders)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHeaders)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSignal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Request)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Request)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHeaders)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHeaders)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSignal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Request)
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Request)
|
||||||
|
|||||||
@@ -30,12 +30,12 @@ namespace dom {
|
|||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Response)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(Response)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Response)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(Response)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Response)
|
NS_IMPL_CYCLE_COLLECTION_CLASS(Response)
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Response)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Response)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHeaders)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mHeaders)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSignal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchStreamReader)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mFetchStreamReader)
|
||||||
|
|
||||||
tmp->mReadableStreamBody = nullptr;
|
tmp->mReadableStreamBody = nullptr;
|
||||||
@@ -47,6 +47,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Response)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Response)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHeaders)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHeaders)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSignal)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchStreamReader)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFetchStreamReader)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
|||||||
@@ -1415,6 +1415,7 @@ BackgroundFactoryRequestChild::BackgroundFactoryRequestChild(
|
|||||||
uint64_t aRequestedVersion)
|
uint64_t aRequestedVersion)
|
||||||
: BackgroundRequestChildBase(aOpenRequest)
|
: BackgroundRequestChildBase(aOpenRequest)
|
||||||
, mFactory(aFactory)
|
, mFactory(aFactory)
|
||||||
|
, mDatabaseActor(nullptr)
|
||||||
, mRequestedVersion(aRequestedVersion)
|
, mRequestedVersion(aRequestedVersion)
|
||||||
, mIsDeleteOp(aIsDeleteOp)
|
, mIsDeleteOp(aIsDeleteOp)
|
||||||
{
|
{
|
||||||
@@ -1439,6 +1440,15 @@ BackgroundFactoryRequestChild::GetOpenDBRequest() const
|
|||||||
return static_cast<IDBOpenDBRequest*>(mRequest.get());
|
return static_cast<IDBOpenDBRequest*>(mRequest.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
BackgroundFactoryRequestChild::SetDatabaseActor(BackgroundDatabaseChild* aActor)
|
||||||
|
{
|
||||||
|
AssertIsOnOwningThread();
|
||||||
|
MOZ_ASSERT(!aActor || !mDatabaseActor);
|
||||||
|
|
||||||
|
mDatabaseActor = aActor;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse)
|
BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse)
|
||||||
{
|
{
|
||||||
@@ -1450,6 +1460,11 @@ BackgroundFactoryRequestChild::HandleResponse(nsresult aResponse)
|
|||||||
|
|
||||||
DispatchErrorEvent(mRequest, aResponse);
|
DispatchErrorEvent(mRequest, aResponse);
|
||||||
|
|
||||||
|
if (mDatabaseActor) {
|
||||||
|
mDatabaseActor->ReleaseDOMObject();
|
||||||
|
MOZ_ASSERT(!mDatabaseActor);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1468,6 +1483,7 @@ BackgroundFactoryRequestChild::HandleResponse(
|
|||||||
IDBDatabase* database = databaseActor->GetDOMObject();
|
IDBDatabase* database = databaseActor->GetDOMObject();
|
||||||
if (!database) {
|
if (!database) {
|
||||||
databaseActor->EnsureDOMObject();
|
databaseActor->EnsureDOMObject();
|
||||||
|
MOZ_ASSERT(mDatabaseActor);
|
||||||
|
|
||||||
database = databaseActor->GetDOMObject();
|
database = databaseActor->GetDOMObject();
|
||||||
MOZ_ASSERT(database);
|
MOZ_ASSERT(database);
|
||||||
@@ -1475,6 +1491,8 @@ BackgroundFactoryRequestChild::HandleResponse(
|
|||||||
MOZ_ASSERT(!database->IsClosed());
|
MOZ_ASSERT(!database->IsClosed());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mDatabaseActor == databaseActor);
|
||||||
|
|
||||||
if (database->IsClosed()) {
|
if (database->IsClosed()) {
|
||||||
// If the database was closed already, which is only possible if we fired an
|
// If the database was closed already, which is only possible if we fired an
|
||||||
// "upgradeneeded" event, then we shouldn't fire a "success" event here.
|
// "upgradeneeded" event, then we shouldn't fire a "success" event here.
|
||||||
@@ -1487,6 +1505,7 @@ BackgroundFactoryRequestChild::HandleResponse(
|
|||||||
}
|
}
|
||||||
|
|
||||||
databaseActor->ReleaseDOMObject();
|
databaseActor->ReleaseDOMObject();
|
||||||
|
MOZ_ASSERT(!mDatabaseActor);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1507,6 +1526,8 @@ BackgroundFactoryRequestChild::HandleResponse(
|
|||||||
|
|
||||||
DispatchSuccessEvent(&helper, successEvent);
|
DispatchSuccessEvent(&helper, successEvent);
|
||||||
|
|
||||||
|
MOZ_ASSERT(!mDatabaseActor);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1737,6 +1758,8 @@ BackgroundDatabaseChild::EnsureDOMObject()
|
|||||||
|
|
||||||
mDatabase = mTemporaryStrongDatabase;
|
mDatabase = mTemporaryStrongDatabase;
|
||||||
mSpec.forget();
|
mSpec.forget();
|
||||||
|
|
||||||
|
mOpenRequestActor->SetDatabaseActor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1748,6 +1771,8 @@ BackgroundDatabaseChild::ReleaseDOMObject()
|
|||||||
MOZ_ASSERT(mOpenRequestActor);
|
MOZ_ASSERT(mOpenRequestActor);
|
||||||
MOZ_ASSERT(mDatabase == mTemporaryStrongDatabase);
|
MOZ_ASSERT(mDatabase == mTemporaryStrongDatabase);
|
||||||
|
|
||||||
|
mOpenRequestActor->SetDatabaseActor(nullptr);
|
||||||
|
|
||||||
mOpenRequestActor = nullptr;
|
mOpenRequestActor = nullptr;
|
||||||
|
|
||||||
// This may be the final reference to the IDBDatabase object so we may end up
|
// This may be the final reference to the IDBDatabase object so we may end up
|
||||||
|
|||||||
@@ -254,6 +254,20 @@ class BackgroundFactoryRequestChild final
|
|||||||
friend class PermissionRequestParent;
|
friend class PermissionRequestParent;
|
||||||
|
|
||||||
RefPtr<IDBFactory> mFactory;
|
RefPtr<IDBFactory> mFactory;
|
||||||
|
|
||||||
|
// Normally when opening of a database is successful, we receive a database
|
||||||
|
// actor in request response, so we can use it to call ReleaseDOMObject()
|
||||||
|
// which clears temporary strong reference to IDBDatabase.
|
||||||
|
// However, when there's an error, we don't receive a database actor and
|
||||||
|
// IDBRequest::mTransaction is already cleared (must be). So the only way how
|
||||||
|
// to call ReleaseDOMObject() is to have a back-reference to database actor.
|
||||||
|
// This creates a weak ref cycle between
|
||||||
|
// BackgroundFactoryRequestChild (using mDatabaseActor member) and
|
||||||
|
// BackgroundDatabaseChild actor (using mOpenRequestActor member).
|
||||||
|
// mDatabaseActor is set in EnsureDOMObject() and cleared in
|
||||||
|
// ReleaseDOMObject().
|
||||||
|
BackgroundDatabaseChild* mDatabaseActor;
|
||||||
|
|
||||||
const uint64_t mRequestedVersion;
|
const uint64_t mRequestedVersion;
|
||||||
const bool mIsDeleteOp;
|
const bool mIsDeleteOp;
|
||||||
|
|
||||||
@@ -271,6 +285,9 @@ private:
|
|||||||
// Only destroyed by BackgroundFactoryChild.
|
// Only destroyed by BackgroundFactoryChild.
|
||||||
~BackgroundFactoryRequestChild();
|
~BackgroundFactoryRequestChild();
|
||||||
|
|
||||||
|
void
|
||||||
|
SetDatabaseActor(BackgroundDatabaseChild* aActor);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
HandleResponse(nsresult aResponse);
|
HandleResponse(nsresult aResponse);
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,9 @@ GetJSValFromKeyPathString(JSContext* aCx,
|
|||||||
// only through getters but we still want to support them for key
|
// only through getters but we still want to support them for key
|
||||||
// extraction. So they need to be handled manually.
|
// extraction. So they need to be handled manually.
|
||||||
Blob* blob;
|
Blob* blob;
|
||||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, &obj, blob))) {
|
// UNWRAP_OBJECT calls might mutate this.
|
||||||
|
JS::Rooted<JSObject*> blobObj(aCx, obj);
|
||||||
|
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, &blobObj, blob))) {
|
||||||
if (token.EqualsLiteral("size")) {
|
if (token.EqualsLiteral("size")) {
|
||||||
ErrorResult rv;
|
ErrorResult rv;
|
||||||
uint64_t size = blob->GetSize(rv);
|
uint64_t size = blob->GetSize(rv);
|
||||||
|
|||||||
@@ -294,8 +294,8 @@ nsXMLContentSink::DidBuildModel(bool aTerminated)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mDocumentChildren.Clear();
|
|
||||||
mXSLTProcessor->SetSourceContentModel(mDocument, mDocumentChildren);
|
mXSLTProcessor->SetSourceContentModel(mDocument, mDocumentChildren);
|
||||||
|
mDocumentChildren.Clear();
|
||||||
// Since the processor now holds a reference to us we drop our reference
|
// Since the processor now holds a reference to us we drop our reference
|
||||||
// to it to avoid owning cycles
|
// to it to avoid owning cycles
|
||||||
mXSLTProcessor = nullptr;
|
mXSLTProcessor = nullptr;
|
||||||
@@ -883,6 +883,9 @@ nsXMLContentSink::SetDocElement(int32_t aNameSpaceID,
|
|||||||
for (nsIContent* child : mDocumentChildren) {
|
for (nsIContent* child : mDocumentChildren) {
|
||||||
if (MOZ_UNLIKELY(child->GetParentNode())) {
|
if (MOZ_UNLIKELY(child->GetParentNode())) {
|
||||||
child->Remove();
|
child->Remove();
|
||||||
|
if (MOZ_UNLIKELY(child->GetParentNode())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mDocument->AppendChildTo(child, false);
|
mDocument->AppendChildTo(child, false);
|
||||||
}
|
}
|
||||||
@@ -996,6 +999,9 @@ nsXMLContentSink::HandleStartElement(const char16_t *aName,
|
|||||||
|
|
||||||
if (MOZ_UNLIKELY(content->GetParentNode())) {
|
if (MOZ_UNLIKELY(content->GetParentNode())) {
|
||||||
content->Remove();
|
content->Remove();
|
||||||
|
if (MOZ_UNLIKELY(content->GetParentNode())) {
|
||||||
|
return NS_ERROR_UNEXPECTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
parent->AppendChildTo(content, false);
|
parent->AppendChildTo(content, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1082,6 +1082,9 @@ ChromeTooltipListener::ChromeTooltipListener(nsWebBrowser* aInBrowser,
|
|||||||
|
|
||||||
ChromeTooltipListener::~ChromeTooltipListener()
|
ChromeTooltipListener::~ChromeTooltipListener()
|
||||||
{
|
{
|
||||||
|
if (mTooltipTimer) {
|
||||||
|
mTooltipTimer->Cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hook up things to the chrome like context menus and tooltips, if the chrome
|
// Hook up things to the chrome like context menus and tooltips, if the chrome
|
||||||
@@ -1329,7 +1332,7 @@ void
|
|||||||
ChromeTooltipListener::sTooltipCallback(nsITimer* aTimer,
|
ChromeTooltipListener::sTooltipCallback(nsITimer* aTimer,
|
||||||
void* aChromeTooltipListener)
|
void* aChromeTooltipListener)
|
||||||
{
|
{
|
||||||
auto self = static_cast<ChromeTooltipListener*>(aChromeTooltipListener);
|
RefPtr<ChromeTooltipListener> self = static_cast<ChromeTooltipListener*>(aChromeTooltipListener);
|
||||||
if (self && self->mPossibleTooltipNode) {
|
if (self && self->mPossibleTooltipNode) {
|
||||||
// The actual coordinates we want to put the tooltip at are relative to the
|
// The actual coordinates we want to put the tooltip at are relative to the
|
||||||
// toplevel docshell of our mWebBrowser. We know what the screen
|
// toplevel docshell of our mWebBrowser. We know what the screen
|
||||||
@@ -1374,7 +1377,7 @@ ChromeTooltipListener::sTooltipCallback(nsITimer* aTimer,
|
|||||||
self->mPossibleTooltipNode, getter_Copies(tooltipText),
|
self->mPossibleTooltipNode, getter_Copies(tooltipText),
|
||||||
getter_Copies(directionText), &textFound);
|
getter_Copies(directionText), &textFound);
|
||||||
|
|
||||||
if (textFound) {
|
if (self->mPossibleTooltipNode && textFound) {
|
||||||
nsString tipText(tooltipText);
|
nsString tipText(tooltipText);
|
||||||
nsString dirText(directionText);
|
nsString dirText(directionText);
|
||||||
LayoutDeviceIntPoint screenDot = widget->WidgetToScreenOffset();
|
LayoutDeviceIntPoint screenDot = widget->WidgetToScreenOffset();
|
||||||
|
|||||||
@@ -1554,8 +1554,7 @@ FilterNodeTileSoftware::SetAttribute(uint32_t aIndex,
|
|||||||
const IntRect &aSourceRect)
|
const IntRect &aSourceRect)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aIndex == ATT_TILE_SOURCE_RECT);
|
MOZ_ASSERT(aIndex == ATT_TILE_SOURCE_RECT);
|
||||||
mSourceRect = IntRect(int32_t(aSourceRect.x), int32_t(aSourceRect.y),
|
mSourceRect = aSourceRect;
|
||||||
int32_t(aSourceRect.width), int32_t(aSourceRect.height));
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1595,14 +1594,24 @@ FilterNodeTileSoftware::Render(const IntRect& aRect)
|
|||||||
typedef std::map<IntRect, RefPtr<DataSourceSurface>, CompareIntRects> InputMap;
|
typedef std::map<IntRect, RefPtr<DataSourceSurface>, CompareIntRects> InputMap;
|
||||||
InputMap inputs;
|
InputMap inputs;
|
||||||
|
|
||||||
|
auto IntRectToInt64Rect = [](const IntRect& aRect) {
|
||||||
|
return RectTyped<UnknownUnits, int64_t>(aRect.X(), aRect.Y(), aRect.Width(),
|
||||||
|
aRect.Height());
|
||||||
|
};
|
||||||
|
|
||||||
IntPoint startIndex = TileIndex(mSourceRect, aRect.TopLeft());
|
IntPoint startIndex = TileIndex(mSourceRect, aRect.TopLeft());
|
||||||
IntPoint endIndex = TileIndex(mSourceRect, aRect.BottomRight());
|
IntPoint endIndex = TileIndex(mSourceRect, aRect.BottomRight());
|
||||||
for (int32_t ix = startIndex.x; ix <= endIndex.x; ix++) {
|
for (int32_t ix = startIndex.x; ix <= endIndex.x; ix++) {
|
||||||
for (int32_t iy = startIndex.y; iy <= endIndex.y; iy++) {
|
for (int32_t iy = startIndex.y; iy <= endIndex.y; iy++) {
|
||||||
IntPoint sourceToDestOffset(ix * mSourceRect.width,
|
auto sourceToDestOffset = PointTyped<UnknownUnits, int64_t>(
|
||||||
iy * mSourceRect.height);
|
ix * mSourceRect.Width(), iy * mSourceRect.Height());
|
||||||
IntRect destRect = aRect.Intersect(mSourceRect + sourceToDestOffset);
|
auto destRect64 = IntRectToInt64Rect(aRect).Intersect(
|
||||||
IntRect srcRect = destRect - sourceToDestOffset;
|
IntRectToInt64Rect(mSourceRect) + sourceToDestOffset);
|
||||||
|
auto srcRect64 = destRect64 - sourceToDestOffset;
|
||||||
|
IntRect destRect, srcRect;
|
||||||
|
if (!destRect64.ToIntRect(&destRect) || !srcRect64.ToIntRect(&srcRect)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
if (srcRect.IsEmpty()) {
|
if (srcRect.IsEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -358,7 +358,8 @@ gl::Error Image9::setManagedSurface(IDirect3DSurface9 *surface)
|
|||||||
surface->GetDesc(&desc);
|
surface->GetDesc(&desc);
|
||||||
ASSERT(desc.Pool == D3DPOOL_MANAGED);
|
ASSERT(desc.Pool == D3DPOOL_MANAGED);
|
||||||
|
|
||||||
if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight)
|
if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight &&
|
||||||
|
desc.Format == mD3DFormat)
|
||||||
{
|
{
|
||||||
if (mSurface)
|
if (mSurface)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -214,6 +214,7 @@ def update_data_file(topsrcdir):
|
|||||||
'-DUCONFIG_NO_TRANSLITERATION ' +
|
'-DUCONFIG_NO_TRANSLITERATION ' +
|
||||||
'-DUCONFIG_NO_REGULAR_EXPRESSIONS ' +
|
'-DUCONFIG_NO_REGULAR_EXPRESSIONS ' +
|
||||||
'-DUCONFIG_NO_BREAK_ITERATION ' +
|
'-DUCONFIG_NO_BREAK_ITERATION ' +
|
||||||
|
'-DUCONFIG_NO_MF2 ' +
|
||||||
'-DU_CHARSET_IS_UTF8')
|
'-DU_CHARSET_IS_UTF8')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include "nsIInputStream.h"
|
#include "nsIInputStream.h"
|
||||||
#include "nsReadLine.h"
|
#include "nsReadLine.h"
|
||||||
#include "nsStreamUtils.h"
|
#include "nsStreamUtils.h"
|
||||||
#include <algorithm>
|
|
||||||
#include "mozilla/dom/EncodingUtils.h"
|
#include "mozilla/dom/EncodingUtils.h"
|
||||||
|
|
||||||
using mozilla::dom::EncodingUtils;
|
using mozilla::dom::EncodingUtils;
|
||||||
|
|||||||
@@ -184,17 +184,8 @@ sub genTest {
|
|||||||
<p>
|
<p>
|
||||||
__END__
|
__END__
|
||||||
foreach my $key (sort { $a <=> $b } keys %$hash) {
|
foreach my $key (sort { $a <=> $b } keys %$hash) {
|
||||||
# Bug 1476304: we exclude Georgian letters U+10D0..10FF because of lack
|
|
||||||
# of widespread font support for the corresponding Mtavruli characters
|
|
||||||
# at this time (July 2018).
|
|
||||||
# This condition is to be removed once the major platforms ship with
|
|
||||||
# fonts that support U+1C90..1CBF.
|
|
||||||
my $skippedGeorgian = $whichMapping eq "upper" && $key >= 0x10D0 && $key <= 0x10FF;
|
|
||||||
print OUT "<!-- " if $skippedGeorgian;
|
|
||||||
printf OUT "&#x%04X;", $key;
|
printf OUT "&#x%04X;", $key;
|
||||||
print OUT " -->" if $skippedGeorgian;
|
|
||||||
print OUT " <!-- $charName{$key} -->" if exists $charName{$key};
|
print OUT " <!-- $charName{$key} -->" if exists $charName{$key};
|
||||||
print OUT " <!-- Temporarily skipped, see bug 1476304. -->" if $skippedGeorgian;
|
|
||||||
print OUT "\n";
|
print OUT "\n";
|
||||||
}
|
}
|
||||||
print OUT <<__END__;
|
print OUT <<__END__;
|
||||||
@@ -220,17 +211,8 @@ __END__
|
|||||||
<p>
|
<p>
|
||||||
__END__
|
__END__
|
||||||
foreach my $key (sort { $a <=> $b } keys %$hash) {
|
foreach my $key (sort { $a <=> $b } keys %$hash) {
|
||||||
# Bug 1476304: we exclude Georgian letters U+10D0..10FF because of lack
|
|
||||||
# of widespread font support for the corresponding Mtavruli characters
|
|
||||||
# at this time (July 2018).
|
|
||||||
# This condition is to be removed once the major platforms ship with
|
|
||||||
# fonts that support U+1C90..1CBF.
|
|
||||||
my $skippedGeorgian = $whichMapping eq "upper" && $key >= 0x10D0 && $key <= 0x10FF;
|
|
||||||
print OUT "<!-- " if $skippedGeorgian;
|
|
||||||
print OUT join('', map { sprintf("&#x%s;", $_) } split(/ /, $hash->{$key}));
|
print OUT join('', map { sprintf("&#x%s;", $_) } split(/ /, $hash->{$key}));
|
||||||
print OUT " -->" if $skippedGeorgian;
|
|
||||||
print OUT " <!-- $charName{$key} -->" if exists $charName{$key};
|
print OUT " <!-- $charName{$key} -->" if exists $charName{$key};
|
||||||
print OUT " <!-- Temporarily skipped, see bug 1476304. -->" if $skippedGeorgian;
|
|
||||||
print OUT "\n";
|
print OUT "\n";
|
||||||
}
|
}
|
||||||
print OUT <<__END__;
|
print OUT <<__END__;
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ class MOZ_NON_PARAM JS_PUBLIC_API(ProfilingFrameIterator)
|
|||||||
// activation (if any) comes around.
|
// activation (if any) comes around.
|
||||||
void* savedPrevJitTop_;
|
void* savedPrevJitTop_;
|
||||||
|
|
||||||
JS::AutoCheckCannotGC nogc_;
|
|
||||||
|
|
||||||
static const unsigned StorageSpace = 8 * sizeof(void*);
|
static const unsigned StorageSpace = 8 * sizeof(void*);
|
||||||
|
|
||||||
alignas(void*) unsigned char storage_[StorageSpace];
|
alignas(void*) unsigned char storage_[StorageSpace];
|
||||||
@@ -144,7 +142,7 @@ class MOZ_NON_PARAM JS_PUBLIC_API(ProfilingFrameIterator)
|
|||||||
void iteratorConstruct();
|
void iteratorConstruct();
|
||||||
void iteratorDestroy();
|
void iteratorDestroy();
|
||||||
bool iteratorDone();
|
bool iteratorDone();
|
||||||
};
|
} JS_HAZ_GC_INVALIDATED;
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
IsProfilingEnabledForContext(JSContext* cx);
|
IsProfilingEnabledForContext(JSContext* cx);
|
||||||
|
|||||||
@@ -69,7 +69,11 @@ WeakRef_deref_impl(JSContext* cx, const CallArgs& args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data->isObject()) {
|
if (data->isObject()) {
|
||||||
JSObject* target = data->objectTarget.get();
|
// Use unbarrieredGet() to avoid barriers on potentially invalid memory.
|
||||||
|
JSObject* target = data->objectTarget.unbarrieredGet();
|
||||||
|
|
||||||
|
// Ensure pointer is not null.
|
||||||
|
// During WeakRef deref, if the target was collected, it will be nullptr.
|
||||||
if (target) {
|
if (target) {
|
||||||
RootedValue kept(cx, ObjectValue(*target));
|
RootedValue kept(cx, ObjectValue(*target));
|
||||||
if (!cx->runtime()->addWeakRefKeptObject(cx, kept))
|
if (!cx->runtime()->addWeakRefKeptObject(cx, kept))
|
||||||
@@ -80,7 +84,9 @@ WeakRef_deref_impl(JSContext* cx, const CallArgs& args)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(data->isSymbol());
|
MOZ_ASSERT(data->isSymbol());
|
||||||
JS::Symbol* target = data->symbolTarget.get();
|
JS::Symbol* target = data->symbolTarget.unbarrieredGet();
|
||||||
|
|
||||||
|
// Ensure pointer is not null.
|
||||||
if (target) {
|
if (target) {
|
||||||
RootedValue kept(cx, SymbolValue(target));
|
RootedValue kept(cx, SymbolValue(target));
|
||||||
if (!cx->runtime()->addWeakRefKeptObject(cx, kept))
|
if (!cx->runtime()->addWeakRefKeptObject(cx, kept))
|
||||||
|
|||||||
@@ -1235,10 +1235,9 @@ def writeCLDRLanguageTagLikelySubtagsTest(println, data, url):
|
|||||||
|
|
||||||
# Step 2: Lookup.
|
# Step 2: Lookup.
|
||||||
searches = ((language, script, region),
|
searches = ((language, script, region),
|
||||||
(language, None, region),
|
|
||||||
(language, script, None),
|
(language, script, None),
|
||||||
(language, None, None),
|
(language, None, region),
|
||||||
("und", script, None))
|
(language, None, None))
|
||||||
search = next(search for search in searches if search in likely_subtags)
|
search = next(search for search in searches if search in likely_subtags)
|
||||||
|
|
||||||
(language_s, script_s, region_s) = search
|
(language_s, script_s, region_s) = search
|
||||||
|
|||||||
@@ -714,13 +714,18 @@ class GCRuntime
|
|||||||
#endif // DEBUG
|
#endif // DEBUG
|
||||||
|
|
||||||
bool isInsideUnsafeRegion() { return inUnsafeRegion != 0; }
|
bool isInsideUnsafeRegion() { return inUnsafeRegion != 0; }
|
||||||
void enterUnsafeRegion() { ++inUnsafeRegion; }
|
void enterUnsafeRegion() {
|
||||||
|
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||||
|
++inUnsafeRegion;
|
||||||
|
}
|
||||||
void leaveUnsafeRegion() {
|
void leaveUnsafeRegion() {
|
||||||
|
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||||
MOZ_ASSERT(inUnsafeRegion > 0);
|
MOZ_ASSERT(inUnsafeRegion > 0);
|
||||||
--inUnsafeRegion;
|
--inUnsafeRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void verifyIsSafeToGC() {
|
void verifyIsSafeToGC() {
|
||||||
|
MOZ_ASSERT(CurrentThreadCanAccessRuntime(rt));
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!isInsideUnsafeRegion(),
|
MOZ_DIAGNOSTIC_ASSERT(!isInsideUnsafeRegion(),
|
||||||
"[AutoAssertNoGC] possible GC in GC-unsafe region");
|
"[AutoAssertNoGC] possible GC in GC-unsafe region");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ using namespace js;
|
|||||||
using namespace js::gc;
|
using namespace js::gc;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
IterateCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
|
IterateCompartmentsArenasCellsUnbarriered(JSContext* cx, Zone* zone, void* data,
|
||||||
JSIterateCompartmentCallback compartmentCallback,
|
JSIterateCompartmentCallback compartmentCallback,
|
||||||
IterateArenaCallback arenaCallback,
|
IterateArenaCallback arenaCallback,
|
||||||
IterateCellCallback cellCallback)
|
IterateCellCallback cellCallback)
|
||||||
@@ -34,14 +34,14 @@ IterateCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
|
|||||||
for (ArenaIter aiter(zone, thingKind); !aiter.done(); aiter.next()) {
|
for (ArenaIter aiter(zone, thingKind); !aiter.done(); aiter.next()) {
|
||||||
Arena* arena = aiter.get();
|
Arena* arena = aiter.get();
|
||||||
(*arenaCallback)(cx, data, arena, traceKind, thingSize);
|
(*arenaCallback)(cx, data, arena, traceKind, thingSize);
|
||||||
for (ArenaCellIter iter(arena); !iter.done(); iter.next())
|
for (ArenaCellIterUnbarriered iter(arena); !iter.done(); iter.next())
|
||||||
(*cellCallback)(cx, data, iter.getCell(), traceKind, thingSize);
|
(*cellCallback)(cx, data, iter.getCell(), traceKind, thingSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
js::IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
|
js::IterateHeapUnbarriered(JSContext* cx, void* data,
|
||||||
IterateZoneCallback zoneCallback,
|
IterateZoneCallback zoneCallback,
|
||||||
JSIterateCompartmentCallback compartmentCallback,
|
JSIterateCompartmentCallback compartmentCallback,
|
||||||
IterateArenaCallback arenaCallback,
|
IterateArenaCallback arenaCallback,
|
||||||
@@ -51,13 +51,13 @@ js::IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
|
|||||||
|
|
||||||
for (ZonesIter zone(cx, WithAtoms); !zone.done(); zone.next()) {
|
for (ZonesIter zone(cx, WithAtoms); !zone.done(); zone.next()) {
|
||||||
(*zoneCallback)(cx, data, zone);
|
(*zoneCallback)(cx, data, zone);
|
||||||
IterateCompartmentsArenasCells(cx, zone, data,
|
IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
|
||||||
compartmentCallback, arenaCallback, cellCallback);
|
compartmentCallback, arenaCallback, cellCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
js::IterateZoneCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
|
js::IterateHeapUnbarrieredForZone(JSContext* cx, Zone* zone, void* data,
|
||||||
IterateZoneCallback zoneCallback,
|
IterateZoneCallback zoneCallback,
|
||||||
JSIterateCompartmentCallback compartmentCallback,
|
JSIterateCompartmentCallback compartmentCallback,
|
||||||
IterateArenaCallback arenaCallback,
|
IterateArenaCallback arenaCallback,
|
||||||
@@ -66,7 +66,7 @@ js::IterateZoneCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
|
|||||||
AutoPrepareForTracing prop(cx, WithAtoms);
|
AutoPrepareForTracing prop(cx, WithAtoms);
|
||||||
|
|
||||||
(*zoneCallback)(cx, data, zone);
|
(*zoneCallback)(cx, data, zone);
|
||||||
IterateCompartmentsArenasCells(cx, zone, data,
|
IterateCompartmentsArenasCellsUnbarriered(cx, zone, data,
|
||||||
compartmentCallback, arenaCallback, cellCallback);
|
compartmentCallback, arenaCallback, cellCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-2
@@ -902,8 +902,28 @@ namespace js {
|
|||||||
// scheduledForDestruction will be set on the compartment, which will cause
|
// scheduledForDestruction will be set on the compartment, which will cause
|
||||||
// some extra GC activity to try to free the compartment.
|
// some extra GC activity to try to free the compartment.
|
||||||
template<typename T> inline void SetMaybeAliveFlag(T* thing) {}
|
template<typename T> inline void SetMaybeAliveFlag(T* thing) {}
|
||||||
template<> inline void SetMaybeAliveFlag(JSObject* thing) {thing->compartment()->maybeAlive = true;}
|
|
||||||
template<> inline void SetMaybeAliveFlag(JSScript* thing) {thing->compartment()->maybeAlive = true;}
|
template<> inline void SetMaybeAliveFlag(JSObject* thing) {
|
||||||
|
// During GC marking of WeakRefs, 'thing' might be an invalid/dangling
|
||||||
|
// pointer. Verify compartment is accessible.
|
||||||
|
if (MOZ_LIKELY(thing)) {
|
||||||
|
JSCompartment* comp = thing->compartment();
|
||||||
|
if (MOZ_LIKELY(comp)) {
|
||||||
|
comp->maybeAlive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline void SetMaybeAliveFlag(JSScript* thing) {
|
||||||
|
// During GC marking of WeakRefs, 'thing' might be an invalid/dangling
|
||||||
|
// pointer. Verify compartment is accessible.
|
||||||
|
if (MOZ_LIKELY(thing)) {
|
||||||
|
JSCompartment* comp = thing->compartment();
|
||||||
|
if (MOZ_LIKELY(comp)) {
|
||||||
|
comp->maybeAlive = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline js::Handle<js::GlobalObject*>
|
inline js::Handle<js::GlobalObject*>
|
||||||
ExclusiveContext::global() const
|
ExclusiveContext::global() const
|
||||||
|
|||||||
@@ -1148,7 +1148,7 @@ js::DumpHeap(JSContext* cx, FILE* fp, js::DumpHeapNurseryBehaviour nurseryBehavi
|
|||||||
fprintf(dtrc.output, "==========\n");
|
fprintf(dtrc.output, "==========\n");
|
||||||
|
|
||||||
dtrc.prefix = "> ";
|
dtrc.prefix = "> ";
|
||||||
IterateZonesCompartmentsArenasCells(cx, &dtrc,
|
IterateHeapUnbarriered(cx, &dtrc,
|
||||||
DumpHeapVisitZone,
|
DumpHeapVisitZone,
|
||||||
DumpHeapVisitCompartment,
|
DumpHeapVisitCompartment,
|
||||||
DumpHeapVisitArena,
|
DumpHeapVisitArena,
|
||||||
|
|||||||
+19
-10
@@ -3646,14 +3646,22 @@ GCRuntime::beginMarkPhase(JS::gcreason::Reason reason, AutoLockForExclusiveAcces
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atoms are not in the cross-compartment map. So if there are any
|
* Atoms are not in the cross-compartment map. If there are any zones that
|
||||||
* zones that are not being collected, we are not allowed to collect
|
* are not being collected then we cannot collect the atoms zone, otherwise
|
||||||
* atoms. Otherwise, the non-collected zones could contain pointers
|
* the non-collected zones could contain pointers to atoms that we would
|
||||||
* to atoms that we would miss.
|
* miss.
|
||||||
*
|
*
|
||||||
* keepAtoms() will only change on the main thread, which we are currently
|
* If keepAtoms() is true then either an instance of AutoKeepAtoms is
|
||||||
* on. If the value of keepAtoms() changes between GC slices, then we'll
|
* currently on the stack or parsing is currently happening on another
|
||||||
* cancel the incremental GC. See IsIncrementalGCSafe.
|
* thread. In either case we don't have information about which atoms are
|
||||||
|
* roots, so we must skip collecting atoms.
|
||||||
|
*
|
||||||
|
* Note that only affects the first slice of an incremental GC since root
|
||||||
|
* marking is completed before we return to the mutator.
|
||||||
|
*
|
||||||
|
* Off-main-thread parsing is inhibited after the start of GC which prevents
|
||||||
|
* races between creating atoms during parsing and sweeping atoms on the
|
||||||
|
* main thread.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (isFull && !rt->keepAtoms()) {
|
if (isFull && !rt->keepAtoms()) {
|
||||||
@@ -5610,9 +5618,6 @@ gc::IsIncrementalGCUnsafe(JSRuntime* rt)
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(!rt->mainThread.suppressGC);
|
MOZ_ASSERT(!rt->mainThread.suppressGC);
|
||||||
|
|
||||||
if (rt->keepAtoms())
|
|
||||||
return gc::AbortReason::KeepAtomsSet;
|
|
||||||
|
|
||||||
if (!rt->gc.isIncrementalGCAllowed())
|
if (!rt->gc.isIncrementalGCAllowed())
|
||||||
return gc::AbortReason::IncrementalDisabled;
|
return gc::AbortReason::IncrementalDisabled;
|
||||||
|
|
||||||
@@ -5786,6 +5791,10 @@ GCRuntime::gcCycle(bool nonincrementalByAPI, SliceBudget& budget, JS::gcreason::
|
|||||||
|
|
||||||
State prevState = incrementalState;
|
State prevState = incrementalState;
|
||||||
|
|
||||||
|
// We don't allow off-main-thread parsing to start while we're doing an
|
||||||
|
// incremental GC.
|
||||||
|
MOZ_ASSERT_IF(rt->activeGCInAtomsZone(), !rt->exclusiveThreadsPresent());
|
||||||
|
|
||||||
if (nonincrementalByAPI) {
|
if (nonincrementalByAPI) {
|
||||||
// Reset any in progress incremental GC if this was triggered via the
|
// Reset any in progress incremental GC if this was triggered via the
|
||||||
// API. This isn't required for correctness, but sometimes during tests
|
// API. This isn't required for correctness, but sometimes during tests
|
||||||
|
|||||||
+6
-3
@@ -56,7 +56,7 @@ enum class State {
|
|||||||
D(None) \
|
D(None) \
|
||||||
D(NonIncrementalRequested) \
|
D(NonIncrementalRequested) \
|
||||||
D(AbortRequested) \
|
D(AbortRequested) \
|
||||||
D(KeepAtomsSet) \
|
D(Unused1) \
|
||||||
D(IncrementalDisabled) \
|
D(IncrementalDisabled) \
|
||||||
D(ModeChange) \
|
D(ModeChange) \
|
||||||
D(MallocBytesTrigger) \
|
D(MallocBytesTrigger) \
|
||||||
@@ -1065,9 +1065,12 @@ typedef void (*IterateCellCallback)(JSRuntime* rt, void* data, void* thing,
|
|||||||
* This function calls |zoneCallback| on every zone, |compartmentCallback| on
|
* This function calls |zoneCallback| on every zone, |compartmentCallback| on
|
||||||
* every compartment, |arenaCallback| on every in-use arena, and |cellCallback|
|
* every compartment, |arenaCallback| on every in-use arena, and |cellCallback|
|
||||||
* on every in-use cell in the GC heap.
|
* on every in-use cell in the GC heap.
|
||||||
|
*
|
||||||
|
* Note that no read barrier is triggered on the cells passed to cellCallback,
|
||||||
|
* so no these pointers must not escape the callback.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
|
IterateHeapUnbarriered(JSContext* cx, void* data,
|
||||||
IterateZoneCallback zoneCallback,
|
IterateZoneCallback zoneCallback,
|
||||||
JSIterateCompartmentCallback compartmentCallback,
|
JSIterateCompartmentCallback compartmentCallback,
|
||||||
IterateArenaCallback arenaCallback,
|
IterateArenaCallback arenaCallback,
|
||||||
@@ -1078,7 +1081,7 @@ IterateZonesCompartmentsArenasCells(JSContext* cx, void* data,
|
|||||||
* single zone.
|
* single zone.
|
||||||
*/
|
*/
|
||||||
extern void
|
extern void
|
||||||
IterateZoneCompartmentsArenasCells(JSContext* cx, Zone* zone, void* data,
|
IterateHeapUnbarrieredForZone(JSContext* cx, Zone* zone, void* data,
|
||||||
IterateZoneCallback zoneCallback,
|
IterateZoneCallback zoneCallback,
|
||||||
JSIterateCompartmentCallback compartmentCallback,
|
JSIterateCompartmentCallback compartmentCallback,
|
||||||
IterateArenaCallback arenaCallback,
|
IterateArenaCallback arenaCallback,
|
||||||
|
|||||||
@@ -147,8 +147,6 @@ class ArenaCellIterImpl
|
|||||||
void init(Arena* arena, CellIterNeedsBarrier mayNeedBarrier) {
|
void init(Arena* arena, CellIterNeedsBarrier mayNeedBarrier) {
|
||||||
MOZ_ASSERT(!initialized);
|
MOZ_ASSERT(!initialized);
|
||||||
MOZ_ASSERT(arena);
|
MOZ_ASSERT(arena);
|
||||||
MOZ_ASSERT_IF(!mayNeedBarrier,
|
|
||||||
CurrentThreadIsPerformingGC() || CurrentThreadIsGCSweeping());
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
AllocKind kind = arena->getAllocKind();
|
AllocKind kind = arena->getAllocKind();
|
||||||
firstThingOffset = Arena::firstThingOffset(kind);
|
firstThingOffset = Arena::firstThingOffset(kind);
|
||||||
@@ -236,6 +234,14 @@ class ArenaCellIterUnderFinalize : public ArenaCellIterImpl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ArenaCellIterUnbarriered : public ArenaCellIterImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ArenaCellIterUnbarriered(Arena* arena)
|
||||||
|
: ArenaCellIterImpl(arena, CellIterDoesntNeedBarrier)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ZoneCellIter;
|
class ZoneCellIter;
|
||||||
|
|
||||||
|
|||||||
@@ -3940,6 +3940,8 @@ js::Unbox(JSContext* cx, HandleObject obj, MutableHandleValue vp)
|
|||||||
vp.setString(obj->as<StringObject>().unbox());
|
vp.setString(obj->as<StringObject>().unbox());
|
||||||
else if (obj->is<DateObject>())
|
else if (obj->is<DateObject>())
|
||||||
vp.set(obj->as<DateObject>().UTCTime());
|
vp.set(obj->as<DateObject>().UTCTime());
|
||||||
|
else if (obj->is<BigIntObject>())
|
||||||
|
vp.setBigInt(obj->as<BigIntObject>().unbox());
|
||||||
else
|
else
|
||||||
vp.setUndefined();
|
vp.setUndefined();
|
||||||
|
|
||||||
|
|||||||
+3
-7
@@ -158,6 +158,8 @@ class JSObject : public js::gc::Cell
|
|||||||
* object will have its group constructed lazily as needed by analysis.
|
* object will have its group constructed lazily as needed by analysis.
|
||||||
*/
|
*/
|
||||||
bool isSingleton() const {
|
bool isSingleton() const {
|
||||||
|
// In some cases, group_ might be null.
|
||||||
|
if (!group_) return false;
|
||||||
return group_->singleton();
|
return group_->singleton();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,10 +897,6 @@ GetElementNoGC(JSContext* cx, JSObject* obj, JSObject* receiver, uint32_t index,
|
|||||||
* try. Long story short, if you just want bog-standard assignment, pass
|
* try. Long story short, if you just want bog-standard assignment, pass
|
||||||
* `ObjectValue(*obj)` as receiver. Or better, use one of the signatures that
|
* `ObjectValue(*obj)` as receiver. Or better, use one of the signatures that
|
||||||
* doesn't have a receiver parameter.
|
* doesn't have a receiver parameter.
|
||||||
*
|
|
||||||
* Callers pass obj != receiver e.g. when a proxy is involved, obj is the
|
|
||||||
* proxy's target, and the proxy is using SetProperty to finish an assignment
|
|
||||||
* that started out as `receiver[id] = v`, by delegating it to obj.
|
|
||||||
*/
|
*/
|
||||||
inline bool
|
inline bool
|
||||||
SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
SetProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v,
|
||||||
@@ -1269,9 +1267,7 @@ FromPropertyDescriptorToObject(JSContext* cx, Handle<JS::PropertyDescriptor> des
|
|||||||
extern bool
|
extern bool
|
||||||
IsDelegate(JSContext* cx, HandleObject obj, const Value& v, bool* result);
|
IsDelegate(JSContext* cx, HandleObject obj, const Value& v, bool* result);
|
||||||
|
|
||||||
// obj is a JSObject*, but we root it immediately up front. We do it
|
bool
|
||||||
// that way because we need a Rooted temporary in this method anyway.
|
|
||||||
extern bool
|
|
||||||
IsDelegateOfObject(JSContext* cx, HandleObject protoObj, JSObject* obj, bool* result);
|
IsDelegateOfObject(JSContext* cx, HandleObject protoObj, JSObject* obj, bool* result);
|
||||||
|
|
||||||
/* Wrap boolean, number or string as Boolean, Number or String object. */
|
/* Wrap boolean, number or string as Boolean, Number or String object. */
|
||||||
|
|||||||
+3
-1
@@ -3954,7 +3954,9 @@ JSScript::traceChildren(JSTracer* trc)
|
|||||||
|
|
||||||
if (hasObjects()) {
|
if (hasObjects()) {
|
||||||
ObjectArray* objarray = objects();
|
ObjectArray* objarray = objects();
|
||||||
TraceRange(trc, objarray->length, objarray->vector, "objects");
|
if (objarray && objarray->length > 0 && objarray->vector) {
|
||||||
|
TraceRange(trc, objarray->length, objarray->vector, "objects");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT_IF(sourceObject(), MaybeForwarded(sourceObject())->compartment() == compartment());
|
MOZ_ASSERT_IF(sourceObject(), MaybeForwarded(sourceObject())->compartment() == compartment());
|
||||||
|
|||||||
@@ -770,7 +770,7 @@ CollectRuntimeStatsHelper(JSContext* cx, RuntimeStats* rtStats, ObjectPrivateVis
|
|||||||
StatsClosure closure(rtStats, opv, anonymize);
|
StatsClosure closure(rtStats, opv, anonymize);
|
||||||
if (!closure.init())
|
if (!closure.init())
|
||||||
return false;
|
return false;
|
||||||
IterateZonesCompartmentsArenasCells(cx, &closure,
|
IterateHeapUnbarriered(cx, &closure,
|
||||||
StatsZoneCallback,
|
StatsZoneCallback,
|
||||||
StatsCompartmentCallback,
|
StatsCompartmentCallback,
|
||||||
StatsArenaCallback,
|
StatsArenaCallback,
|
||||||
@@ -916,7 +916,7 @@ AddSizeOfTab(JSContext* cx, HandleObject obj, MallocSizeOf mallocSizeOf, ObjectP
|
|||||||
StatsClosure closure(&rtStats, opv, /* anonymize = */ false);
|
StatsClosure closure(&rtStats, opv, /* anonymize = */ false);
|
||||||
if (!closure.init())
|
if (!closure.init())
|
||||||
return false;
|
return false;
|
||||||
IterateZoneCompartmentsArenasCells(cx, zone, &closure,
|
IterateHeapUnbarrieredForZone(cx, zone, &closure,
|
||||||
StatsZoneCallback,
|
StatsZoneCallback,
|
||||||
StatsCompartmentCallback,
|
StatsCompartmentCallback,
|
||||||
StatsArenaCallback,
|
StatsArenaCallback,
|
||||||
|
|||||||
@@ -1373,16 +1373,18 @@ intrinsic_MoveTypedArrayElements(JSContext* cx, unsigned argc, Value* vp)
|
|||||||
MOZ_ASSERT((UINT32_MAX >> ElementShift) >= count);
|
MOZ_ASSERT((UINT32_MAX >> ElementShift) >= count);
|
||||||
uint32_t byteSize = count << ElementShift;
|
uint32_t byteSize = count << ElementShift;
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
{
|
{
|
||||||
uint32_t viewByteLength = tarray->byteLength();
|
uint32_t viewByteLength = tarray->byteLength();
|
||||||
MOZ_ASSERT(byteSize <= viewByteLength);
|
if (byteSize > viewByteLength ||
|
||||||
MOZ_ASSERT(byteDest < viewByteLength);
|
byteDest >= viewByteLength ||
|
||||||
MOZ_ASSERT(byteSrc < viewByteLength);
|
byteSrc >= viewByteLength ||
|
||||||
MOZ_ASSERT(byteDest <= viewByteLength - byteSize);
|
byteDest > viewByteLength - byteSize ||
|
||||||
MOZ_ASSERT(byteSrc <= viewByteLength - byteSize);
|
byteSrc > viewByteLength - byteSize) {
|
||||||
|
JS_ReportErrorNumberASCII(
|
||||||
|
cx, GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_OUT_OF_BOUNDS);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
SharedMem<uint8_t*> data = tarray->viewDataEither().cast<uint8_t*>();
|
SharedMem<uint8_t*> data = tarray->viewDataEither().cast<uint8_t*>();
|
||||||
jit::AtomicOperations::memmoveSafeWhenRacy(data + byteDest, data + byteSrc, byteSize);
|
jit::AtomicOperations::memmoveSafeWhenRacy(data + byteDest, data + byteSrc, byteSize);
|
||||||
|
|||||||
+1
-2
@@ -1740,8 +1740,7 @@ JS::ProfilingFrameIterator::ProfilingFrameIterator(JSContext* cx, const Register
|
|||||||
: rt_(cx),
|
: rt_(cx),
|
||||||
sampleBufferGen_(sampleBufferGen),
|
sampleBufferGen_(sampleBufferGen),
|
||||||
activation_(nullptr),
|
activation_(nullptr),
|
||||||
savedPrevJitTop_(nullptr),
|
savedPrevJitTop_(nullptr)
|
||||||
nogc_(cx)
|
|
||||||
{
|
{
|
||||||
if (!cx->spsProfiler.enabled())
|
if (!cx->spsProfiler.enabled())
|
||||||
MOZ_CRASH("ProfilingFrameIterator called when spsProfiler not enabled for runtime.");
|
MOZ_CRASH("ProfilingFrameIterator called when spsProfiler not enabled for runtime.");
|
||||||
|
|||||||
@@ -261,7 +261,7 @@ RestyleManager::ContentStateChanged(nsIContent* aContent,
|
|||||||
ContentStateChangedInternal(aElement, aStateMask, &changeHint, &restyleHint);
|
ContentStateChangedInternal(aElement, aStateMask, &changeHint, &restyleHint);
|
||||||
|
|
||||||
PostRestyleEvent(aElement, restyleHint, changeHint);
|
PostRestyleEvent(aElement, restyleHint, changeHint);
|
||||||
RestyleForHasPseudoClassChange(aElement);
|
RestyleForHasPseudoClassChange(aElement, aStateMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forwarded nsIMutationObserver method, to handle restyling.
|
// Forwarded nsIMutationObserver method, to handle restyling.
|
||||||
@@ -282,6 +282,12 @@ RestyleManager::AttributeWillChange(Element* aElement,
|
|||||||
aNewValue,
|
aNewValue,
|
||||||
rsdata);
|
rsdata);
|
||||||
PostRestyleEvent(aElement, rshint, nsChangeHint(0), &rsdata);
|
PostRestyleEvent(aElement, rshint, nsChangeHint(0), &rsdata);
|
||||||
|
// Class values are preparsed by Element before this notification. Compare
|
||||||
|
// membership now: AttributeChanged need not receive the previous value.
|
||||||
|
if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::_class) {
|
||||||
|
RestyleForHasPseudoClassChange(aElement, EventStates(), aAttribute,
|
||||||
|
aNewValue, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forwarded nsIMutationObserver method, to handle restyling (and
|
// Forwarded nsIMutationObserver method, to handle restyling (and
|
||||||
@@ -373,30 +379,68 @@ RestyleManager::AttributeChanged(Element* aElement,
|
|||||||
aOldValue,
|
aOldValue,
|
||||||
rsdata);
|
rsdata);
|
||||||
PostRestyleEvent(aElement, rshint, hint, &rsdata);
|
PostRestyleEvent(aElement, rshint, hint, &rsdata);
|
||||||
RestyleForHasPseudoClassChange(aElement);
|
if (aNameSpaceID != kNameSpaceID_None || aAttribute != nsGkAtoms::_class) {
|
||||||
|
RestyleForHasPseudoClassChange(aElement, EventStates(), aAttribute);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
RestyleManager::RestyleForHasPseudoClassChange(nsINode* aNode)
|
RestyleManager::RestyleForHasPseudoClassChange(nsINode* aNode,
|
||||||
|
EventStates aStateMask,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
const nsAttrValue* aNewClasses,
|
||||||
|
bool aCompareClasses)
|
||||||
{
|
{
|
||||||
Element* affectedRoot = nullptr;
|
MOZ_ASSERT(!aAttribute || aNode->IsElement());
|
||||||
|
if (!aNode->OwnerDoc()->GetProperty(nsGkAtoms::hasSelectorDependency)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Dependency = nsCSSRuleUtils::HasSelectorDependency;
|
||||||
|
auto restyleAnchor = [&](Element* aAnchor, Dependency* aDependency) {
|
||||||
|
nsRestyleHint hint = eRestyle_Subtree;
|
||||||
|
if (aDependency->mRestyleLaterSiblings) {
|
||||||
|
hint = nsRestyleHint(hint | eRestyle_LaterSiblings);
|
||||||
|
}
|
||||||
|
PostRestyleEvent(aAnchor, hint, nsChangeHint(0));
|
||||||
|
};
|
||||||
|
|
||||||
for (nsINode* node = aNode; node; node = node->GetParentNode()) {
|
for (nsINode* node = aNode; node; node = node->GetParentNode()) {
|
||||||
if (!node->GetProperty(nsGkAtoms::hasSelectorDependency)) {
|
auto* dependency = static_cast<Dependency*>(
|
||||||
|
node->GetProperty(nsGkAtoms::hasSelectorDependency));
|
||||||
|
if (!dependency) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (node->IsElement()) {
|
if (node->IsElement() && dependency->MightDependOnChange(
|
||||||
affectedRoot = node->AsElement();
|
node->AsElement(), aNode, aStateMask, aAttribute, aNewClasses,
|
||||||
} else if (ShadowRoot* shadow = ShadowRoot::FromNode(node)) {
|
aCompareClasses, false)) {
|
||||||
affectedRoot = shadow->GetHost();
|
restyleAnchor(node->AsElement(), dependency);
|
||||||
|
}
|
||||||
|
if (!dependency->MightAffectSiblingAnchor(
|
||||||
|
node, aNode, aStateMask, aAttribute, aNewClasses, aCompareClasses)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// The parent is an index of sibling anchors, not itself an anchor. Keep
|
||||||
|
// unrelated subtrees out of the restyle, including mutations deep inside
|
||||||
|
// a sibling whose :has() argument only inspects the sibling element.
|
||||||
|
bool nodeIsFollowingSibling = true;
|
||||||
|
for (nsIContent* child = node->GetFirstChild(); child;
|
||||||
|
child = child->GetNextSibling()) {
|
||||||
|
if (child == aNode) {
|
||||||
|
nodeIsFollowingSibling = false;
|
||||||
|
}
|
||||||
|
if (!child->IsElement()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto* siblingDependency = static_cast<Dependency*>(
|
||||||
|
child->GetProperty(nsGkAtoms::hasSelectorDependency));
|
||||||
|
if (siblingDependency && siblingDependency->MightDependOnChange(
|
||||||
|
child->AsElement(), aNode, aStateMask, aAttribute, aNewClasses,
|
||||||
|
aCompareClasses, true, nodeIsFollowingSibling)) {
|
||||||
|
restyleAnchor(child->AsElement(), siblingDependency);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!affectedRoot) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PostRestyleEvent(affectedRoot, eRestyle_Subtree, nsChangeHint(0));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ uint64_t
|
/* static */ uint64_t
|
||||||
@@ -425,9 +469,7 @@ RestyleManager::RestyleForAppend(nsIContent* aContainer,
|
|||||||
nsIContent* aFirstNewContent)
|
nsIContent* aFirstNewContent)
|
||||||
{
|
{
|
||||||
// The container cannot be a document, but might be a ShadowRoot.
|
// The container cannot be a document, but might be a ShadowRoot.
|
||||||
if (RestyleForHasPseudoClassChange(aContainer)) {
|
RestyleForHasPseudoClassChange(aContainer);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aContainer->IsElement()) {
|
if (!aContainer->IsElement()) {
|
||||||
return;
|
return;
|
||||||
@@ -518,9 +560,7 @@ RestyleManager::RestyleForInsertOrChange(nsINode* aContainer,
|
|||||||
nsIContent* aChild)
|
nsIContent* aChild)
|
||||||
{
|
{
|
||||||
// The container might be a document or a ShadowRoot.
|
// The container might be a document or a ShadowRoot.
|
||||||
if (RestyleForHasPseudoClassChange(aContainer)) {
|
RestyleForHasPseudoClassChange(aContainer);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aContainer->IsElement()) {
|
if (!aContainer->IsElement()) {
|
||||||
return;
|
return;
|
||||||
@@ -612,9 +652,7 @@ RestyleManager::ContentRemoved(nsINode* aContainer,
|
|||||||
nsIContent* aFollowingSibling)
|
nsIContent* aFollowingSibling)
|
||||||
{
|
{
|
||||||
// The container might be a document or a ShadowRoot.
|
// The container might be a document or a ShadowRoot.
|
||||||
if (RestyleForHasPseudoClassChange(aContainer)) {
|
RestyleForHasPseudoClassChange(aContainer);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aContainer->IsElement()) {
|
if (!aContainer->IsElement()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -314,9 +314,14 @@ public:
|
|||||||
// the container is null, no work is needed.
|
// the container is null, no work is needed.
|
||||||
void RestyleForAppend(nsIContent* aContainer, nsIContent* aFirstNewContent);
|
void RestyleForAppend(nsIContent* aContainer, nsIContent* aFirstNewContent);
|
||||||
|
|
||||||
// Restyle a subtree containing any :has() anchor affected by a change at
|
// Restyle affected :has() anchors, retaining normal mutation invalidation.
|
||||||
// or below aNode. Returns true when such a restyle was posted.
|
// With no state/attribute, aNode is the container of a content mutation.
|
||||||
bool RestyleForHasPseudoClassChange(nsINode* aNode);
|
// Class changes are compared before mutation, while both values are known.
|
||||||
|
void RestyleForHasPseudoClassChange(nsINode* aNode,
|
||||||
|
EventStates aStateMask = EventStates(),
|
||||||
|
nsIAtom* aAttribute = nullptr,
|
||||||
|
const nsAttrValue* aNewClasses = nullptr,
|
||||||
|
bool aCompareClasses = false);
|
||||||
|
|
||||||
// Process any pending restyles. This should be called after
|
// Process any pending restyles. This should be called after
|
||||||
// CreateNeededFrames.
|
// CreateNeededFrames.
|
||||||
|
|||||||
@@ -185,15 +185,18 @@ struct InlineBackgroundData
|
|||||||
mPIStartBorderData.SetCoord(joinedBorderArea.x);
|
mPIStartBorderData.SetCoord(joinedBorderArea.x);
|
||||||
}
|
}
|
||||||
} else if (mPIStartBorderData.mFrame) {
|
} else if (mPIStartBorderData.mFrame) {
|
||||||
|
// Copy data to a temporary object so that computing the
|
||||||
|
// continous rect here doesn't clobber our normal state.
|
||||||
|
InlineBackgroundData temp = *this;
|
||||||
if (mVertical) {
|
if (mVertical) {
|
||||||
mPIStartBorderData.SetCoord(GetContinuousRect(mPIStartBorderData.mFrame).y);
|
mPIStartBorderData.SetCoord(temp.GetContinuousRect(mPIStartBorderData.mFrame).y);
|
||||||
} else {
|
} else {
|
||||||
mPIStartBorderData.SetCoord(GetContinuousRect(mPIStartBorderData.mFrame).x);
|
mPIStartBorderData.SetCoord(temp.GetContinuousRect(mPIStartBorderData.mFrame).x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// ... and restore it when possible.
|
// ... and restore it when possible.
|
||||||
mPIStartBorderData.mCoord = saved.mCoord;
|
mPIStartBorderData.SetCoord(saved.mCoord);
|
||||||
}
|
}
|
||||||
if (mVertical) {
|
if (mVertical) {
|
||||||
if (joinedBorderArea.y > mPIStartBorderData.mCoord) {
|
if (joinedBorderArea.y > mPIStartBorderData.mCoord) {
|
||||||
@@ -342,6 +345,7 @@ protected:
|
|||||||
// Start with the previous flow frame as our continuation point
|
// Start with the previous flow frame as our continuation point
|
||||||
// is the total of the widths of the previous frames.
|
// is the total of the widths of the previous frames.
|
||||||
nsIFrame* inlineFrame = GetPrevContinuation(aFrame);
|
nsIFrame* inlineFrame = GetPrevContinuation(aFrame);
|
||||||
|
bool changedLines = false;
|
||||||
while (inlineFrame) {
|
while (inlineFrame) {
|
||||||
if (!mPIStartBorderData.mFrame &&
|
if (!mPIStartBorderData.mFrame &&
|
||||||
!(mVertical ? inlineFrame->GetSkipSides().Top()
|
!(mVertical ? inlineFrame->GetSkipSides().Top()
|
||||||
@@ -350,8 +354,9 @@ protected:
|
|||||||
}
|
}
|
||||||
nsRect rect = inlineFrame->GetRect();
|
nsRect rect = inlineFrame->GetRect();
|
||||||
mContinuationPoint += mVertical ? rect.height : rect.width;
|
mContinuationPoint += mVertical ? rect.height : rect.width;
|
||||||
if (mBidiEnabled && !AreOnSameLine(aFrame, inlineFrame)) {
|
if (mBidiEnabled && (changedLines || !AreOnSameLine(aFrame, inlineFrame))) {
|
||||||
mLineContinuationPoint += mVertical ? rect.height : rect.width;
|
mLineContinuationPoint += mVertical ? rect.height : rect.width;
|
||||||
|
changedLines = true;
|
||||||
}
|
}
|
||||||
mUnbrokenMeasure += mVertical ? rect.height : rect.width;
|
mUnbrokenMeasure += mVertical ? rect.height : rect.width;
|
||||||
mBoundingBox.UnionRect(mBoundingBox, rect);
|
mBoundingBox.UnionRect(mBoundingBox, rect);
|
||||||
|
|||||||
@@ -2166,20 +2166,20 @@ nsFrameSelection::CommonPageMove(bool aForward,
|
|||||||
//get the frame from the scrollable view
|
//get the frame from the scrollable view
|
||||||
|
|
||||||
nsIFrame* scrolledFrame = aScrollableFrame->GetScrolledFrame();
|
nsIFrame* scrolledFrame = aScrollableFrame->GetScrolledFrame();
|
||||||
if (!scrolledFrame) [[unlikely]] {
|
if MOZ_UNLIKELY(!scrolledFrame) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find out where the caret is.
|
// find out where the caret is.
|
||||||
// we should know mDesiredPos value of nsFrameSelection, but I havent seen that behavior in other windows applications yet.
|
// we should know mDesiredPos value of nsFrameSelection, but I havent seen that behavior in other windows applications yet.
|
||||||
nsISelection* domSel = GetSelection(SelectionType::eNormal);
|
nsISelection* domSel = GetSelection(SelectionType::eNormal);
|
||||||
if (!domSel) [[unlikely]] {
|
if MOZ_UNLIKELY(!domSel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect caretPos;
|
nsRect caretPos;
|
||||||
nsIFrame* caretFrame = nsCaret::GetGeometry(domSel, &caretPos);
|
nsIFrame* caretFrame = nsCaret::GetGeometry(domSel, &caretPos);
|
||||||
if (!caretFrame) [[unlikely]] {
|
if MOZ_UNLIKELY(!caretFrame) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2200,7 +2200,7 @@ nsFrameSelection::CommonPageMove(bool aForward,
|
|||||||
desiredPoint.y = caretPos.y + caretPos.height/2;
|
desiredPoint.y = caretPos.y + caretPos.height/2;
|
||||||
nsIFrame::ContentOffsets offsets = scrolledFrame->GetContentOffsetsFromPoint(desiredPoint);
|
nsIFrame::ContentOffsets offsets = scrolledFrame->GetContentOffsetsFromPoint(desiredPoint);
|
||||||
|
|
||||||
if (!offsets.content) [[unlikely]] {
|
if MOZ_UNLIKELY(!offsets.content) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2846,7 +2846,12 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent,
|
|||||||
if (!mDomSelections[index])
|
if (!mDomSelections[index])
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsTableWrapperFrame* tableFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
// This is needed as an nsTableWrapperFrame as we use this to know we can
|
||||||
|
// static cast tableFrame to nsTableWrapperFrame.
|
||||||
|
nsTableWrapperFrame* tableWrapperFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
||||||
|
|
||||||
|
// Declared as weak frame, as the frame may be freed during a call to a listener.
|
||||||
|
nsWeakFrame tableFrame(tableWrapperFrame);
|
||||||
if (!tableFrame)
|
if (!tableFrame)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
@@ -2878,6 +2883,9 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent,
|
|||||||
curColIndex < minColIndex || curColIndex > maxColIndex) {
|
curColIndex < minColIndex || curColIndex > maxColIndex) {
|
||||||
|
|
||||||
mDomSelections[index]->RemoveRange(range);
|
mDomSelections[index]->RemoveRange(range);
|
||||||
|
if (!tableFrame.IsAlive()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
// Since we've removed the range, decrement pointer to next range
|
// Since we've removed the range, decrement pointer to next range
|
||||||
mSelectedCellIndex--;
|
mSelectedCellIndex--;
|
||||||
}
|
}
|
||||||
@@ -2885,21 +2893,30 @@ nsFrameSelection::UnselectCells(nsIContent *aTableContent,
|
|||||||
} else {
|
} else {
|
||||||
// Remove cell from selection if it belongs to the given cells range or
|
// Remove cell from selection if it belongs to the given cells range or
|
||||||
// it is spanned onto the cells range.
|
// it is spanned onto the cells range.
|
||||||
|
|
||||||
|
MOZ_ASSERT(tableFrame.IsAlive());
|
||||||
|
// In general, static casting to another table type is not a good idea,
|
||||||
|
// but it is valid here due to the earlier do_QueryFrame() that
|
||||||
|
// established that tableFrame is an nsTableWrapperFrame*.
|
||||||
|
auto tempTableFrame = static_cast<nsTableWrapperFrame*>(tableFrame.GetFrame());
|
||||||
nsTableCellFrame* cellFrame =
|
nsTableCellFrame* cellFrame =
|
||||||
tableFrame->GetCellFrameAt(curRowIndex, curColIndex);
|
tempTableFrame->GetCellFrameAt(curRowIndex, curColIndex);
|
||||||
|
|
||||||
uint32_t origRowIndex = cellFrame->RowIndex();
|
uint32_t origRowIndex = cellFrame->RowIndex();
|
||||||
uint32_t origColIndex = cellFrame->ColIndex();
|
uint32_t origColIndex = cellFrame->ColIndex();
|
||||||
uint32_t actualRowSpan =
|
uint32_t actualRowSpan =
|
||||||
tableFrame->GetEffectiveRowSpanAt(origRowIndex, origColIndex);
|
tempTableFrame->GetEffectiveRowSpanAt(origRowIndex, origColIndex);
|
||||||
uint32_t actualColSpan =
|
uint32_t actualColSpan =
|
||||||
tableFrame->GetEffectiveColSpanAt(curRowIndex, curColIndex);
|
tempTableFrame->GetEffectiveColSpanAt(curRowIndex, curColIndex);
|
||||||
if (origRowIndex <= static_cast<uint32_t>(maxRowIndex) && maxRowIndex >= 0 &&
|
if (origRowIndex <= static_cast<uint32_t>(maxRowIndex) && maxRowIndex >= 0 &&
|
||||||
origRowIndex + actualRowSpan - 1 >= static_cast<uint32_t>(minRowIndex) &&
|
origRowIndex + actualRowSpan - 1 >= static_cast<uint32_t>(minRowIndex) &&
|
||||||
origColIndex <= static_cast<uint32_t>(maxColIndex) && maxColIndex >= 0 &&
|
origColIndex <= static_cast<uint32_t>(maxColIndex) && maxColIndex >= 0 &&
|
||||||
origColIndex + actualColSpan - 1 >= static_cast<uint32_t>(minColIndex)) {
|
origColIndex + actualColSpan - 1 >= static_cast<uint32_t>(minColIndex)) {
|
||||||
|
|
||||||
mDomSelections[index]->RemoveRange(range);
|
mDomSelections[index]->RemoveRange(range);
|
||||||
|
if (!tableFrame.IsAlive()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
// Since we've removed the range, decrement pointer to next range
|
// Since we've removed the range, decrement pointer to next range
|
||||||
mSelectedCellIndex--;
|
mSelectedCellIndex--;
|
||||||
}
|
}
|
||||||
@@ -2925,7 +2942,12 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
|||||||
if (!mDomSelections[index])
|
if (!mDomSelections[index])
|
||||||
return NS_ERROR_NULL_POINTER;
|
return NS_ERROR_NULL_POINTER;
|
||||||
|
|
||||||
nsTableWrapperFrame* tableFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
// This is needed as an nsTableWrapperFrame as we use this to know we can
|
||||||
|
// static cast tableFrame to nsTableWrapperFrame.
|
||||||
|
nsTableWrapperFrame* tableWrapperFrame = do_QueryFrame(aTableContent->GetPrimaryFrame());
|
||||||
|
|
||||||
|
// Declared as weak frame, as the frame may be freed during a call to a listener.
|
||||||
|
nsWeakFrame tableFrame(tableWrapperFrame);
|
||||||
if (!tableFrame) // Check that |table| is a table.
|
if (!tableFrame) // Check that |table| is a table.
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
@@ -2936,7 +2958,12 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
|||||||
uint32_t col = aStartColumnIndex;
|
uint32_t col = aStartColumnIndex;
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
nsTableCellFrame* cellFrame = tableFrame->GetCellFrameAt(row, col);
|
MOZ_ASSERT(tableFrame.IsAlive());
|
||||||
|
// In general, static casting to another table type is not a good idea,
|
||||||
|
// but it is valid here due to the earlier do_QueryFrame() that
|
||||||
|
// established that tableFrame is an nsTableWrapperFrame*.
|
||||||
|
nsTableCellFrame* cellFrame =
|
||||||
|
static_cast<nsTableWrapperFrame*>(tableFrame.GetFrame())->GetCellFrameAt(row, col);
|
||||||
|
|
||||||
// Skip cells that are spanned from previous locations or are already selected
|
// Skip cells that are spanned from previous locations or are already selected
|
||||||
if (cellFrame) {
|
if (cellFrame) {
|
||||||
@@ -2944,7 +2971,9 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
|||||||
uint32_t origCol = cellFrame->ColIndex();
|
uint32_t origCol = cellFrame->ColIndex();
|
||||||
if (origRow == row && origCol == col && !cellFrame->IsSelected()) {
|
if (origRow == row && origCol == col && !cellFrame->IsSelected()) {
|
||||||
result = SelectCellElement(cellFrame->GetContent());
|
result = SelectCellElement(cellFrame->GetContent());
|
||||||
if (NS_FAILED(result)) return result;
|
if (NS_FAILED(result) || !tableFrame.IsAlive()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Done when we reach end column
|
// Done when we reach end column
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "nsNameSpaceManager.h"
|
#include "nsNameSpaceManager.h"
|
||||||
#include "nsXMLNameSpaceMap.h"
|
#include "nsXMLNameSpaceMap.h"
|
||||||
#include "nsCSSParser.h"
|
#include "nsCSSParser.h"
|
||||||
|
#include "nsCSSRuleUtils.h"
|
||||||
#include "nsCSSPseudoClasses.h"
|
#include "nsCSSPseudoClasses.h"
|
||||||
#include "nsCSSAnonBoxes.h"
|
#include "nsCSSAnonBoxes.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
@@ -1009,6 +1010,7 @@ nsCSSSelectorList::~nsCSSSelectorList()
|
|||||||
nsCSSSelector*
|
nsCSSSelector*
|
||||||
nsCSSSelectorList::AddSelector(char16_t aOperator)
|
nsCSSSelectorList::AddSelector(char16_t aOperator)
|
||||||
{
|
{
|
||||||
|
mHasSelectorData = nullptr;
|
||||||
nsCSSSelector* newSel = new nsCSSSelector();
|
nsCSSSelector* newSel = new nsCSSSelector();
|
||||||
|
|
||||||
if (mSelectors) {
|
if (mSelectors) {
|
||||||
@@ -1026,6 +1028,7 @@ nsCSSSelectorList::AddSelector(char16_t aOperator)
|
|||||||
void
|
void
|
||||||
nsCSSSelectorList::RemoveRightmostSelector()
|
nsCSSSelectorList::RemoveRightmostSelector()
|
||||||
{
|
{
|
||||||
|
mHasSelectorData = nullptr;
|
||||||
nsCSSSelector* current = mSelectors;
|
nsCSSSelector* current = mSelectors;
|
||||||
mSelectors = mSelectors->mNext;
|
mSelectors = mSelectors->mNext;
|
||||||
MOZ_ASSERT(mSelectors,
|
MOZ_ASSERT(mSelectors,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
class nsIAtom;
|
class nsIAtom;
|
||||||
struct nsCSSSelectorList;
|
struct nsCSSSelectorList;
|
||||||
|
struct nsCSSHasSelectorData;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
enum class CSSPseudoClassType : uint8_t;
|
enum class CSSPseudoClassType : uint8_t;
|
||||||
@@ -318,6 +319,9 @@ struct nsCSSSelectorList {
|
|||||||
// stored as their leftmost selector. This flag keeps that implementation
|
// stored as their leftmost selector. This flag keeps that implementation
|
||||||
// detail out of serialization and is preserved by cloning.
|
// detail out of serialization and is preserved by cloning.
|
||||||
bool mIsRelativeSelector;
|
bool mIsRelativeSelector;
|
||||||
|
// Immutable dependency metadata, collected lazily for a :has() argument.
|
||||||
|
// Nodes retain this data independently of the stylesheet's lifetime.
|
||||||
|
RefPtr<nsCSSHasSelectorData> mHasSelectorData;
|
||||||
protected:
|
protected:
|
||||||
friend class inDOMUtils;
|
friend class inDOMUtils;
|
||||||
nsCSSSelectorList* Clone(bool aDeep) const;
|
nsCSSSelectorList* Clone(bool aDeep) const;
|
||||||
|
|||||||
@@ -77,9 +77,9 @@ CSS_PSEUDO_CLASS(is, ":is", 0, "layout.css.is-where-pseudo.enabled")
|
|||||||
CSS_PSEUDO_CLASS(matches, ":matches", 0, "layout.css.is-where-pseudo.enabled")
|
CSS_PSEUDO_CLASS(matches, ":matches", 0, "layout.css.is-where-pseudo.enabled")
|
||||||
CSS_PSEUDO_CLASS(any, ":any", 0, "layout.css.is-where-pseudo.enabled")
|
CSS_PSEUDO_CLASS(any, ":any", 0, "layout.css.is-where-pseudo.enabled")
|
||||||
CSS_PSEUDO_CLASS(where, ":where", 0, "layout.css.is-where-pseudo.enabled")
|
CSS_PSEUDO_CLASS(where, ":where", 0, "layout.css.is-where-pseudo.enabled")
|
||||||
CSS_PSEUDO_CLASS(has, ":has", 0, "")
|
CSS_PSEUDO_CLASS(has, ":has", 0, "layout.css.has-pseudo.enabled")
|
||||||
CSS_PSEUDO_CLASS(mozHasRelativeAnchor, ":-moz-has-relative-anchor",
|
CSS_PSEUDO_CLASS(mozHasRelativeAnchor, ":-moz-has-relative-anchor",
|
||||||
CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "")
|
CSS_PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME, "layout.css.has-pseudo.enabled")
|
||||||
|
|
||||||
CSS_PSEUDO_CLASS(firstChild, ":first-child", 0, "")
|
CSS_PSEUDO_CLASS(firstChild, ":first-child", 0, "")
|
||||||
CSS_PSEUDO_CLASS(firstNode, ":-moz-first-node", 0, "")
|
CSS_PSEUDO_CLASS(firstNode, ":-moz-first-node", 0, "")
|
||||||
|
|||||||
+331
-10
@@ -642,6 +642,10 @@ nsCSSRuleUtils::SelectorMatches(Element* aElement,
|
|||||||
{
|
{
|
||||||
NS_PRECONDITION(!aSelector->IsPseudoElement(),
|
NS_PRECONDITION(!aSelector->IsPseudoElement(),
|
||||||
"Pseudo-element snuck into SelectorMatches?");
|
"Pseudo-element snuck into SelectorMatches?");
|
||||||
|
AutoRestore<bool> laterSiblingsRestorer(
|
||||||
|
aTreeMatchContext.mHasSelectorLaterSiblings);
|
||||||
|
aTreeMatchContext.mHasSelectorLaterSiblings |=
|
||||||
|
aSelector->mOperator == '+' || aSelector->mOperator == '~';
|
||||||
MOZ_ASSERT(aTreeMatchContext.mForStyling ||
|
MOZ_ASSERT(aTreeMatchContext.mForStyling ||
|
||||||
!aNodeMatchContext.mIsRelevantLink,
|
!aNodeMatchContext.mIsRelevantLink,
|
||||||
"mIsRelevantLink should be set to false when mForStyling "
|
"mIsRelevantLink should be set to false when mForStyling "
|
||||||
@@ -1722,6 +1726,291 @@ matchesSubtree(nsIContent* aRoot,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using HasSelectorDependency = nsCSSRuleUtils::HasSelectorDependency;
|
||||||
|
|
||||||
|
static void
|
||||||
|
AddHasDependencyAtom(nsTArray<nsCOMPtr<nsIAtom>>& aAtoms, nsIAtom* aAtom)
|
||||||
|
{
|
||||||
|
if (!aAtoms.Contains(aAtom)) {
|
||||||
|
aAtoms.AppendElement(aAtom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect every branch before matching, including :is() and legacy :not().
|
||||||
|
void
|
||||||
|
nsCSSHasSelectorData::Branch::AddSelector(nsCSSSelector* aSelector)
|
||||||
|
{
|
||||||
|
for (nsCSSSelector* selector = aSelector; selector; selector = selector->mNext) {
|
||||||
|
if (selector->mIDList) {
|
||||||
|
AddHasDependencyAtom(mAttributes, nsGkAtoms::id);
|
||||||
|
}
|
||||||
|
for (nsAtomList* cls = selector->mClassList; cls; cls = cls->mNext) {
|
||||||
|
AddHasDependencyAtom(mClasses, cls->mAtom);
|
||||||
|
}
|
||||||
|
for (nsAttrSelector* attr = selector->mAttrList; attr; attr = attr->mNext) {
|
||||||
|
// Include both spellings and conservatively ignore namespaces here.
|
||||||
|
AddHasDependencyAtom(mAttributes, attr->mLowercaseAttr);
|
||||||
|
AddHasDependencyAtom(mAttributes, attr->mCasedAttr);
|
||||||
|
}
|
||||||
|
for (nsPseudoClassList* pseudo = selector->mPseudoClassList;
|
||||||
|
pseudo; pseudo = pseudo->mNext) {
|
||||||
|
mStates |= nsCSSPseudoClasses::sPseudoClassStateDependences[
|
||||||
|
static_cast<CSSPseudoClassTypeBase>(pseudo->mType)];
|
||||||
|
if (nsCSSPseudoClasses::HasSelectorListArg(pseudo->mType)) {
|
||||||
|
for (nsCSSSelectorList* list = pseudo->u.mSelectorList;
|
||||||
|
list; list = list->mNext) {
|
||||||
|
AddSelector(list->mSelectors);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (pseudo->mType) {
|
||||||
|
case CSSPseudoClassType::mozHasRelativeAnchor:
|
||||||
|
case CSSPseudoClassType::empty:
|
||||||
|
case CSSPseudoClassType::mozOnlyWhitespace:
|
||||||
|
case CSSPseudoClassType::mozEmptyExceptChildrenWithLocalname:
|
||||||
|
case CSSPseudoClassType::root:
|
||||||
|
case CSSPseudoClassType::scope:
|
||||||
|
case CSSPseudoClassType::firstChild:
|
||||||
|
case CSSPseudoClassType::lastChild:
|
||||||
|
case CSSPseudoClassType::onlyChild:
|
||||||
|
case CSSPseudoClassType::firstNode:
|
||||||
|
case CSSPseudoClassType::lastNode:
|
||||||
|
case CSSPseudoClassType::firstOfType:
|
||||||
|
case CSSPseudoClassType::lastOfType:
|
||||||
|
case CSSPseudoClassType::onlyOfType:
|
||||||
|
case CSSPseudoClassType::nthChild:
|
||||||
|
case CSSPseudoClassType::nthLastChild:
|
||||||
|
case CSSPseudoClassType::nthOfType:
|
||||||
|
case CSSPseudoClassType::nthLastOfType:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Pseudo-classes can depend on attributes implicitly (:lang(),
|
||||||
|
// :dir(), form states, etc.). Keep those cases conservative.
|
||||||
|
mAllAttributes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (selector->mNegations) {
|
||||||
|
AddSelector(selector->mNegations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsCSSHasSelectorData::Branch::Merge(const Branch& aOther)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mCombinator == aOther.mCombinator && mIsLocal == aOther.mIsLocal);
|
||||||
|
mStates |= aOther.mStates;
|
||||||
|
mAllAttributes |= aOther.mAllAttributes;
|
||||||
|
for (nsIAtom* attr : aOther.mAttributes) {
|
||||||
|
AddHasDependencyAtom(mAttributes, attr);
|
||||||
|
}
|
||||||
|
for (nsIAtom* cls : aOther.mClasses) {
|
||||||
|
AddHasDependencyAtom(mClasses, cls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
HasSelectorDependency::AddSelectorData(nsCSSHasSelectorData* aData, bool aSibling)
|
||||||
|
{
|
||||||
|
auto& lastSelector = aSibling ? mLastSiblingSelector : mLastSelector;
|
||||||
|
if (lastSelector == aData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto& branches = aSibling ? mSiblingBranches : mBranches;
|
||||||
|
for (const auto& source : aData->mBranches) {
|
||||||
|
if (aSibling && !source.IsSibling()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
nsCSSHasSelectorData::Branch* destination = nullptr;
|
||||||
|
for (auto& branch : branches) {
|
||||||
|
if (branch.mCombinator == source.mCombinator &&
|
||||||
|
branch.mIsLocal == source.mIsLocal) {
|
||||||
|
destination = &branch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (destination) {
|
||||||
|
destination->Merge(source);
|
||||||
|
} else {
|
||||||
|
branches.AppendElement(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastSelector = aData;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A local compound cannot observe children, ancestors, or state propagated
|
||||||
|
// from descendants. Keep structural/state/complex functional arguments on the
|
||||||
|
// conservative path; plain :is()/:not() compounds are safe to narrow.
|
||||||
|
static bool
|
||||||
|
IsLocalHasCompound(nsCSSSelector* aSelector)
|
||||||
|
{
|
||||||
|
for (nsPseudoClassList* pseudo = aSelector->mPseudoClassList;
|
||||||
|
pseudo; pseudo = pseudo->mNext) {
|
||||||
|
switch (pseudo->mType) {
|
||||||
|
case CSSPseudoClassType::is:
|
||||||
|
case CSSPseudoClassType::matches:
|
||||||
|
case CSSPseudoClassType::any:
|
||||||
|
case CSSPseudoClassType::where:
|
||||||
|
case CSSPseudoClassType::mozAny:
|
||||||
|
case CSSPseudoClassType::mozAnyPrivate:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (nsCSSSelectorList* list = pseudo->u.mSelectorList;
|
||||||
|
list; list = list->mNext) {
|
||||||
|
if (list->mSelectors &&
|
||||||
|
(list->mSelectors->mNext || !IsLocalHasCompound(list->mSelectors))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (nsCSSSelector* negation = aSelector->mNegations;
|
||||||
|
negation; negation = negation->mNegations) {
|
||||||
|
if (negation->mNext || !IsLocalHasCompound(negation)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCSSHasSelectorData::nsCSSHasSelectorData(nsCSSSelectorList* aList)
|
||||||
|
{
|
||||||
|
for (nsCSSSelectorList* list = aList; list; list = list->mNext) {
|
||||||
|
Branch* branch = mBranches.AppendElement();
|
||||||
|
branch->AddSelector(list->mSelectors);
|
||||||
|
nsCSSSelector* anchor = list->mSelectors;
|
||||||
|
while (anchor->mNext) {
|
||||||
|
anchor = anchor->mNext;
|
||||||
|
}
|
||||||
|
branch->mCombinator = anchor->mOperator;
|
||||||
|
branch->mIsLocal = list->mSelectors->mNext == anchor &&
|
||||||
|
IsLocalHasCompound(list->mSelectors);
|
||||||
|
mHasSibling |= branch->IsSibling();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsCSSHasSelectorData::Branch::MightDependOnAttribute(
|
||||||
|
Element* aElement, nsIAtom* aAttribute, const nsAttrValue* aNewClasses,
|
||||||
|
bool aCompareClasses) const
|
||||||
|
{
|
||||||
|
if (mAllAttributes || mAttributes.Contains(aAttribute)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (aAttribute != nsGkAtoms::_class) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const nsAttrValue* classes = aElement->GetClasses();
|
||||||
|
nsCaseTreatment caseTreatment =
|
||||||
|
aElement->OwnerDoc()->GetCompatibilityMode() == eCompatibility_NavQuirks
|
||||||
|
? eIgnoreCase : eCaseMatters;
|
||||||
|
for (nsIAtom* cls : mClasses) {
|
||||||
|
bool hadClass = classes && classes->Contains(cls, caseTreatment);
|
||||||
|
if (aCompareClasses) {
|
||||||
|
bool hasClass = aNewClasses && aNewClasses->Contains(cls, caseTreatment);
|
||||||
|
if (hadClass != hasClass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (hadClass) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HasSelectorDependency::MightDependOnChange(
|
||||||
|
Element* aAnchor, nsINode* aNode, EventStates aStateMask,
|
||||||
|
nsIAtom* aAttribute, const nsAttrValue* aNewClasses,
|
||||||
|
bool aCompareClasses, bool aSibling, bool aNodeIsFollowingSibling) const
|
||||||
|
{
|
||||||
|
bool contentChange = !aAttribute && aStateMask.IsEmpty();
|
||||||
|
for (const auto& branch : mBranches) {
|
||||||
|
if (branch.IsSibling() != aSibling ||
|
||||||
|
(!aStateMask.IsEmpty() &&
|
||||||
|
!branch.mStates.HasAtLeastOneOfStates(aStateMask)) ||
|
||||||
|
(aAttribute && !branch.MightDependOnAttribute(
|
||||||
|
aNode->AsElement(), aAttribute, aNewClasses, aCompareClasses))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (branch.mIsLocal) {
|
||||||
|
if (aSibling) {
|
||||||
|
nsINode* parent = aAnchor->GetParentNode();
|
||||||
|
if (contentChange) {
|
||||||
|
// Changing a sibling's contents cannot affect a local compound.
|
||||||
|
if (aNode != parent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (aNode->GetParentNode() != parent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (branch.mCombinator == '+') {
|
||||||
|
if (aAnchor->GetNextElementSibling() != aNode) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (!aNodeIsFollowingSibling) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (branch.mCombinator == '>') {
|
||||||
|
if (contentChange ? aNode != aAnchor
|
||||||
|
: aNode->GetParentNode() != aAnchor) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
HasSelectorDependency::MightAffectSiblingAnchor(
|
||||||
|
nsINode* aParent, nsINode* aNode, EventStates aStateMask,
|
||||||
|
nsIAtom* aAttribute, const nsAttrValue* aNewClasses,
|
||||||
|
bool aCompareClasses) const
|
||||||
|
{
|
||||||
|
bool contentChange = !aAttribute && aStateMask.IsEmpty();
|
||||||
|
for (const auto& branch : mSiblingBranches) {
|
||||||
|
if (!branch.IsSibling() ||
|
||||||
|
(branch.mIsLocal && (contentChange ? aNode != aParent
|
||||||
|
: aNode->GetParentNode() != aParent)) ||
|
||||||
|
(!aStateMask.IsEmpty() &&
|
||||||
|
!branch.mStates.HasAtLeastOneOfStates(aStateMask)) ||
|
||||||
|
(aAttribute && !branch.MightDependOnAttribute(
|
||||||
|
aNode->AsElement(), aAttribute, aNewClasses, aCompareClasses))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DeleteHasSelectorDependency(void*, nsIAtom*, void* aValue, void*)
|
||||||
|
{
|
||||||
|
delete static_cast<HasSelectorDependency*>(aValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HasSelectorDependency*
|
||||||
|
EnsureHasSelectorDependency(nsINode* aNode)
|
||||||
|
{
|
||||||
|
auto* dependency = static_cast<HasSelectorDependency*>(
|
||||||
|
aNode->GetProperty(nsGkAtoms::hasSelectorDependency));
|
||||||
|
if (!dependency) {
|
||||||
|
dependency = new HasSelectorDependency;
|
||||||
|
if (NS_FAILED(aNode->SetProperty(nsGkAtoms::hasSelectorDependency, dependency,
|
||||||
|
DeleteHasSelectorDependency))) {
|
||||||
|
delete dependency;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dependency;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
nsCSSRuleUtils::RelativeSelectorListMatches(
|
nsCSSRuleUtils::RelativeSelectorListMatches(
|
||||||
Element* aAnchor,
|
Element* aAnchor,
|
||||||
@@ -1731,17 +2020,23 @@ nsCSSRuleUtils::RelativeSelectorListMatches(
|
|||||||
MOZ_ASSERT(aAnchor);
|
MOZ_ASSERT(aAnchor);
|
||||||
MOZ_ASSERT(aList);
|
MOZ_ASSERT(aList);
|
||||||
|
|
||||||
// :has() reverses the usual direction of selector invalidation. The
|
|
||||||
// restyle manager uses these conservative markers to promote changes in the
|
|
||||||
// anchor's descendants, or in following sibling subtrees, back to a subtree
|
|
||||||
// that contains the anchor.
|
|
||||||
if (aTreeMatchContext.mForStyling) {
|
if (aTreeMatchContext.mForStyling) {
|
||||||
aAnchor->SetProperty(nsGkAtoms::hasSelectorDependency,
|
if (!aList->mHasSelectorData) {
|
||||||
reinterpret_cast<void*>(1));
|
aList->mHasSelectorData = new nsCSSHasSelectorData(aList);
|
||||||
nsIContent* parent = aAnchor->GetParent();
|
}
|
||||||
if (parent) {
|
const auto& data = aList->mHasSelectorData;
|
||||||
parent->SetProperty(nsGkAtoms::hasSelectorDependency,
|
// The document marker makes mutations in documents without styled :has()
|
||||||
reinterpret_cast<void*>(1));
|
// selectors a constant-time no-op. All markers use the same property type.
|
||||||
|
EnsureHasSelectorDependency(aAnchor->OwnerDoc());
|
||||||
|
if (auto* dependency = EnsureHasSelectorDependency(aAnchor)) {
|
||||||
|
dependency->AddSelectorData(data, false);
|
||||||
|
dependency->mRestyleLaterSiblings |=
|
||||||
|
aTreeMatchContext.mHasSelectorLaterSiblings;
|
||||||
|
}
|
||||||
|
if (data->mHasSibling && aAnchor->GetParent()) {
|
||||||
|
if (auto* dependency = EnsureHasSelectorDependency(aAnchor->GetParent())) {
|
||||||
|
dependency->AddSelectorData(data, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1764,6 +2059,26 @@ nsCSSRuleUtils::RelativeSelectorListMatches(
|
|||||||
}
|
}
|
||||||
MOZ_ASSERT(leftmost->mNext);
|
MOZ_ASSERT(leftmost->mNext);
|
||||||
|
|
||||||
|
// A single compound cannot move beyond the leading relationship.
|
||||||
|
// Avoid scanning descendants for >, and all following subtrees for +/~.
|
||||||
|
if (leftmost == relative->mSelectors) {
|
||||||
|
char combinator = leftmost->mNext->mOperator;
|
||||||
|
if (combinator == '>' || combinator == '+' || combinator == '~') {
|
||||||
|
Element* candidate = combinator == '>'
|
||||||
|
? aAnchor->GetFirstElementChild()
|
||||||
|
: aAnchor->GetNextElementSibling();
|
||||||
|
for (; candidate; candidate = candidate->GetNextElementSibling()) {
|
||||||
|
if (matchesCandidate(candidate, relative, aTreeMatchContext)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (combinator == '+') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (leftmost->mNext->mOperator) {
|
switch (leftmost->mNext->mOperator) {
|
||||||
// Even for a leading adjacent-sibling combinator, a later combinator in
|
// Even for a leading adjacent-sibling combinator, a later combinator in
|
||||||
// the relative selector can move the rightmost matching element into a
|
// the relative selector can move the rightmost matching element into a
|
||||||
@@ -1778,6 +2093,12 @@ nsCSSRuleUtils::RelativeSelectorListMatches(
|
|||||||
if (matchesSubtree(sibling, relative, aTreeMatchContext)) {
|
if (matchesSubtree(sibling, relative, aTreeMatchContext)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// Once + .a enters .a's descendants, later combinators cannot
|
||||||
|
// leave that subtree. + .a + .b still needs the broader search.
|
||||||
|
if (leftmost->mNext->mOperator == '+' &&
|
||||||
|
NS_IS_ANCESTOR_OPERATOR(leftmost->mOperator)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "mozilla/EventStates.h"
|
#include "mozilla/EventStates.h"
|
||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/RefCountType.h"
|
#include "mozilla/RefCountType.h"
|
||||||
|
#include "mozilla/RefCounted.h"
|
||||||
#include "mozilla/SheetType.h"
|
#include "mozilla/SheetType.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "nsExpirationTracker.h"
|
#include "nsExpirationTracker.h"
|
||||||
@@ -20,8 +21,64 @@
|
|||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "StyleRule.h"
|
#include "StyleRule.h"
|
||||||
|
|
||||||
|
// No selector or DOM pointers: nodes can safely keep this after a rule is
|
||||||
|
// removed, without keeping either the stylesheet or an anchor alive.
|
||||||
|
struct nsCSSHasSelectorData : public mozilla::RefCounted<nsCSSHasSelectorData> {
|
||||||
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(nsCSSHasSelectorData)
|
||||||
|
|
||||||
|
struct Branch {
|
||||||
|
mozilla::EventStates mStates;
|
||||||
|
nsTArray<nsCOMPtr<nsIAtom>> mAttributes;
|
||||||
|
nsTArray<nsCOMPtr<nsIAtom>> mClasses;
|
||||||
|
bool mAllAttributes = false;
|
||||||
|
bool mIsLocal = false;
|
||||||
|
char16_t mCombinator = ' ';
|
||||||
|
|
||||||
|
void AddSelector(nsCSSSelector* aSelector);
|
||||||
|
void Merge(const Branch& aOther);
|
||||||
|
bool MightDependOnAttribute(mozilla::dom::Element* aElement,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
const nsAttrValue* aNewClasses,
|
||||||
|
bool aCompareClasses) const;
|
||||||
|
bool IsSibling() const {
|
||||||
|
return mCombinator == '+' || mCombinator == '~';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit nsCSSHasSelectorData(nsCSSSelectorList* aList);
|
||||||
|
nsTArray<Branch> mBranches;
|
||||||
|
bool mHasSibling = false;
|
||||||
|
};
|
||||||
|
|
||||||
struct nsCSSRuleUtils
|
struct nsCSSRuleUtils
|
||||||
{
|
{
|
||||||
|
// Stored on nodes under hasSelectorDependency. Dependencies accumulate
|
||||||
|
// across matching passes, so a failed/short-circuited branch stays watched.
|
||||||
|
struct HasSelectorDependency {
|
||||||
|
// Merge rules with the same search relationship. Retaining a reference
|
||||||
|
// to every rule ever matched would grow without bound on long-lived pages
|
||||||
|
// that replace stylesheets. Only the most recent registration is cached.
|
||||||
|
nsTArray<nsCSSHasSelectorData::Branch> mBranches;
|
||||||
|
nsTArray<nsCSSHasSelectorData::Branch> mSiblingBranches;
|
||||||
|
RefPtr<nsCSSHasSelectorData> mLastSelector;
|
||||||
|
RefPtr<nsCSSHasSelectorData> mLastSiblingSelector;
|
||||||
|
bool mRestyleLaterSiblings = false;
|
||||||
|
|
||||||
|
void AddSelectorData(nsCSSHasSelectorData* aData, bool aSibling);
|
||||||
|
bool MightDependOnChange(Element* aAnchor, nsINode* aNode,
|
||||||
|
mozilla::EventStates aStateMask,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
const nsAttrValue* aNewClasses,
|
||||||
|
bool aCompareClasses,
|
||||||
|
bool aSibling,
|
||||||
|
bool aNodeIsFollowingSibling = false) const;
|
||||||
|
bool MightAffectSiblingAnchor(nsINode* aParent, nsINode* aNode,
|
||||||
|
mozilla::EventStates aStateMask,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
const nsAttrValue* aNewClasses,
|
||||||
|
bool aCompareClasses) const;
|
||||||
|
};
|
||||||
|
|
||||||
static void Startup();
|
static void Startup();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
static void FreeSystemMetrics();
|
static void FreeSystemMetrics();
|
||||||
|
|||||||
@@ -450,6 +450,7 @@ struct MOZ_STACK_CLASS TreeMatchContext {
|
|||||||
, mIsTopmostScope(false)
|
, mIsTopmostScope(false)
|
||||||
, mForAssignedSlot(false)
|
, mForAssignedSlot(false)
|
||||||
, mRelativeSelectorAnchor(nullptr)
|
, mRelativeSelectorAnchor(nullptr)
|
||||||
|
, mHasSelectorLaterSiblings(false)
|
||||||
{
|
{
|
||||||
if (aMatchVisited != eNeverMatchVisited) {
|
if (aMatchVisited != eNeverMatchVisited) {
|
||||||
nsILoadContext* loadContext = mDocument->GetLoadContext();
|
nsILoadContext* loadContext = mDocument->GetLoadContext();
|
||||||
@@ -472,6 +473,8 @@ struct MOZ_STACK_CLASS TreeMatchContext {
|
|||||||
// relative selector. This is deliberately separate from mScopes: an
|
// relative selector. This is deliberately separate from mScopes: an
|
||||||
// explicit :scope inside :has() still refers to the API/style scope.
|
// explicit :scope inside :has() still refers to the API/style scope.
|
||||||
mozilla::dom::Element* mRelativeSelectorAnchor;
|
mozilla::dom::Element* mRelativeSelectorAnchor;
|
||||||
|
// Propagate an outer sibling combinator through :is(), :not(), etc.
|
||||||
|
bool mHasSelectorLaterSiblings;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MOZ_STACK_CLASS RuleProcessorData {
|
struct MOZ_STACK_CLASS RuleProcessorData {
|
||||||
|
|||||||
@@ -333,12 +333,10 @@ void vp8_build_inter16x16_predictors_mb(MACROBLOCKD *x, unsigned char *dst_y,
|
|||||||
_16x16mv.as_mv.row &= x->fullpixel_mask;
|
_16x16mv.as_mv.row &= x->fullpixel_mask;
|
||||||
_16x16mv.as_mv.col &= x->fullpixel_mask;
|
_16x16mv.as_mv.col &= x->fullpixel_mask;
|
||||||
|
|
||||||
if (2 * _16x16mv.as_mv.col < (x->mb_to_left_edge - (19 << 3)) ||
|
/* Rounding to full-pel can move the chroma MV outside the border tap
|
||||||
2 * _16x16mv.as_mv.col > x->mb_to_right_edge + (18 << 3) ||
|
* window even though the luma MV was already clamped, so clamp again to
|
||||||
2 * _16x16mv.as_mv.row < (x->mb_to_top_edge - (19 << 3)) ||
|
* keep the reference read in bounds and ensure dst_u/dst_v are written. */
|
||||||
2 * _16x16mv.as_mv.row > x->mb_to_bottom_edge + (18 << 3)) {
|
clamp_uvmv_to_umv_border(&_16x16mv.as_mv, x);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre_stride >>= 1;
|
pre_stride >>= 1;
|
||||||
offset = (_16x16mv.as_mv.row >> 3) * pre_stride + (_16x16mv.as_mv.col >> 3);
|
offset = (_16x16mv.as_mv.row >> 3) * pre_stride + (_16x16mv.as_mv.col >> 3);
|
||||||
|
|||||||
@@ -379,12 +379,12 @@ template<typename T>
|
|||||||
static MOZ_ALWAYS_INLINE bool
|
static MOZ_ALWAYS_INLINE bool
|
||||||
NumberEqualsInt32(T aValue, int32_t* aInt32)
|
NumberEqualsInt32(T aValue, int32_t* aInt32)
|
||||||
{
|
{
|
||||||
/*
|
// Check the range before casting: an out-of-range float-to-integer cast is
|
||||||
* XXX Casting a floating-point value that doesn't truncate to int32_t, to
|
// undefined behavior. Use an exclusive upper bound of 2^31, since converting
|
||||||
* int32_t, induces undefined behavior. We should definitely fix this
|
// INT32_MAX to float rounds up to 2^31. This also rejects NaN and infinities.
|
||||||
* (bug 744965), but as apparently it "works" in practice, it's not a
|
if (!(aValue >= T(INT32_MIN) && aValue < -T(INT32_MIN))) {
|
||||||
* pressing concern now.
|
return false;
|
||||||
*/
|
}
|
||||||
return aValue == (*aInt32 = int32_t(aValue));
|
return aValue == (*aInt32 = int32_t(aValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -111,9 +111,11 @@ nsJARProtocolHandler::GetDefaultPort(int32_t *result)
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsJARProtocolHandler::GetProtocolFlags(uint32_t *result)
|
nsJARProtocolHandler::GetProtocolFlags(uint32_t *result)
|
||||||
{
|
{
|
||||||
// URI_LOADABLE_BY_ANYONE, since it's our inner URI that will matter
|
// A jar: URI is only ever as loadable as the inner URI it
|
||||||
// anyway.
|
// wraps, and security checks consult the innermost URI. Claim
|
||||||
*result = URI_NORELATIVE | URI_NOAUTH | URI_LOADABLE_BY_ANYONE;
|
// the restrictive flag here so that consumers which look at the
|
||||||
|
// jar: handler alone don't treat it as web-loadable.
|
||||||
|
*result = URI_NORELATIVE | URI_NOAUTH | URI_IS_LOCAL_FILE;
|
||||||
/* Although jar uris have their own concept of relative urls
|
/* Although jar uris have their own concept of relative urls
|
||||||
it is very different from the standard behaviour, so we
|
it is very different from the standard behaviour, so we
|
||||||
have to say norelative here! */
|
have to say norelative here! */
|
||||||
|
|||||||
@@ -2572,6 +2572,9 @@ pref("layout.css.legacy-negation-pseudo.enabled", false);
|
|||||||
// Is support for the :is() and :where() selectors enabled?
|
// Is support for the :is() and :where() selectors enabled?
|
||||||
pref("layout.css.is-where-pseudo.enabled", true);
|
pref("layout.css.is-where-pseudo.enabled", true);
|
||||||
|
|
||||||
|
// Is support for the :has() selector enabled?
|
||||||
|
pref("layout.css.has-pseudo.enabled", false);
|
||||||
|
|
||||||
// Is support for the ::slotted() selector enabled?
|
// Is support for the ::slotted() selector enabled?
|
||||||
pref("layout.css.slotted-pseudo.enabled", true);
|
pref("layout.css.slotted-pseudo.enabled", true);
|
||||||
|
|
||||||
@@ -4513,6 +4516,9 @@ pref("html5.flushtimer.initialdelay", 120);
|
|||||||
// Time in milliseconds between the time a network buffer is seen and the
|
// Time in milliseconds between the time a network buffer is seen and the
|
||||||
// timer firing when the timer has already fired previously in this parse.
|
// timer firing when the timer has already fired previously in this parse.
|
||||||
pref("html5.flushtimer.subsequentdelay", 120);
|
pref("html5.flushtimer.subsequentdelay", 120);
|
||||||
|
// Determine whether strict (standards-compliant) subtree node checking is
|
||||||
|
// enabled for forms. See UXP issue #3197
|
||||||
|
pref("html5.forms.standards_compliant", true);
|
||||||
|
|
||||||
// Push/Pop/Replace State prefs
|
// Push/Pop/Replace State prefs
|
||||||
pref("browser.history.maxStateObjectSize", 655360);
|
pref("browser.history.maxStateObjectSize", 655360);
|
||||||
|
|||||||
@@ -3,11 +3,17 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "nsMIMEHeaderParamImpl.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "prmem.h"
|
|
||||||
|
#include "mozilla/Base64.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/TextUtils.h"
|
||||||
|
#include "mozilla/dom/EncodingUtils.h"
|
||||||
|
|
||||||
#include "prprf.h"
|
#include "prprf.h"
|
||||||
#include "plstr.h"
|
#include "plstr.h"
|
||||||
#include "plbase64.h"
|
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "nsMemory.h"
|
#include "nsMemory.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
@@ -16,18 +22,20 @@
|
|||||||
#include "nsIUTF8ConverterService.h"
|
#include "nsIUTF8ConverterService.h"
|
||||||
#include "nsUConvCID.h"
|
#include "nsUConvCID.h"
|
||||||
#include "nsIServiceManager.h"
|
#include "nsIServiceManager.h"
|
||||||
#include "nsMIMEHeaderParamImpl.h"
|
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "nsNativeCharsetUtils.h"
|
#include "nsNativeCharsetUtils.h"
|
||||||
#include "nsError.h"
|
#include "nsError.h"
|
||||||
#include "nsIUnicodeDecoder.h"
|
#include "nsIUnicodeDecoder.h"
|
||||||
#include "mozilla/dom/EncodingUtils.h"
|
|
||||||
|
|
||||||
using mozilla::dom::EncodingUtils;
|
using mozilla::dom::EncodingUtils;
|
||||||
|
using mozilla::Maybe;
|
||||||
|
using mozilla::Nothing;
|
||||||
|
using mozilla::Some;
|
||||||
|
|
||||||
|
|
||||||
// static functions declared below are moved from mailnews/mime/src/comi18n.cpp
|
// static functions declared below are moved from mailnews/mime/src/comi18n.cpp
|
||||||
|
|
||||||
static char *DecodeQ(const char *, uint32_t);
|
static Maybe<nsCString> DecodeQ(const char *, uint32_t);
|
||||||
static bool Is7bitNonAsciiString(const char *, uint32_t);
|
static bool Is7bitNonAsciiString(const char *, uint32_t);
|
||||||
static void CopyRawHeader(const char *, uint32_t, const char *, nsACString &);
|
static void CopyRawHeader(const char *, uint32_t, const char *, nsACString &);
|
||||||
static nsresult DecodeRFC2047Str(const char *, const char *, bool, nsACString&);
|
static nsresult DecodeRFC2047Str(const char *, const char *, bool, nsACString&);
|
||||||
@@ -48,8 +56,7 @@ nsMIMEHeaderParamImpl::GetParameter(const nsACString& aHeaderVal,
|
|||||||
const char *aParamName,
|
const char *aParamName,
|
||||||
const nsACString& aFallbackCharset,
|
const nsACString& aFallbackCharset,
|
||||||
bool aTryLocaleCharset,
|
bool aTryLocaleCharset,
|
||||||
char **aLang, nsAString& aResult)
|
char **aLang, nsAString& aResult) {
|
||||||
{
|
|
||||||
return DoGetParameter(aHeaderVal, aParamName, MIME_FIELD_ENCODING,
|
return DoGetParameter(aHeaderVal, aParamName, MIME_FIELD_ENCODING,
|
||||||
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
|
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
|
||||||
}
|
}
|
||||||
@@ -59,8 +66,7 @@ nsMIMEHeaderParamImpl::GetParameterHTTP(const nsACString& aHeaderVal,
|
|||||||
const char *aParamName,
|
const char *aParamName,
|
||||||
const nsACString& aFallbackCharset,
|
const nsACString& aFallbackCharset,
|
||||||
bool aTryLocaleCharset,
|
bool aTryLocaleCharset,
|
||||||
char **aLang, nsAString& aResult)
|
char **aLang, nsAString& aResult) {
|
||||||
{
|
|
||||||
return DoGetParameter(aHeaderVal, aParamName, HTTP_FIELD_ENCODING,
|
return DoGetParameter(aHeaderVal, aParamName, HTTP_FIELD_ENCODING,
|
||||||
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
|
aFallbackCharset, aTryLocaleCharset, aLang, aResult);
|
||||||
}
|
}
|
||||||
@@ -94,76 +100,75 @@ nsMIMEHeaderParamImpl::DoGetParameter(const nsACString& aHeaderVal,
|
|||||||
ParamDecoding aDecoding,
|
ParamDecoding aDecoding,
|
||||||
const nsACString& aFallbackCharset,
|
const nsACString& aFallbackCharset,
|
||||||
bool aTryLocaleCharset,
|
bool aTryLocaleCharset,
|
||||||
char **aLang, nsAString& aResult)
|
char **aLang, nsAString& aResult) {
|
||||||
{
|
aResult.Truncate();
|
||||||
aResult.Truncate();
|
nsresult rv;
|
||||||
nsresult rv;
|
|
||||||
|
|
||||||
// get parameter (decode RFC 2231/5987 when applicable, as specified by
|
// get parameter (decode RFC 2231/5987 when applicable, as specified by
|
||||||
// aDecoding (5987 being a subset of 2231) and return charset.)
|
// aDecoding (5987 being a subset of 2231) and return charset.)
|
||||||
nsXPIDLCString med;
|
nsXPIDLCString med;
|
||||||
nsXPIDLCString charset;
|
nsXPIDLCString charset;
|
||||||
rv = DoParameterInternal(aHeaderVal, aParamName, aDecoding,
|
rv = DoParameterInternal(aHeaderVal, aParamName, aDecoding,
|
||||||
getter_Copies(charset), aLang, getter_Copies(med));
|
getter_Copies(charset), aLang, getter_Copies(med));
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
// convert to UTF-8 after charset conversion and RFC 2047 decoding
|
// convert to UTF-8 after charset conversion and RFC 2047 decoding
|
||||||
// if necessary.
|
// if necessary.
|
||||||
|
|
||||||
nsAutoCString str1;
|
nsAutoCString str1;
|
||||||
rv = internalDecodeParameter(med, charset.get(), nullptr, false,
|
rv = internalDecodeParameter(med, charset.get(), nullptr, false,
|
||||||
// was aDecoding == MIME_FIELD_ENCODING
|
// was aDecoding == MIME_FIELD_ENCODING
|
||||||
// see bug 875615
|
// see bug 875615
|
||||||
true,
|
true,
|
||||||
str1);
|
str1);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (!aFallbackCharset.IsEmpty())
|
if (!aFallbackCharset.IsEmpty()) {
|
||||||
{
|
nsAutoCString charset;
|
||||||
nsAutoCString charset;
|
EncodingUtils::FindEncodingForLabel(aFallbackCharset, charset);
|
||||||
EncodingUtils::FindEncodingForLabel(aFallbackCharset, charset);
|
nsAutoCString str2;
|
||||||
nsAutoCString str2;
|
nsCOMPtr<nsIUTF8ConverterService> cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
||||||
nsCOMPtr<nsIUTF8ConverterService>
|
if (cvtUTF8 &&
|
||||||
cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
NS_SUCCEEDED(cvtUTF8->ConvertStringToUTF8(str1,
|
||||||
if (cvtUTF8 &&
|
PromiseFlatCString(aFallbackCharset).get(),
|
||||||
NS_SUCCEEDED(cvtUTF8->ConvertStringToUTF8(str1,
|
false,
|
||||||
PromiseFlatCString(aFallbackCharset).get(), false,
|
!charset.EqualsLiteral("UTF-8"),
|
||||||
!charset.EqualsLiteral("UTF-8"),
|
1,
|
||||||
1, str2))) {
|
str2))) {
|
||||||
CopyUTF8toUTF16(str2, aResult);
|
CopyUTF8toUTF16(str2, aResult);
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsUTF8(str1)) {
|
|
||||||
CopyUTF8toUTF16(str1, aResult);
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (aTryLocaleCharset && !NS_IsNativeUTF8())
|
if (IsUTF8(str1)) {
|
||||||
return NS_CopyNativeToUnicode(str1, aResult);
|
CopyUTF8toUTF16(str1, aResult);
|
||||||
|
|
||||||
CopyASCIItoUTF16(str1, aResult);
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aTryLocaleCharset && !NS_IsNativeUTF8()) {
|
||||||
|
return NS_CopyNativeToUnicode(str1, aResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyASCIItoUTF16(str1, aResult);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove backslash-encoded sequences from quoted-strings
|
// remove backslash-encoded sequences from quoted-strings
|
||||||
// modifies string in place, potentially shortening it
|
// modifies aValue, potentially shortening it
|
||||||
void RemoveQuotedStringEscapes(char *src)
|
void RemoveQuotedStringEscapes(nsCString& aValue) {
|
||||||
{
|
nsAutoCString unescaped;
|
||||||
char *dst = src;
|
unescaped.SetCapacity(aValue.Length());
|
||||||
|
|
||||||
for (char *c = src; *c; ++c)
|
for (uint32_t i = 0; i < aValue.Length(); ++i) {
|
||||||
{
|
if (aValue[i] == '\\' && i + 1 < aValue.Length()) {
|
||||||
if (c[0] == '\\' && c[1])
|
|
||||||
{
|
|
||||||
// skip backslash if not at end
|
// skip backslash if not at end
|
||||||
++c;
|
++i;
|
||||||
}
|
}
|
||||||
*dst++ = *c;
|
unescaped.Append(aValue[i]);
|
||||||
}
|
}
|
||||||
*dst = 0;
|
aValue = std::move(unescaped);
|
||||||
}
|
}
|
||||||
|
|
||||||
// true is character is a hex digit
|
// true is character is a hex digit
|
||||||
@@ -176,12 +181,13 @@ bool IsHexDigit(char aChar)
|
|||||||
(c >= '0' && c <= '9');
|
(c >= '0' && c <= '9');
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate that a C String containing %-escapes is syntactically valid
|
// validate that a string containing %-escapes is syntactically valid
|
||||||
bool IsValidPercentEscaped(const char *aValue, int32_t len)
|
bool IsValidPercentEscaped(const nsACString& aValue) {
|
||||||
{
|
for (uint32_t i = 0; i < aValue.Length(); i++) {
|
||||||
for (int32_t i = 0; i < len; i++) {
|
|
||||||
if (aValue[i] == '%') {
|
if (aValue[i] == '%') {
|
||||||
if (!IsHexDigit(aValue[i + 1]) || !IsHexDigit(aValue[i + 2])) {
|
if (i + 2 >= aValue.Length() ||
|
||||||
|
!IsHexDigit(aValue[i + 1]) ||
|
||||||
|
!IsHexDigit(aValue[i + 2])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,6 +195,21 @@ bool IsValidPercentEscaped(const char *aValue, int32_t len)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A NUL anywhere in a decoded value would silently truncate it in any later
|
||||||
|
// C-string based processing. Note that this is stricter than
|
||||||
|
// ContainsTrailingCharPastNull, which tolerates a value whose tail past the
|
||||||
|
// NUL is only more NULs.
|
||||||
|
static bool ContainsNull(const nsACString& aValue) {
|
||||||
|
return aValue.Contains('\0');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Percent-decode aValue in place (which happens whether or not this succeeds),
|
||||||
|
// returning false if the decoded value contains a NUL.
|
||||||
|
static bool UnescapeRejectingNull(nsCString& aValue) {
|
||||||
|
NS_UnescapeURL(aValue);
|
||||||
|
return !ContainsNull(aValue);
|
||||||
|
}
|
||||||
|
|
||||||
// Support for continuations (RFC 2231, Section 3)
|
// Support for continuations (RFC 2231, Section 3)
|
||||||
|
|
||||||
// only a sane number supported
|
// only a sane number supported
|
||||||
@@ -220,59 +241,41 @@ class Continuation {
|
|||||||
bool wasQuotedString;
|
bool wasQuotedString;
|
||||||
};
|
};
|
||||||
|
|
||||||
// combine segments into a single string, returning the allocated string
|
// combine segments into a single string, up to the first segment that is
|
||||||
// (or nullptr) while emptying the list
|
// missing. Returns Nothing() if that leaves nothing at all, or, with
|
||||||
char *combineContinuations(nsTArray<Continuation>& aArray)
|
// aContainedNull set, if percent-decoding a segment produced a NUL.
|
||||||
{
|
Maybe<nsCString> combineContinuations(const nsTArray<Continuation>& aArray,
|
||||||
// Sanity check
|
bool& aContainedNull) {
|
||||||
if (aArray.Length() == 0)
|
nsCString result;
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// Get an upper bound for the length
|
for (const Continuation& cont : aArray) {
|
||||||
uint32_t length = 0;
|
if (!cont.value) break;
|
||||||
for (uint32_t i = 0; i < aArray.Length(); i++) {
|
|
||||||
length += aArray[i].length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate
|
nsAutoCString segment(cont.value, cont.length);
|
||||||
char *result = (char *) moz_xmalloc(length + 1);
|
if (cont.needsPercentDecoding) {
|
||||||
|
if (!UnescapeRejectingNull(segment)) {
|
||||||
// Concatenate
|
aContainedNull = true;
|
||||||
if (result) {
|
return Nothing();
|
||||||
*result = '\0';
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < aArray.Length(); i++) {
|
|
||||||
Continuation cont = aArray[i];
|
|
||||||
if (! cont.value) break;
|
|
||||||
|
|
||||||
char *c = result + strlen(result);
|
|
||||||
strncat(result, cont.value, cont.length);
|
|
||||||
if (cont.needsPercentDecoding) {
|
|
||||||
nsUnescape(c);
|
|
||||||
}
|
|
||||||
if (cont.wasQuotedString) {
|
|
||||||
RemoveQuotedStringEscapes(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (cont.wasQuotedString) {
|
||||||
// return null if empty value
|
RemoveQuotedStringEscapes(segment);
|
||||||
if (*result == '\0') {
|
|
||||||
free(result);
|
|
||||||
result = nullptr;
|
|
||||||
}
|
}
|
||||||
} else {
|
result.Append(segment);
|
||||||
// Handle OOM
|
|
||||||
NS_WARNING("Out of memory\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
// no result if empty value
|
||||||
|
if (result.IsEmpty()) {
|
||||||
|
return Nothing();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(std::move(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a continuation, return false on error if segment already has been seen
|
// add a continuation, return false on error if segment already has been seen
|
||||||
bool addContinuation(nsTArray<Continuation>& aArray, uint32_t aIndex,
|
bool addContinuation(nsTArray<Continuation>& aArray, uint32_t aIndex,
|
||||||
const char *aValue, uint32_t aLength,
|
const char *aValue, uint32_t aLength,
|
||||||
bool aNeedsPercentDecoding, bool aWasQuotedString)
|
bool aNeedsPercentDecoding, bool aWasQuotedString) {
|
||||||
{
|
|
||||||
if (aIndex < aArray.Length() && aArray[aIndex].value) {
|
if (aIndex < aArray.Length() && aArray[aIndex].value) {
|
||||||
NS_WARNING("duplicate RC2231 continuation segment #\n");
|
NS_WARNING("duplicate RC2231 continuation segment #\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -299,8 +302,7 @@ bool addContinuation(nsTArray<Continuation>& aArray, uint32_t aIndex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse a segment number; return -1 on error
|
// parse a segment number; return -1 on error
|
||||||
int32_t parseSegmentNumber(const char *aValue, int32_t aLen)
|
int32_t parseSegmentNumber(const char *aValue, int32_t aLen) {
|
||||||
{
|
|
||||||
if (aLen < 1) {
|
if (aLen < 1) {
|
||||||
NS_WARNING("segment number missing\n");
|
NS_WARNING("segment number missing\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -332,20 +334,16 @@ int32_t parseSegmentNumber(const char *aValue, int32_t aLen)
|
|||||||
|
|
||||||
// validate a given octet sequence for compliance with the specified
|
// validate a given octet sequence for compliance with the specified
|
||||||
// encoding
|
// encoding
|
||||||
bool IsValidOctetSequenceForCharset(nsACString& aCharset, const char *aOctets)
|
bool IsValidOctetSequenceForCharset(nsACString& aCharset, const nsACString& aOctets) {
|
||||||
{
|
nsCOMPtr<nsIUTF8ConverterService> cvtUTF8(do_GetService(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
||||||
nsCOMPtr<nsIUTF8ConverterService> cvtUTF8(do_GetService
|
|
||||||
(NS_UTF8CONVERTERSERVICE_CONTRACTID));
|
|
||||||
if (!cvtUTF8) {
|
if (!cvtUTF8) {
|
||||||
NS_WARNING("Can't get UTF8ConverterService\n");
|
NS_WARNING("Can't get UTF8ConverterService\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoCString tmpRaw;
|
|
||||||
tmpRaw.Assign(aOctets);
|
|
||||||
nsAutoCString tmpDecoded;
|
nsAutoCString tmpDecoded;
|
||||||
|
|
||||||
nsresult rv = cvtUTF8->ConvertStringToUTF8(tmpRaw,
|
nsresult rv = cvtUTF8->ConvertStringToUTF8(aOctets,
|
||||||
PromiseFlatCString(aCharset).get(),
|
PromiseFlatCString(aCharset).get(),
|
||||||
false, false, 1, tmpDecoded);
|
false, false, 1, tmpDecoded);
|
||||||
|
|
||||||
@@ -371,8 +369,7 @@ nsMIMEHeaderParamImpl::GetParameterInternal(const nsACString& aHeaderValue,
|
|||||||
const char* aParamName,
|
const char* aParamName,
|
||||||
char** aCharset,
|
char** aCharset,
|
||||||
char** aLang,
|
char** aLang,
|
||||||
char** aResult)
|
char** aResult) {
|
||||||
{
|
|
||||||
return DoParameterInternal(aHeaderValue, aParamName, MIME_FIELD_ENCODING,
|
return DoParameterInternal(aHeaderValue, aParamName, MIME_FIELD_ENCODING,
|
||||||
aCharset, aLang, aResult);
|
aCharset, aLang, aResult);
|
||||||
}
|
}
|
||||||
@@ -384,9 +381,7 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
|||||||
ParamDecoding aDecoding,
|
ParamDecoding aDecoding,
|
||||||
char** aCharset,
|
char** aCharset,
|
||||||
char** aLang,
|
char** aLang,
|
||||||
char** aResult)
|
char** aResult) {
|
||||||
{
|
|
||||||
|
|
||||||
if (aHeaderValue.IsEmpty() || !aResult) {
|
if (aHeaderValue.IsEmpty() || !aResult) {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
@@ -405,8 +400,12 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
|||||||
|
|
||||||
*aResult = nullptr;
|
*aResult = nullptr;
|
||||||
|
|
||||||
if (aCharset) *aCharset = nullptr;
|
if (aCharset) {
|
||||||
if (aLang) *aLang = nullptr;
|
*aCharset = nullptr;
|
||||||
|
}
|
||||||
|
if (aLang) {
|
||||||
|
*aLang = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoCString charset;
|
nsAutoCString charset;
|
||||||
|
|
||||||
@@ -415,8 +414,8 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
|||||||
bool acceptContinuations = true;
|
bool acceptContinuations = true;
|
||||||
|
|
||||||
// skip leading white space.
|
// skip leading white space.
|
||||||
for (; *str && nsCRT::IsAsciiSpace(*str); ++str)
|
for (; *str && nsCRT::IsAsciiSpace(*str); ++str) { }
|
||||||
;
|
|
||||||
const char *start = str;
|
const char *start = str;
|
||||||
|
|
||||||
// aParamName is empty. return the first (possibly) _unnamed_ 'parameter'
|
// aParamName is empty. return the first (possibly) _unnamed_ 'parameter'
|
||||||
@@ -429,9 +428,7 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
|||||||
if (str == start)
|
if (str == start)
|
||||||
return NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY;
|
return NS_ERROR_FIRST_HEADER_FIELD_COMPONENT_EMPTY;
|
||||||
|
|
||||||
*aResult = (char *) nsMemory::Clone(start, (str - start) + 1);
|
*aResult = ToNewCString(Substring(start, str - start));
|
||||||
NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
(*aResult)[str - start] = '\0'; // null-terminate
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,9 +462,14 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
|||||||
// collect results for the different algorithms (plain filename,
|
// collect results for the different algorithms (plain filename,
|
||||||
// RFC5987/2231-encoded filename, + continuations) separately and decide
|
// RFC5987/2231-encoded filename, + continuations) separately and decide
|
||||||
// which to use at the end
|
// which to use at the end
|
||||||
char *caseAResult = nullptr;
|
Maybe<nsCString> caseAResult;
|
||||||
char *caseBResult = nullptr;
|
Maybe<nsCString> caseBResult;
|
||||||
char *caseCDResult = nullptr;
|
Maybe<nsCString> caseCDResult;
|
||||||
|
|
||||||
|
// set when percent-decoding produced a NUL, which makes us reject the
|
||||||
|
// parameter outright rather than fall back to a value the sender did not
|
||||||
|
// intend to be used
|
||||||
|
bool containedNull = false;
|
||||||
|
|
||||||
// collect continuation segments
|
// collect continuation segments
|
||||||
nsTArray<Continuation> segments;
|
nsTArray<Continuation> segments;
|
||||||
@@ -548,15 +550,14 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
|||||||
|
|
||||||
// if the parameter spans across multiple lines we have to strip out the
|
// if the parameter spans across multiple lines we have to strip out the
|
||||||
// line continuation -- jht 4/29/98
|
// line continuation -- jht 4/29/98
|
||||||
nsAutoCString tempStr(valueStart, valueEnd - valueStart);
|
nsCString tempStr(valueStart, valueEnd - valueStart);
|
||||||
tempStr.StripChars("\r\n");
|
tempStr.StripChars("\r\n");
|
||||||
char *res = ToNewCString(tempStr);
|
|
||||||
NS_ENSURE_TRUE(res, NS_ERROR_OUT_OF_MEMORY);
|
|
||||||
|
|
||||||
if (isQuotedString)
|
if (isQuotedString) {
|
||||||
RemoveQuotedStringEscapes(res);
|
RemoveQuotedStringEscapes(tempStr);
|
||||||
|
}
|
||||||
|
|
||||||
caseAResult = res;
|
caseAResult.emplace(std::move(tempStr));
|
||||||
// keep going, we may find a RFC 2231/5987 encoded alternative
|
// keep going, we may find a RFC 2231/5987 encoded alternative
|
||||||
}
|
}
|
||||||
// case B, C, and D
|
// case B, C, and D
|
||||||
@@ -645,19 +646,16 @@ nsMIMEHeaderParamImpl::DoParameterInternal(const nsACString& aHeaderValue,
|
|||||||
// non-empty value part
|
// non-empty value part
|
||||||
if (rawValLength > 0) {
|
if (rawValLength > 0) {
|
||||||
if (!caseBResult && caseB) {
|
if (!caseBResult && caseB) {
|
||||||
if (!IsValidPercentEscaped(rawValStart, rawValLength)) {
|
nsCString rawVal(rawValStart, rawValLength);
|
||||||
|
if (!IsValidPercentEscaped(rawVal)) {
|
||||||
goto increment_str;
|
goto increment_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate buffer for the raw value
|
if (!UnescapeRejectingNull(rawVal)) {
|
||||||
char *tmpResult = (char *) nsMemory::Clone(rawValStart, rawValLength + 1);
|
containedNull = true;
|
||||||
if (!tmpResult) {
|
break;
|
||||||
goto increment_str;
|
|
||||||
}
|
}
|
||||||
*(tmpResult + rawValLength) = 0;
|
caseBResult.emplace(std::move(rawVal));
|
||||||
|
|
||||||
nsUnescape(tmpResult);
|
|
||||||
caseBResult = tmpResult;
|
|
||||||
} else {
|
} else {
|
||||||
// caseC
|
// caseC
|
||||||
bool added = addContinuation(segments, 0, rawValStart,
|
bool added = addContinuation(segments, 0, rawValStart,
|
||||||
@@ -701,44 +699,45 @@ increment_str:
|
|||||||
while (nsCRT::IsAsciiSpace(*str)) ++str;
|
while (nsCRT::IsAsciiSpace(*str)) ++str;
|
||||||
}
|
}
|
||||||
|
|
||||||
caseCDResult = combineContinuations(segments);
|
if (!containedNull) {
|
||||||
|
caseCDResult = combineContinuations(segments, containedNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (containedNull) {
|
||||||
|
// Percent-decoding produced a NUL, which would truncate the value.
|
||||||
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
if (caseBResult && !charsetB.IsEmpty()) {
|
if (caseBResult && !charsetB.IsEmpty()) {
|
||||||
// check that the 2231/5987 result decodes properly given the
|
// check that the 2231/5987 result decodes properly given the
|
||||||
// specified character set
|
// specified character set
|
||||||
if (!IsValidOctetSequenceForCharset(charsetB, caseBResult))
|
if (!IsValidOctetSequenceForCharset(charsetB, *caseBResult)) {
|
||||||
caseBResult = nullptr;
|
caseBResult.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caseCDResult && !charsetCD.IsEmpty()) {
|
if (caseCDResult && !charsetCD.IsEmpty()) {
|
||||||
// check that the 2231/5987 result decodes properly given the
|
// check that the 2231/5987 result decodes properly given the
|
||||||
// specified character set
|
// specified character set
|
||||||
if (!IsValidOctetSequenceForCharset(charsetCD, caseCDResult))
|
if (!IsValidOctetSequenceForCharset(charsetCD, *caseCDResult)) {
|
||||||
caseCDResult = nullptr;
|
caseCDResult.reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (caseBResult) {
|
if (caseBResult) {
|
||||||
// prefer simple 5987 format over 2231 with continuations
|
// prefer simple 5987 format over 2231 with continuations
|
||||||
*aResult = caseBResult;
|
*aResult = ToNewCString(*caseBResult);
|
||||||
caseBResult = nullptr;
|
|
||||||
charset.Assign(charsetB);
|
charset.Assign(charsetB);
|
||||||
}
|
}
|
||||||
else if (caseCDResult) {
|
else if (caseCDResult) {
|
||||||
// prefer 2231/5987 with or without continuations over plain format
|
// prefer 2231/5987 with or without continuations over plain format
|
||||||
*aResult = caseCDResult;
|
*aResult = ToNewCString(*caseCDResult);
|
||||||
caseCDResult = nullptr;
|
|
||||||
charset.Assign(charsetCD);
|
charset.Assign(charsetCD);
|
||||||
}
|
}
|
||||||
else if (caseAResult) {
|
else if (caseAResult) {
|
||||||
*aResult = caseAResult;
|
*aResult = ToNewCString(*caseAResult);
|
||||||
caseAResult = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// free unused stuff
|
|
||||||
free(caseAResult);
|
|
||||||
free(caseBResult);
|
|
||||||
free(caseCDResult);
|
|
||||||
|
|
||||||
// if we have a result
|
// if we have a result
|
||||||
if (*aResult) {
|
if (*aResult) {
|
||||||
// then return charset and lang as well
|
// then return charset and lang as well
|
||||||
@@ -825,23 +824,6 @@ bool IsRFC5987AttrChar(char aChar)
|
|||||||
c == '_' || c == '`' || c == '|' || c == '~');
|
c == '_' || c == '`' || c == '|' || c == '~');
|
||||||
}
|
}
|
||||||
|
|
||||||
// percent-decode a value
|
|
||||||
// returns false on failure
|
|
||||||
bool PercentDecode(nsACString& aValue)
|
|
||||||
{
|
|
||||||
char *c = (char *) moz_xmalloc(aValue.Length() + 1);
|
|
||||||
if (!c) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(c, PromiseFlatCString(aValue).get());
|
|
||||||
nsUnescape(c);
|
|
||||||
aValue.Assign(c);
|
|
||||||
free(c);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode a parameter value using the encoding defined in RFC 5987
|
// Decode a parameter value using the encoding defined in RFC 5987
|
||||||
//
|
//
|
||||||
// charset "'" [ language ] "'" value-chars
|
// charset "'" [ language ] "'" value-chars
|
||||||
@@ -909,8 +891,8 @@ nsMIMEHeaderParamImpl::DecodeRFC5987Param(const nsACString& aParamVal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// percent-decode
|
// percent-decode
|
||||||
if (!PercentDecode(value)) {
|
if (!UnescapeRejectingNull(value)) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the encoding
|
// return the encoding
|
||||||
@@ -999,52 +981,44 @@ nsMIMEHeaderParamImpl::DecodeParameter(const nsACString& aParamValue,
|
|||||||
(0x41 <= uint8_t(c) && uint8_t(c) <= 0x46) || \
|
(0x41 <= uint8_t(c) && uint8_t(c) <= 0x46) || \
|
||||||
(0x61 <= uint8_t(c) && uint8_t(c) <= 0x66))
|
(0x61 <= uint8_t(c) && uint8_t(c) <= 0x66))
|
||||||
|
|
||||||
// Decode Q encoding (RFC 2047).
|
// Decode Q encoding (RFC 2047). Returns Nothing() on bad syntax.
|
||||||
// static
|
// static
|
||||||
char *DecodeQ(const char *in, uint32_t length)
|
Maybe<nsCString> DecodeQ(const char* in, uint32_t length) {
|
||||||
{
|
nsCString dest;
|
||||||
char *out, *dest = 0;
|
dest.SetCapacity(length);
|
||||||
|
|
||||||
out = dest = (char *)PR_Calloc(length + 1, sizeof(char));
|
|
||||||
if (dest == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
unsigned c = 0;
|
unsigned c = 0;
|
||||||
switch (*in) {
|
switch (*in) {
|
||||||
case '=':
|
case '=':
|
||||||
// check if |in| in the form of '=hh' where h is [0-9a-fA-F].
|
// check if |in| in the form of '=hh' where h is [0-9a-fA-F].
|
||||||
if (length < 3 || !ISHEXCHAR(in[1]) || !ISHEXCHAR(in[2]))
|
if (length < 3 || !ISHEXCHAR(in[1]) || !ISHEXCHAR(in[2])) {
|
||||||
goto badsyntax;
|
return Nothing();
|
||||||
PR_sscanf(in + 1, "%2X", &c);
|
}
|
||||||
*out++ = (char) c;
|
PR_sscanf(in + 1, "%2X", &c);
|
||||||
in += 3;
|
dest.Append((char)c);
|
||||||
length -= 3;
|
in += 3;
|
||||||
break;
|
length -= 3;
|
||||||
|
break;
|
||||||
|
|
||||||
case '_':
|
case '_':
|
||||||
*out++ = ' ';
|
dest.Append(' ');
|
||||||
in++;
|
in++;
|
||||||
length--;
|
length--;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (*in & 0x80) goto badsyntax;
|
if (*in & 0x80) {
|
||||||
*out++ = *in++;
|
return Nothing();
|
||||||
length--;
|
}
|
||||||
|
dest.Append(*in++);
|
||||||
|
length--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*out++ = '\0';
|
|
||||||
|
|
||||||
for (out = dest; *out ; ++out) {
|
dest.ReplaceChar('\t', ' ');
|
||||||
if (*out == '\t')
|
|
||||||
*out = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
return dest;
|
return Some(std::move(dest));
|
||||||
|
|
||||||
badsyntax:
|
|
||||||
PR_Free(dest);
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if input is HZ (a 7bit encoding for simplified Chinese : RFC 1842))
|
// check if input is HZ (a 7bit encoding for simplified Chinese : RFC 1842))
|
||||||
@@ -1154,17 +1128,25 @@ void CopyRawHeader(const char *aInput, uint32_t aLen,
|
|||||||
nsresult DecodeQOrBase64Str(const char *aEncoded, size_t aLen, char aQOrBase64,
|
nsresult DecodeQOrBase64Str(const char *aEncoded, size_t aLen, char aQOrBase64,
|
||||||
const char *aCharset, nsACString &aResult)
|
const char *aCharset, nsACString &aResult)
|
||||||
{
|
{
|
||||||
char *decodedText;
|
nsCString decodedText;
|
||||||
NS_ASSERTION(aQOrBase64 == 'Q' || aQOrBase64 == 'B', "Should be 'Q' or 'B'");
|
NS_ASSERTION(aQOrBase64 == 'Q' || aQOrBase64 == 'B', "Should be 'Q' or 'B'");
|
||||||
if(aQOrBase64 == 'Q')
|
if(aQOrBase64 == 'Q') {
|
||||||
decodedText = DecodeQ(aEncoded, aLen);
|
Maybe<nsCString> decoded = DecodeQ(aEncoded, aLen);
|
||||||
else if (aQOrBase64 == 'B') {
|
if (!decoded) {
|
||||||
decodedText = PL_Base64Decode(aEncoded, aLen, nullptr);
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
decodedText = std::move(*decoded);
|
||||||
|
} else if (aQOrBase64 == 'B') {
|
||||||
|
if (NS_FAILED(
|
||||||
|
mozilla::Base64Decode(Substring(aEncoded, aLen), decodedText))) {
|
||||||
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!decodedText) {
|
if (ContainsNull(decodedText)) {
|
||||||
|
// a NUL would truncate the decoded value
|
||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1174,12 +1156,11 @@ nsresult DecodeQOrBase64Str(const char *aEncoded, size_t aLen, char aQOrBase64,
|
|||||||
nsAutoCString utf8Text;
|
nsAutoCString utf8Text;
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv)) {
|
||||||
// skip ASCIIness/UTF8ness test if aCharset is 7bit non-ascii charset.
|
// skip ASCIIness/UTF8ness test if aCharset is 7bit non-ascii charset.
|
||||||
rv = cvtUTF8->ConvertStringToUTF8(nsDependentCString(decodedText),
|
rv = cvtUTF8->ConvertStringToUTF8(decodedText,
|
||||||
aCharset,
|
aCharset,
|
||||||
IS_7BIT_NON_ASCII_CHARSET(aCharset),
|
IS_7BIT_NON_ASCII_CHARSET(aCharset),
|
||||||
true, 1, utf8Text);
|
true, 1, utf8Text);
|
||||||
}
|
}
|
||||||
PR_Free(decodedText);
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -825,6 +825,13 @@ nsHttpChannelAuthProvider::GetCredentialsForChallenge(const char *challenge,
|
|||||||
// as restartable.
|
// as restartable.
|
||||||
mAuthChannel->ConnectionRestartable(mConnectionBased && !authAtProgress);
|
mAuthChannel->ConnectionRestartable(mConnectionBased && !authAtProgress);
|
||||||
|
|
||||||
|
if (identFromURI &&
|
||||||
|
(authFlags & nsIHttpAuthenticator::IDENTITY_INCLUDES_DOMAIN)) {
|
||||||
|
LOG((" ignoring URL identity for a domain-identity scheme\n"));
|
||||||
|
ident->Clear();
|
||||||
|
identFromURI = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (identityInvalid) {
|
if (identityInvalid) {
|
||||||
if (entry) {
|
if (entry) {
|
||||||
if (ident->Equals(entry->Identity())) {
|
if (ident->Equals(entry->Identity())) {
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel *channel,
|
|||||||
if (PL_strcasecmp(challenge, "NTLM") == 0) {
|
if (PL_strcasecmp(challenge, "NTLM") == 0) {
|
||||||
nsCOMPtr<nsISupports> module;
|
nsCOMPtr<nsISupports> module;
|
||||||
|
|
||||||
|
mAllowDefaultCredentials = CanUseDefaultCredentials(channel, isProxyAuth);
|
||||||
// Check to see if we should default to our generic NTLM auth module
|
// Check to see if we should default to our generic NTLM auth module
|
||||||
// through UseGenericNTLM. (We use native auth by default if the
|
// through UseGenericNTLM. (We use native auth by default if the
|
||||||
// system provides it.) If *sessionState is non-null, we failed to
|
// system provides it.) If *sessionState is non-null, we failed to
|
||||||
@@ -288,7 +289,7 @@ nsHttpNTLMAuth::ChallengeReceived(nsIHttpAuthenticableChannel *channel,
|
|||||||
// Check for approved default credentials hosts and proxies. If
|
// Check for approved default credentials hosts and proxies. If
|
||||||
// *continuationState is non-null, the last authentication attempt
|
// *continuationState is non-null, the last authentication attempt
|
||||||
// failed so skip default credential use.
|
// failed so skip default credential use.
|
||||||
if (!*continuationState && CanUseDefaultCredentials(channel, isProxyAuth)) {
|
if (!*continuationState && mAllowDefaultCredentials) {
|
||||||
// Try logging in with the user's default credentials. If
|
// Try logging in with the user's default credentials. If
|
||||||
// successful, |identityInvalid| is false, which will trigger
|
// successful, |identityInvalid| is false, which will trigger
|
||||||
// a default credentials attempt once we return.
|
// a default credentials attempt once we return.
|
||||||
@@ -399,6 +400,13 @@ nsHttpNTLMAuth::GenerateCredentials(nsIHttpAuthenticableChannel *authChannel,
|
|||||||
|
|
||||||
// initial challenge
|
// initial challenge
|
||||||
if (PL_strcasecmp(challenge, "NTLM") == 0) {
|
if (PL_strcasecmp(challenge, "NTLM") == 0) {
|
||||||
|
// An empty user or password makes nsAuthSSPI::Init authenticate as the
|
||||||
|
// logged-in user, which only CanUseDefaultCredentials() hosts may do.
|
||||||
|
if (mUseNative && !mAllowDefaultCredentials &&
|
||||||
|
(!*user || !*pass)) {
|
||||||
|
LOG(("Not using default credentials for an untrusted host\n"));
|
||||||
|
return NS_ERROR_ABORT;
|
||||||
|
}
|
||||||
// NTLM service name format is 'HTTP@host' for both http and https
|
// NTLM service name format is 'HTTP@host' for both http and https
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
rv = authChannel->GetURI(getter_AddRefs(uri));
|
rv = authChannel->GetURI(getter_AddRefs(uri));
|
||||||
|
|||||||
@@ -22,7 +22,11 @@ private:
|
|||||||
|
|
||||||
// This flag indicates whether we are using the native NTLM implementation
|
// This flag indicates whether we are using the native NTLM implementation
|
||||||
// or the internal one.
|
// or the internal one.
|
||||||
bool mUseNative;
|
bool mUseNative;
|
||||||
|
|
||||||
|
// Whether the prefs let this host use the logged-in user's identity. Set by
|
||||||
|
// ChallengeReceived, read by GenerateCredentials.
|
||||||
|
bool mAllowDefaultCredentials = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace net
|
} // namespace net
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include "nsIHTMLDocument.h"
|
#include "nsIHTMLDocument.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "nsTextNode.h"
|
#include "nsTextNode.h"
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
@@ -690,7 +691,9 @@ nsHtml5TreeOperation::CreateMathMLElement(nsIAtom* aName,
|
|||||||
void
|
void
|
||||||
nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
|
nsHtml5TreeOperation::SetFormElement(nsIContent* aNode, nsIContent* aParent)
|
||||||
{
|
{
|
||||||
if (aNode->SubtreeRoot() != aParent->SubtreeRoot()) {
|
// sFormSubtreeStrict is a pref to temporarily disable this check. See UXP #3197
|
||||||
|
bool sFormSubtreeStrict = mozilla::Preferences::GetBool("html5.forms.standards_compliant", true);
|
||||||
|
if (sFormSubtreeStrict && aNode->SubtreeRoot() != aParent->SubtreeRoot()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
|
nsCOMPtr<nsIFormControl> formControl(do_QueryInterface(aNode));
|
||||||
|
|||||||
+2772
-3809
File diff suppressed because it is too large.
Load diff
@@ -184,8 +184,18 @@ NS_IMETHODIMP nsDataObj::CStream::OnStopRequest(nsIRequest *aRequest,
|
|||||||
// Pumps thread messages while waiting for the async listener operation to
|
// Pumps thread messages while waiting for the async listener operation to
|
||||||
// complete. Failing this call will fail the stream incall from Windows
|
// complete. Failing this call will fail the stream incall from Windows
|
||||||
// and cancel the operation.
|
// and cancel the operation.
|
||||||
|
// The method spins the event loop during operation and may unregister the
|
||||||
|
// CStream, so it holds a strong reference for its duration. Callers
|
||||||
|
// must consider that, upon return, the CStream may have been unregistered and
|
||||||
|
// destroyed, so they will need to hold a strong reference if they need it to
|
||||||
|
// exist after this.
|
||||||
nsresult nsDataObj::CStream::WaitForCompletion()
|
nsresult nsDataObj::CStream::WaitForCompletion()
|
||||||
{
|
{
|
||||||
|
// HttpBaseChannel::ReleaseListeners, as part of
|
||||||
|
// nsIRequestObserver::OnStopRequest, may drop its reference when we spin the
|
||||||
|
// event loop.
|
||||||
|
RefPtr<CStream> keepAliveDuringWait(this);
|
||||||
|
|
||||||
// We are guaranteed OnStopRequest will get called, so this should be ok.
|
// We are guaranteed OnStopRequest will get called, so this should be ok.
|
||||||
while (!mChannelRead) {
|
while (!mChannelRead) {
|
||||||
// Pump messages
|
// Pump messages
|
||||||
@@ -233,6 +243,8 @@ STDMETHODIMP nsDataObj::CStream::Read(void* pvBuffer,
|
|||||||
ULONG nBytesToRead,
|
ULONG nBytesToRead,
|
||||||
ULONG* nBytesRead)
|
ULONG* nBytesRead)
|
||||||
{
|
{
|
||||||
|
RefPtr<CStream> keepAliveDuringRead(this);
|
||||||
|
|
||||||
// Wait for the write into our buffer to complete via the stream listener.
|
// Wait for the write into our buffer to complete via the stream listener.
|
||||||
// We can't respond to this by saying "call us back later".
|
// We can't respond to this by saying "call us back later".
|
||||||
if (NS_FAILED(WaitForCompletion()))
|
if (NS_FAILED(WaitForCompletion()))
|
||||||
@@ -285,6 +297,8 @@ STDMETHODIMP nsDataObj::CStream::Stat(STATSTG* statstg, DWORD dwFlags)
|
|||||||
if (statstg == nullptr)
|
if (statstg == nullptr)
|
||||||
return STG_E_INVALIDPOINTER;
|
return STG_E_INVALIDPOINTER;
|
||||||
|
|
||||||
|
RefPtr<CStream> keepAliveDuringRead(this);
|
||||||
|
|
||||||
if (!mChannel || NS_FAILED(WaitForCompletion()))
|
if (!mChannel || NS_FAILED(WaitForCompletion()))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
@@ -299,6 +313,8 @@ STDMETHODIMP nsDataObj::CStream::Stat(STATSTG* statstg, DWORD dwFlags)
|
|||||||
|
|
||||||
nsAutoCString strFileName;
|
nsAutoCString strFileName;
|
||||||
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
|
nsCOMPtr<nsIURL> sourceURL = do_QueryInterface(sourceURI);
|
||||||
|
if (!sourceURL) return E_FAIL;
|
||||||
|
|
||||||
sourceURL->GetFileName(strFileName);
|
sourceURL->GetFileName(strFileName);
|
||||||
|
|
||||||
if (strFileName.IsEmpty())
|
if (strFileName.IsEmpty())
|
||||||
|
|||||||
@@ -1776,10 +1776,11 @@ nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
|
|||||||
|
|
||||||
size_t
|
size_t
|
||||||
nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
|
||||||
const
|
|
||||||
{
|
{
|
||||||
size_t n = aMallocSizeOf(this);
|
size_t n = aMallocSizeOf(this);
|
||||||
|
|
||||||
|
SafeMutexAutoLock lock(mLock);
|
||||||
|
|
||||||
n += mLoaderMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
n += mLoaderMap.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||||
|
|
||||||
n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
n += mFactories.ShallowSizeOfExcludingThis(aMallocSizeOf);
|
||||||
|
|||||||
@@ -327,7 +327,7 @@ public:
|
|||||||
|
|
||||||
nsTArray<PendingServiceInfo> mPendingServices;
|
nsTArray<PendingServiceInfo> mPendingServices;
|
||||||
|
|
||||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~nsComponentManagerImpl();
|
~nsComponentManagerImpl();
|
||||||
|
|||||||
@@ -3009,6 +3009,7 @@ nsLocalFile::IsExecutable(bool* aResult)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Search for any of the set of executable extensions.
|
// Search for any of the set of executable extensions.
|
||||||
|
// Note: always use lower case here since we lowercase the extensions before comparing.
|
||||||
static const char* const executableExts[] = {
|
static const char* const executableExts[] = {
|
||||||
"ad",
|
"ad",
|
||||||
"ade", // access project extension
|
"ade", // access project extension
|
||||||
@@ -3016,6 +3017,7 @@ nsLocalFile::IsExecutable(bool* aResult)
|
|||||||
"air", // Adobe AIR installer
|
"air", // Adobe AIR installer
|
||||||
"app", // executable application
|
"app", // executable application
|
||||||
"application", // from bug 348763
|
"application", // from bug 348763
|
||||||
|
"appcontent-ms",
|
||||||
"appref-ms", // ClickOnce link
|
"appref-ms", // ClickOnce link
|
||||||
"appx",
|
"appx",
|
||||||
"appxbundle",
|
"appxbundle",
|
||||||
@@ -3061,11 +3063,12 @@ nsLocalFile::IsExecutable(bool* aResult)
|
|||||||
"msc",
|
"msc",
|
||||||
"msh", // Microsoft Shell
|
"msh", // Microsoft Shell
|
||||||
"mshxml", // Microsoft Shell
|
"mshxml", // Microsoft Shell
|
||||||
"msi",
|
"msi", // Standalone microsoft installer package
|
||||||
"msix",
|
"msix",
|
||||||
"msixbundle",
|
"msixbundle",
|
||||||
"msp",
|
"msp",
|
||||||
"mst",
|
"mst",
|
||||||
|
// "msu", // Windows Update Standalone Installer. Gated by Windows on MS signatures already.
|
||||||
"ops", // Office Profile Settings
|
"ops", // Office Profile Settings
|
||||||
"pcd",
|
"pcd",
|
||||||
"pif",
|
"pif",
|
||||||
@@ -3077,7 +3080,8 @@ nsLocalFile::IsExecutable(bool* aResult)
|
|||||||
"scf", // Windows explorer command
|
"scf", // Windows explorer command
|
||||||
"scr",
|
"scr",
|
||||||
"sct",
|
"sct",
|
||||||
"search-ms", // Windows Saved Search
|
"searchconnector-ms", // Windows Search connector installs an OpenSearch provider
|
||||||
|
"search-ms", // Windows Saved Search
|
||||||
"settingcontent-ms",
|
"settingcontent-ms",
|
||||||
"shb",
|
"shb",
|
||||||
"shs",
|
"shs",
|
||||||
|
|||||||
Reference in new issue
Block a user