Compare commits
400
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
810c2bf808 | ||
|
|
203be74ffe | ||
|
|
0ea6dd009f | ||
|
|
dabdec3b3a | ||
|
|
cd17592001 | ||
|
|
62d550e22d | ||
|
|
2f60cae35e | ||
|
|
65bbd1acb6 | ||
|
|
3edea8e9e0 | ||
|
|
fc539ba189 | ||
|
|
68299c8613 | ||
|
|
d0b7069d1c | ||
|
|
55dbbe4d16 | ||
|
|
a52529970f | ||
|
|
bcb46bf65e | ||
|
|
176f4fe206 | ||
|
|
aed41dc542 | ||
|
|
a7a521e378 | ||
|
|
e9b56e301c | ||
|
|
57debb342a | ||
|
|
78219cdbf1 | ||
|
|
c68e97f01c | ||
|
|
5165ed0228 | ||
|
|
ca9abcdf17 | ||
|
|
459c36b9df | ||
|
|
c9508464d5 | ||
|
|
2219a336dd | ||
|
|
a6763e7451 | ||
|
|
727f4372a9 | ||
|
|
556a15567d | ||
|
|
95d93b55c9 | ||
|
|
693dc6a5fc | ||
|
|
08cc9cd558 | ||
|
|
4f0f4aa879 | ||
|
|
53ca366d2b | ||
|
|
14f7bec523 | ||
|
|
976ccaa922 | ||
|
|
8b3375e2c2 | ||
|
|
8fefeee3c3 | ||
|
|
b645d59b1e | ||
|
|
71e0814af2 | ||
|
|
5744d59188 | ||
|
|
45a976a5f1 | ||
|
|
06f9b815ce | ||
|
|
0032e8313d | ||
|
|
d7df9b336a | ||
|
|
6c1b1bd18f | ||
|
|
770cb9a4b9 | ||
|
|
90309c01a8 | ||
|
|
4de0e9c68d | ||
|
|
4dae04e594 | ||
|
|
b9c41e2624 | ||
|
|
e1db27e199 | ||
|
|
a5203631d8 | ||
|
|
e2fe23c90b | ||
|
|
fcc0241430 | ||
|
|
24657db629 | ||
|
|
4939447eb7 | ||
|
|
f07d60c09f | ||
|
|
d7a05ea9e5 | ||
|
|
10bf4a6d5b | ||
|
|
c3778db14d | ||
|
|
abcee4f85c | ||
|
|
67a7e4eabd | ||
|
|
c1ef954679 | ||
|
|
eac19e3356 | ||
|
|
a98d06380f | ||
|
|
1e8d07cac2 | ||
|
|
e7a0013f81 | ||
|
|
17b4d049f4 | ||
|
|
abf1d5a099 | ||
|
|
b7dac18c0e | ||
|
|
63a0006985 | ||
|
|
e50094ab02 | ||
|
|
d11196927a | ||
|
|
af6a8637f5 | ||
|
|
5a9f8ae723 | ||
|
|
9f5c27ba47 | ||
|
|
f624bd1375 | ||
|
|
312f0b3a76 | ||
|
|
04479387a2 | ||
|
|
b0c271c7f9 | ||
|
|
37efb98518 | ||
|
|
3272147d97 | ||
|
|
f2866a5420 | ||
|
|
b862145e9c | ||
|
|
e2e483ac47 | ||
|
|
892a2d9655 | ||
|
|
075fa01286 | ||
|
|
32e0d2ca23 | ||
|
|
791d5f8a43 | ||
|
|
ed1f54ab73 | ||
|
|
eb1315e093 | ||
|
|
fa9730a46c | ||
|
|
ba0518147f | ||
|
|
7564818c79 | ||
|
|
10866dd35c | ||
|
|
f43c37cabe | ||
|
|
157f218c8d | ||
|
|
d49fb8a691 | ||
|
|
71b988d1b4 | ||
|
|
ddc43bf9d7 | ||
|
|
5819a1a525 | ||
|
|
351974555b | ||
|
|
abaea77ccb | ||
|
|
4698b4b3ca | ||
|
|
798f0bd3ad | ||
|
|
427d325d0c | ||
|
|
9c515323ff | ||
|
|
c2b91aaf8c | ||
|
|
1da42403ec | ||
|
|
602fbdcb44 | ||
|
|
42f895f27f | ||
|
|
a6f632714f | ||
|
|
b28effe2ea | ||
|
|
afd6edd667 | ||
|
|
582a1ce72a | ||
|
|
71ac56ba40 | ||
|
|
ae184d09e6 | ||
|
|
868f0755ae | ||
|
|
5ca8fbd41c | ||
|
|
549c8b9283 | ||
|
|
77e8ba7eaf | ||
|
|
e854d58633 | ||
|
|
d58cb8e11b | ||
|
|
429a7bdb93 | ||
|
|
3f14e9ec5f | ||
|
|
aefb293793 | ||
|
|
c583315558 | ||
|
|
834ecdc59a | ||
|
|
798c2ed4f8 | ||
|
|
767b637c83 | ||
|
|
702ad218b0 | ||
|
|
b9af9c0c51 | ||
|
|
9d6e28d3d0 | ||
|
|
c735355ae1 | ||
|
|
10a10fd375 | ||
|
|
1012dbe9e5 | ||
|
|
9982c1f5cb | ||
|
|
fe912e94e4 | ||
|
|
770b1c9071 | ||
|
|
daf56131a7 | ||
|
|
d8686de401 | ||
|
|
c8a38346c8 | ||
|
|
70bafe4df5 | ||
|
|
498b1ab0c8 | ||
|
|
2f145b6eda | ||
|
|
06a092d08e | ||
|
|
d107016d37 | ||
|
|
63371593c0 | ||
|
|
ce1dc7e6c6 | ||
|
|
a4780ebaeb | ||
|
|
c384fa6e25 | ||
|
|
5e8e0d05a6 | ||
|
|
bf95a03189 | ||
|
|
c75e412f17 | ||
|
|
0bbe6ec105 | ||
|
|
48d31ea5eb | ||
|
|
3cf0843679 | ||
|
|
ff21776616 | ||
|
|
2f022ab1fa | ||
|
|
14e7f881be | ||
|
|
4f03fb2798 | ||
|
|
3dd316f739 | ||
|
|
972ab6d437 | ||
|
|
83ae5bd019 | ||
|
|
c237a54f23 | ||
|
|
8f72a673ca | ||
|
|
3266e0976f | ||
|
|
4433519ae8 | ||
|
|
d419fe2d52 | ||
|
|
c77c6de9ce | ||
|
|
2ed0607c74 | ||
|
|
922a72766c | ||
|
|
16d1313104 | ||
|
|
0387f52bd3 | ||
|
|
a1ca8ca9bd | ||
|
|
2ee2ca7dfb | ||
|
|
0d7b7b74c6 | ||
|
|
45db2388fe | ||
|
|
323288bc72 | ||
|
|
3323a8eda3 | ||
|
|
71293f0fe4 | ||
|
|
a91722be27 | ||
|
|
1ef64f9ea3 | ||
|
|
4a960879c8 | ||
|
|
4329ae3337 | ||
|
|
ad453f0b28 | ||
|
|
d332d4a60d | ||
|
|
ad5e9449d2 | ||
|
|
71848c23a4 | ||
|
|
1d321e689e | ||
|
|
b9b9d5bfb9 | ||
|
|
b92abc83c2 | ||
|
|
4950c982e0 | ||
|
|
86b184b957 | ||
|
|
33ba46c6bb | ||
|
|
451980d51b | ||
|
|
4ddbe58171 | ||
|
|
84caa4f3ad | ||
|
|
4f44e23c16 | ||
|
|
a69eda9b9c | ||
|
|
f1b51be787 | ||
|
|
82faff19e1 | ||
|
|
1597b61148 | ||
|
|
694c5f889c | ||
|
|
c1f8c0cb5d | ||
|
|
dcab408a5f | ||
|
|
407c503fa4 | ||
|
|
9130f12906 | ||
|
|
5e2b3d1d89 | ||
|
|
0c5a41e894 | ||
|
|
e29a8bd113 | ||
|
|
83abc5af59 | ||
|
|
47101f49c0 | ||
|
|
f6a6900a6b | ||
|
|
40aad1a220 | ||
|
|
1e14031a59 | ||
|
|
765c90318f | ||
|
|
ef8d18da70 | ||
|
|
7bf3e4c464 | ||
|
|
57523a0deb | ||
|
|
3f25d0c8e4 | ||
|
|
ab05017026 | ||
|
|
255c7f6f3a | ||
|
|
5ffe27bb03 | ||
|
|
0633844f46 | ||
|
|
d0126b96cd | ||
|
|
d4cd571021 | ||
|
|
016c55f409 | ||
|
|
016313d559 | ||
|
|
1fa428a789 | ||
|
|
d41fe2f55a | ||
|
|
4d9da86152 | ||
|
|
aa19e3d8ba | ||
|
|
f5b146a460 | ||
|
|
e2403eeb5a | ||
|
|
301ae8c2df | ||
|
|
21403c31e0 | ||
|
|
29bca891d5 | ||
|
|
bb70605829 | ||
|
|
3f3d626434 | ||
|
|
a04d67dd12 | ||
|
|
9e2da53a02 | ||
|
|
2b41c85019 | ||
|
|
e9d41c9968 | ||
|
|
0e0feed5da | ||
|
|
7f238b1cf9 | ||
|
|
6235023c8b | ||
|
|
f51beb3fda | ||
|
|
a934165b57 | ||
|
|
2516886ceb | ||
|
|
fbab1f4f9e | ||
|
|
90c42b7afd | ||
|
|
2deaddfca2 | ||
|
|
0ccb51f2ae | ||
|
|
5e5f2277f5 | ||
|
|
265d1b8019 | ||
|
|
687f535b9c | ||
|
|
54b4fb0be6 | ||
|
|
a054ece041 | ||
|
|
c6ca4380e9 | ||
|
|
744b044935 | ||
|
|
b246f7b2f1 | ||
|
|
8618719921 | ||
|
|
b6db7da98a | ||
|
|
9805ddc483 | ||
|
|
83ac4391b6 | ||
|
|
027a4cac9c | ||
|
|
66470fa1d8 | ||
|
|
451509e2c0 | ||
|
|
7895b8acd9 | ||
|
|
ccff4610c5 | ||
|
|
3045e1d5c9 | ||
|
|
44de3c3023 | ||
|
|
a3124c55a1 | ||
|
|
c4ed566602 | ||
|
|
15a1f78f8b | ||
|
|
8b44473fe6 | ||
|
|
6e0aee959e | ||
|
|
99c2e698d2 | ||
|
|
15ac4021b0 | ||
|
|
344b272991 | ||
|
|
fb8fcffe1d | ||
|
|
b67a630966 | ||
|
|
a148bd40d8 | ||
|
|
e59757fddf | ||
|
|
be954fca72 | ||
|
|
f411e02716 | ||
|
|
a34d02924c | ||
|
|
084ea153c1 | ||
|
|
c40bda67bb | ||
|
|
0c2de12ffd | ||
|
|
e44709892b | ||
|
|
237f8d7ebd | ||
|
|
5001007287 | ||
|
|
f83a88907a | ||
|
|
ff8603d7a2 | ||
|
|
31ad2d12db | ||
|
|
494cfe32c9 | ||
|
|
b4f0be5e95 | ||
|
|
ac62e4cfdd | ||
|
|
0fa41e2adc | ||
|
|
61af6cc299 | ||
|
|
c3a21acaee | ||
|
|
3fb8648bed | ||
|
|
f18d78dea0 | ||
|
|
16ae8db806 | ||
|
|
43f57fe642 | ||
|
|
f50410bd79 | ||
|
|
609d904cc1 | ||
|
|
fa1628f767 | ||
|
|
0136960ec0 | ||
|
|
d9e0b4be85 | ||
|
|
a17ab79b88 | ||
|
|
f11fff32fa | ||
|
|
912e37d202 | ||
|
|
e15b6906c5 | ||
|
|
b048f3d473 | ||
|
|
6cdd6c6286 | ||
|
|
25c1a5cbe3 | ||
|
|
83a71d9c9d | ||
|
|
d8a0849b7f | ||
|
|
02923a3648 | ||
|
|
a5da610b87 | ||
|
|
aedf5c0169 | ||
|
|
1c16924e08 | ||
|
|
9c21ed1804 | ||
|
|
41b982b9bb | ||
|
|
4c76b52e09 | ||
|
|
e50cfc7b63 | ||
|
|
8bbc95988a | ||
|
|
ed9eb8f722 | ||
|
|
1cd91bc155 | ||
|
|
8c8e5fba69 | ||
|
|
ed1ea719dd | ||
|
|
d38d5414fc | ||
|
|
1182ecd0b4 | ||
|
|
3220b7dc56 | ||
|
|
3e82ac05b1 | ||
|
|
3ab7bd811f | ||
|
|
8c4892fb45 | ||
|
|
11749de754 | ||
|
|
5186d78330 | ||
|
|
0538c32e32 | ||
|
|
46040d136d | ||
|
|
35c731cf08 | ||
|
|
b1851a4ad0 | ||
|
|
935ce8fa8e | ||
|
|
85b89ee754 | ||
|
|
9c006089e1 | ||
|
|
c3fc87a904 | ||
|
|
5f04717b00 | ||
|
|
e74b4ad8f8 | ||
|
|
fa68aa6fd5 | ||
|
|
9f37161ec5 | ||
|
|
21348b56d9 | ||
|
|
ad69c023a9 | ||
|
|
206b1af429 | ||
|
|
2bdbc482e7 | ||
|
|
a444b5cc39 | ||
|
|
d050188cd5 | ||
|
|
3a1bebfb87 | ||
|
|
d3d3aad6e5 | ||
|
|
d8d0538162 | ||
|
|
36369e0fef | ||
|
|
3c1e71f0b1 | ||
|
|
71137783ac | ||
|
|
fe0963002f | ||
|
|
aeef4240d5 | ||
|
|
938e6204ef | ||
|
|
16aaa21930 | ||
|
|
6b7997abbe | ||
|
|
f358c4dfa9 | ||
|
|
ad5cb04d71 | ||
|
|
ba5930cc8e | ||
|
|
6376255c0c | ||
|
|
9be6582ec3 | ||
|
|
883fa80f7d | ||
|
|
82b6d2cf9d | ||
|
|
09b4a7828e | ||
|
|
ed58b7905e | ||
|
|
31f47a2ba4 | ||
|
|
8b3b858546 | ||
|
|
dd506c896f | ||
|
|
f8588a2e86 | ||
|
|
0aa1b02b2b | ||
|
|
e008deb88b | ||
|
|
56cb90a482 | ||
|
|
812574875b | ||
|
|
cd196a77d4 | ||
|
|
e175224b88 | ||
|
|
0afb9e2d75 | ||
|
|
e733c3681b | ||
|
|
157cd64a8e | ||
|
|
5c3c92da90 | ||
|
|
aa21f96cf5 | ||
|
|
537c63d600 | ||
|
|
975db4c7f0 | ||
|
|
528abd534e |
No files matched your search
@@ -22,5 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for NSS Update
|
||||
|
||||
Clobber for NSS update
|
||||
@@ -18,7 +18,7 @@ directory. This will contain relevant documentation regarding contributing,
|
||||
using and distributing this code and its binaries.
|
||||
|
||||
If you are interested in the development and building side of things, some
|
||||
information will be available on the [Pale Moon developer wiki](http://developer.palemoon.org).
|
||||
information will be available on the [Pale Moon developer site](http://developer.palemoon.org).
|
||||
You are also always welcome to get in touch with our community on the [Pale Moon forum](https://forum.palemoon.org/).
|
||||
|
||||
### A note about trademarks and branding
|
||||
@@ -36,4 +36,4 @@ improvement patches upstream to its origin to mutually improve the platform and
|
||||
a future for XUL.
|
||||
|
||||
## Looking for Pale Moon and Basilisk?
|
||||
As of [`Issue #969`](https://github.com/MoonchildProductions/UXP/issues/969), release versions `28.9.0` and `2020.03.04` respectively, they have been split off into their own dedicated repositories located at [`MoonchildProductions/Pale-Moon`](https://github.com/MoonchildProductions/Pale-Moon) and [`MoonchildProductions/Basilisk`](https://github.com/MoonchildProductions/Basilisk).
|
||||
As of [`Issue #969`](https://repo.palemoon.org/MoonchildProductions/UXP/issues/969), release versions `28.9.0` and `2020.03.04` respectively, they have been split off into their own dedicated repositories located at [`MoonchildProductions/Pale-Moon`](https://repo.palemoon.org/MoonchildProductions/Pale-Moon) and [`MoonchildProductions/Basilisk`](https://repo.palemoon.org/MoonchildProductions/Basilisk).
|
||||
+1
-1
@@ -23,7 +23,7 @@ Generally not security vulnerabilities:
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you find an issue in UXP or the applications it builds on that could impact the security or safety of users please **do not**
|
||||
make an issue on GitHub about it. GitHub does not support restricted viewability for security sensitive bugs.
|
||||
make an issue on Gitea about it. Gitea does not support restricted viewability for security sensitive bugs.
|
||||
|
||||
If you want to report a security-sensitive issue then please go to the [forum](https://forum.palemoon.org) and report the issue
|
||||
via a **private message** to **Moonchild** (the founder and prime responsible for security issues).
|
||||
|
||||
@@ -347,16 +347,6 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // marquee
|
||||
&nsGkAtoms::marquee,
|
||||
roles::ANIMATION,
|
||||
kUseMapRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eOffLiveAttr,
|
||||
kGenericAccType,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // math
|
||||
&nsGkAtoms::math,
|
||||
roles::FLAT_EQUATION,
|
||||
|
||||
@@ -732,8 +732,6 @@ using namespace mozilla::a11y;
|
||||
return @"AXDocument";
|
||||
if (roleAtom == nsGkAtoms::log_)
|
||||
return @"AXApplicationLog";
|
||||
if (roleAtom == nsGkAtoms::marquee)
|
||||
return @"AXApplicationMarquee";
|
||||
if (roleAtom == nsGkAtoms::math)
|
||||
return @"AXDocumentMath";
|
||||
if (roleAtom == nsGkAtoms::note_)
|
||||
@@ -869,7 +867,6 @@ static const RoleDescrMap sRoleDescrMap[] = {
|
||||
{ @"AXApplicationAlert", NS_LITERAL_STRING("alert") },
|
||||
{ @"AXApplicationAlertDialog", NS_LITERAL_STRING("alertDialog") },
|
||||
{ @"AXApplicationLog", NS_LITERAL_STRING("log") },
|
||||
{ @"AXApplicationMarquee", NS_LITERAL_STRING("marquee") },
|
||||
{ @"AXApplicationStatus", NS_LITERAL_STRING("status") },
|
||||
{ @"AXApplicationTimer", NS_LITERAL_STRING("timer") },
|
||||
{ @"AXContentSeparator", NS_LITERAL_STRING("separator") },
|
||||
|
||||
@@ -62,7 +62,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
testAbsentAttrs("live3", {"live" : ""});
|
||||
testAttrs("log", {"live" : "polite"}, true);
|
||||
testAttrs("logAssertive", {"live" : "assertive"}, true);
|
||||
testAttrs("marquee", {"live" : "off"}, true);
|
||||
testAttrs("status", {"live" : "polite"}, true);
|
||||
testAttrs("timer", {"live" : "off"}, true);
|
||||
testAbsentAttrs("tablist", {"live" : "polite"});
|
||||
@@ -72,7 +71,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
testAttrs("live2Child", {"container-live" : "polite"}, true);
|
||||
testAttrs("logChild", {"container-live" : "polite"}, true);
|
||||
testAttrs("logAssertiveChild", {"container-live" : "assertive"}, true);
|
||||
testAttrs("marqueeChild", {"container-live" : "off"}, true);
|
||||
testAttrs("statusChild", {"container-live" : "polite"}, true);
|
||||
testAttrs("timerChild", {"container-live" : "off"}, true);
|
||||
testAbsentAttrs("tablistChild", {"container-live" : "polite"});
|
||||
@@ -80,13 +78,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
// container-live-role object attribute
|
||||
testAttrs("log", {"container-live-role" : "log"}, true);
|
||||
testAttrs("logAssertive", {"container-live-role" : "log"}, true);
|
||||
testAttrs("marquee", {"container-live-role" : "marquee"}, true);
|
||||
testAttrs("status", {"container-live-role" : "status"}, true);
|
||||
testAttrs("timer", {"container-live-role" : "timer"}, true);
|
||||
testAttrs("logChild", {"container-live-role" : "log"}, true);
|
||||
testAttrs("logAssertive", {"container-live-role" : "log"}, true);
|
||||
testAttrs("logAssertiveChild", {"container-live-role" : "log"}, true);
|
||||
testAttrs("marqueeChild", {"container-live-role" : "marquee"}, true);
|
||||
testAttrs("statusChild", {"container-live-role" : "status"}, true);
|
||||
testAttrs("timerChild", {"container-live-role" : "timer"}, true);
|
||||
testAbsentAttrs("tablistChild", {"container-live-role" : "tablist"});
|
||||
@@ -230,11 +226,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
|
||||
<!-- back to aria -->
|
||||
<div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
|
||||
<div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
|
||||
<div id="live3" role="region">excuse</div>
|
||||
<div id="log" role="log">excuse <div id="logChild">me</div></div>
|
||||
<div id="logAssertive" role="log" aria-live="assertive">excuse <div id="logAssertiveChild">me</div></div>
|
||||
<div id="marquee" role="marquee">excuse <div id="marqueeChild">me</div></div>
|
||||
<div id="status" role="status">excuse <div id="statusChild">me</div></div>
|
||||
<div id="tablist" role="tablist">tablist <div id="tablistChild">tab</div></div>
|
||||
<div id="timer" role="timer">excuse <div id="timerChild">me</div></div>
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
'listitem-2-3']);
|
||||
|
||||
queueTraversalSequence(gQueue, docAcc, TraversalRules.Graphic, null,
|
||||
['image-2', 'image-3']);
|
||||
['image-1', 'image-2', 'image-3']);
|
||||
|
||||
queueTraversalSequence(gQueue, docAcc, TraversalRules.Link, null,
|
||||
['link-0', 'link-1', 'link-2', 'link-3']);
|
||||
@@ -117,7 +117,7 @@
|
||||
'1. Scheme', '2. Racket', '3. Clojure',
|
||||
'4. Standard Lisp', 'link-0', ' Lisp',
|
||||
'checkbox-1-5', ' LeLisp', '• JavaScript',
|
||||
'heading-5', 'image-2', 'image-3',
|
||||
'heading-5', 'image-1', 'image-2', 'image-3',
|
||||
'Not actually an image', 'link-1', 'anchor-1',
|
||||
'link-2', 'anchor-2', 'link-3', '3', '1', '4',
|
||||
'1', 'Sunday', 'M', 'Week 1', '3', '4', '7', '2',
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
testRole("aria_listbox", ROLE_LISTBOX);
|
||||
testRole("aria_listitem", ROLE_LISTITEM);
|
||||
testRole("aria_log", ROLE_TEXT); // weak role
|
||||
testRole("aria_marquee", ROLE_ANIMATION);
|
||||
testRole("aria_math", ROLE_FLAT_EQUATION);
|
||||
testRole("aria_menu", ROLE_MENUPOPUP);
|
||||
testRole("aria_menubar", ROLE_MENUBAR);
|
||||
@@ -89,9 +88,6 @@
|
||||
testRole("log_table", ROLE_TABLE);
|
||||
testRole("timer_div", ROLE_SECTION);
|
||||
|
||||
// other roles that are forms of "live regions"
|
||||
testRole("marquee_h1", ROLE_ANIMATION);
|
||||
|
||||
// strong landmark
|
||||
testRole("application", ROLE_APPLICATION);
|
||||
testRole("form", ROLE_FORM);
|
||||
@@ -219,7 +215,6 @@
|
||||
<span id="aria_listbox" role="listbox"/>
|
||||
<span id="aria_listitem" role="listitem"/>
|
||||
<span id="aria_log" role="log"/>
|
||||
<span id="aria_marquee" role="marquee"/>
|
||||
<span id="aria_math" role="math"/>
|
||||
<span id="aria_menu" role="menu"/>
|
||||
<span id="aria_menubar" role="menubar"/>
|
||||
@@ -263,7 +258,6 @@
|
||||
<table role="log" id="log_table">
|
||||
<tr><td>Table based log</td></tr>
|
||||
</table>
|
||||
<h1 role="marquee" id="marquee_h1">marquee</h1>
|
||||
<div role="timer" id="timer_div">timer</div>
|
||||
|
||||
<!-- landmarks -->
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
document.getElementsByTagName("img")[0].firstChild.data = "2";
|
||||
|
||||
var accTree = {
|
||||
role: ROLE_TEXT,
|
||||
children: [ { role: ROLE_TEXT_LEAF } ]
|
||||
role: ROLE_GRAPHIC,
|
||||
children: []
|
||||
};
|
||||
testAccessibleTree("the_img", accTree);
|
||||
SimpleTest.finish();
|
||||
|
||||
@@ -38,7 +38,7 @@ if test -n "$USE_ICU"; then
|
||||
dnl We also don't do it on Windows because sometimes the file goes
|
||||
dnl missing -- possibly due to overzealous antivirus software? --
|
||||
dnl which prevents the browser from starting up :(
|
||||
if test -z "$JS_STANDALONE" -a "$OS_TARGET" != WINNT -a "$MOZ_WIDGET_TOOLKIT" != "android"; then
|
||||
if test -z "$JS_STANDALONE"; then
|
||||
MOZ_ICU_DATA_ARCHIVE=1
|
||||
else
|
||||
MOZ_ICU_DATA_ARCHIVE=
|
||||
|
||||
@@ -162,6 +162,8 @@ def old_configure_options(*options):
|
||||
'--enable-b2g-camera',
|
||||
'--enable-b2g-ril',
|
||||
'--enable-bundled-fonts',
|
||||
'--enable-chrome-compression',
|
||||
'--enable-chrome-format',
|
||||
'--enable-clang-plugin',
|
||||
'--enable-content-sandbox',
|
||||
'--enable-cookies',
|
||||
@@ -263,6 +265,7 @@ def old_configure_options(*options):
|
||||
'--with-app-name',
|
||||
'--with-arch',
|
||||
'--with-branding',
|
||||
'--with-chrome-name',
|
||||
'--with-crashreporter-enable-percent',
|
||||
'--with-cross-lib',
|
||||
'--with-debug-label',
|
||||
@@ -310,6 +313,7 @@ def old_configure_options(*options):
|
||||
'--disable-browser-statusbar',
|
||||
'--disable-sync',
|
||||
'--disable-personas',
|
||||
'--enable-phoenix-extensions',
|
||||
|
||||
# Below are configure flags used by Basilisk
|
||||
'--disable-webextensions',
|
||||
|
||||
+1
-1
@@ -216,7 +216,7 @@ endif # NO_PROFILE_GUIDED_OPTIMIZE
|
||||
|
||||
MAKE_JARS_FLAGS = \
|
||||
-t $(topsrcdir) \
|
||||
-f $(MOZ_JAR_MAKER_FILE_FORMAT) \
|
||||
-f $(MOZ_CHROME_FILE_FORMAT) \
|
||||
$(NULL)
|
||||
|
||||
ifdef USE_EXTENSION_MANIFEST
|
||||
|
||||
Vendored
-6
@@ -40,12 +40,6 @@ external_dirs += ['media/libwebp']
|
||||
if CONFIG['CPU_ARCH'] == 'arm':
|
||||
external_dirs += ['media/openmax_dl']
|
||||
|
||||
if CONFIG['MOZ_WEBSPEECH_POCKETSPHINX']:
|
||||
external_dirs += [
|
||||
'media/sphinxbase',
|
||||
'media/pocketsphinx',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FFVPX']:
|
||||
external_dirs += ['media/ffvpx']
|
||||
|
||||
|
||||
Vendored
+3
@@ -112,6 +112,7 @@ CERT_GetCertChainFromCert
|
||||
CERT_GetCertEmailAddress
|
||||
CERT_GetCertificateDer
|
||||
CERT_GetCertificateRequestExtensions
|
||||
CERT_GetCertKeyType
|
||||
CERT_GetCertTimes
|
||||
CERT_GetCertTrust
|
||||
CERT_GetCommonName
|
||||
@@ -270,6 +271,7 @@ NSS_Init
|
||||
NSS_Initialize
|
||||
NSS_InitWithMerge
|
||||
NSS_IsInitialized
|
||||
NSS_OptionGet
|
||||
NSS_OptionSet
|
||||
NSS_NoDB_Init
|
||||
NSS_SecureMemcmp
|
||||
@@ -383,6 +385,7 @@ PK11_GetNextSymKey
|
||||
PK11_GetPadMechanism
|
||||
PK11_GetPrivateKeyNickname
|
||||
PK11_GetPrivateModulusLen
|
||||
PK11_GetSlotFromPrivateKey
|
||||
PK11_GetSlotID
|
||||
PK11_GetSlotInfo
|
||||
PK11_GetSlotName
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
4.5.0
|
||||
4.7.0
|
||||
@@ -526,7 +526,6 @@ hardware/lights.h
|
||||
hardware/power.h
|
||||
hardware_legacy/power.h
|
||||
hardware_legacy/uevent.h
|
||||
hardware_legacy/vibrator.h
|
||||
#endif
|
||||
HIToolbox/HIToolbox.h
|
||||
hlink.h
|
||||
|
||||
@@ -22,7 +22,7 @@ REF_MANIFEST = $(if $(USE_EXTENSION_MANIFEST),chrome.manifest,test.manifest)
|
||||
|
||||
check-%::
|
||||
if test -d $(FINAL_TARGET); then rm -rf $(FINAL_TARGET); fi;
|
||||
$(MAKE) realchrome MOZ_JAR_MAKER_FILE_FORMAT=$*
|
||||
$(MAKE) realchrome MOZ_CHROME_FILE_FORMAT=$*
|
||||
@echo 'Comparing manifests...'
|
||||
@if ! sort $(MY_MANIFEST) | diff --text -U 0 $(srcdir)/../$(REF_MANIFEST).$* - ; then \
|
||||
echo 'TEST-UNEXPECTED-FAIL | config/tests/$(REF_MANIFEST).$* | differing content in manifest!' ; \
|
||||
|
||||
@@ -65,9 +65,13 @@ if CONFIG['MOZ_DEBUG']:
|
||||
|
||||
# Force using malloc_usable_size when building with jemalloc because _msize
|
||||
# causes assertions on Win64. See bug 719579.
|
||||
# This causes a known warning due to the way mozjemalloc is linked and the
|
||||
# malloc_usable_size function not being available at compile time on MSVC
|
||||
# so we suppress that particular warning (C4013)
|
||||
if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_MEMORY']:
|
||||
DEFINES['HAVE_MALLOC_USABLE_SIZE'] = True
|
||||
DEFINES['SQLITE_WITHOUT_MSIZE'] = True
|
||||
CFLAGS += ['-wd4013']
|
||||
|
||||
# Omit unused functions to save some library footprint.
|
||||
DEFINES['SQLITE_OMIT_DEPRECATED'] = True
|
||||
|
||||
+20958
-15503
File diff suppressed because it is too large.
Load diff
+1205
-888
File diff suppressed because it is too large.
Load diff
@@ -30,7 +30,7 @@ function* testTopLeft(inspector, view) {
|
||||
elementRulesNb: 4,
|
||||
firstLineRulesNb: 2,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 0,
|
||||
selectionRulesNb: 1,
|
||||
afterRulesNb: 1,
|
||||
beforeRulesNb: 2
|
||||
}
|
||||
@@ -167,7 +167,7 @@ function* testParagraph(inspector, view) {
|
||||
elementRulesNb: 3,
|
||||
firstLineRulesNb: 1,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 1,
|
||||
selectionRulesNb: 2,
|
||||
beforeRulesNb: 0,
|
||||
afterRulesNb: 0
|
||||
});
|
||||
@@ -217,7 +217,7 @@ function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
|
||||
firstLetterRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":first-letter"),
|
||||
selectionRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":-moz-selection"),
|
||||
rule.pseudoElement === ":selection"),
|
||||
beforeRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":before"),
|
||||
afterRules: elementStyle.rules.filter(rule =>
|
||||
|
||||
@@ -94,7 +94,7 @@ exports.menuitems = [
|
||||
},
|
||||
key: {
|
||||
id: "browserToolbox",
|
||||
modifiers: "accel,alt,shift",
|
||||
modifiers: isMac ? "accel,alt" : "accel,shift",
|
||||
keytext: true
|
||||
}
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
a {
|
||||
-moz-user-focus: normal;
|
||||
-moz-user-input: enabled;
|
||||
cursor: pointer;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@@ -1233,7 +1233,7 @@ exports.CSS_PROPERTIES = {
|
||||
"-moz-tab-size": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"-moz-tab-size"
|
||||
"tab-size"
|
||||
],
|
||||
"supports": [
|
||||
7
|
||||
@@ -1440,6 +1440,8 @@ exports.CSS_PROPERTIES = {
|
||||
"supports": [],
|
||||
"values": [
|
||||
"auto",
|
||||
"disabled",
|
||||
"enabled",
|
||||
"inherit",
|
||||
"initial",
|
||||
"none",
|
||||
@@ -2870,6 +2872,7 @@ exports.CSS_PROPERTIES = {
|
||||
"box-shadow",
|
||||
"box-sizing",
|
||||
"caption-side",
|
||||
"caret-color",
|
||||
"clear",
|
||||
"clip",
|
||||
"clip-path",
|
||||
@@ -3049,7 +3052,7 @@ exports.CSS_PROPERTIES = {
|
||||
"stroke-opacity",
|
||||
"stroke-width",
|
||||
"-x-system-font",
|
||||
"-moz-tab-size",
|
||||
"tab-size",
|
||||
"table-layout",
|
||||
"text-align",
|
||||
"text-align-last",
|
||||
@@ -5275,6 +5278,28 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"caret-color": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"caret-color"
|
||||
],
|
||||
"supports": [
|
||||
2
|
||||
],
|
||||
"values": [
|
||||
"COLOR",
|
||||
"auto",
|
||||
"currentColor",
|
||||
"hsl",
|
||||
"hsla",
|
||||
"inherit",
|
||||
"initial",
|
||||
"rgb",
|
||||
"rgba",
|
||||
"transparent",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"clear": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@@ -7855,6 +7880,7 @@ exports.CSS_PROPERTIES = {
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"anywhere",
|
||||
"break-word",
|
||||
"inherit",
|
||||
"initial",
|
||||
@@ -8624,6 +8650,23 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"tab-size": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"tab-size"
|
||||
],
|
||||
"supports": [
|
||||
6,
|
||||
7
|
||||
],
|
||||
"values": [
|
||||
"-moz-calc",
|
||||
"calc",
|
||||
"inherit",
|
||||
"initial",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"table-layout": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@@ -9315,6 +9358,7 @@ exports.CSS_PROPERTIES = {
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"anywhere",
|
||||
"break-word",
|
||||
"inherit",
|
||||
"initial",
|
||||
@@ -9371,6 +9415,7 @@ exports.PSEUDO_ELEMENTS = [
|
||||
":backdrop",
|
||||
":first-letter",
|
||||
":first-line",
|
||||
":selection",
|
||||
":-moz-selection",
|
||||
":-moz-focus-inner",
|
||||
":-moz-focus-outer",
|
||||
|
||||
@@ -93,15 +93,20 @@ With rare exception, it is advisable to use the following style for commit messa
|
||||
|
||||
This would directly apply to anyone making a pull request.
|
||||
|
||||
Single commits are where issues can be reasonably resolved in a single commit.
|
||||
- Single Commit: `Issue #xxx - Cited issue title or appropriate direct description of changes`
|
||||
- *`Issue #1083 - Deprecate FUEL extension helper javascript library`*
|
||||
- Multi-Part Commits: `Issue #xxx - Part Number: Appropriate direct description of changes`
|
||||
|
||||
Multi-part commits would be used for complex issues. However, an exception exists for multi-part commits where the issue is anticipated or ends up being long term such as "Stop using unified compilation of sources". In these instances the multi-part form is not required.
|
||||
- Multi-Part Form: `Issue #xxx - Part Number: Appropriate direct description of changes`
|
||||
- *`Issue #492 - Part 1: Remove files`*
|
||||
- *`Issue #492 - Part 2: Build system, Installer/Packaging`*
|
||||
- *`Issue #492 - Part 3: nsUpdateService.js, updater.cpp, nsUpdateDriver.cpp`*
|
||||
- *`Issue #492 - Part 4: Remove superfluous brackets in nsUpdateService.js and updater.cpp`*
|
||||
|
||||
An exception exists for multi-part commits where the issue is anticipated or ends up being long term such as "Stop using unified compilation of sources". In these instances the multi-part form is not required.
|
||||
Occasionally a resolved (and shipped) issue requires further changes to fix bugs. However, If follow-ups are complex enough to be multi-part it should be considered a new issue.
|
||||
- Follow-up Form: *`Issue #xxx - Follow-up: Appropriate direct description of changes`*
|
||||
- *`Issue #1643 - Follow-up: Make sure things aren't changed while iterating.`*
|
||||
|
||||
### Commits with no issue
|
||||
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AbortController.h"
|
||||
#include "AbortSignal.h"
|
||||
#include "mozilla/dom/AbortControllerBinding.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AbortController, mGlobal, mSignal)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(AbortController)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(AbortController)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AbortController)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
/* static */ bool
|
||||
AbortController::IsEnabled(JSContext* aCx, JSObject* aGlobal)
|
||||
{
|
||||
if (NS_IsMainThread()) {
|
||||
return Preferences::GetBool("dom.abortController.enabled", false);
|
||||
}
|
||||
|
||||
using namespace workers;
|
||||
|
||||
// Otherwise, check the pref via the WorkerPrivate
|
||||
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
|
||||
if (!workerPrivate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return workerPrivate->AbortControllerEnabled();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<AbortController>
|
||||
AbortController::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
if (!global) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<AbortController> abortController = new AbortController(global);
|
||||
return abortController.forget();
|
||||
}
|
||||
|
||||
AbortController::AbortController(nsIGlobalObject* aGlobal)
|
||||
: mGlobal(aGlobal)
|
||||
, mAborted(false)
|
||||
{}
|
||||
|
||||
JSObject*
|
||||
AbortController::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return AbortControllerBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsIGlobalObject*
|
||||
AbortController::GetParentObject() const
|
||||
{
|
||||
return mGlobal;
|
||||
}
|
||||
|
||||
AbortSignal*
|
||||
AbortController::Signal()
|
||||
{
|
||||
if (!mSignal) {
|
||||
mSignal = new AbortSignal(this, mAborted);
|
||||
}
|
||||
|
||||
return mSignal;
|
||||
}
|
||||
|
||||
void
|
||||
AbortController::Abort()
|
||||
{
|
||||
if (mAborted) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAborted = true;
|
||||
|
||||
if (mSignal) {
|
||||
mSignal->Abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
@@ -0,0 +1,59 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_AbortController_h
|
||||
#define mozilla_dom_AbortController_h
|
||||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/AbortSignal.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AbortController final : public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AbortController)
|
||||
|
||||
static bool
|
||||
IsEnabled(JSContext* aCx, JSObject* aGlobal);
|
||||
|
||||
static already_AddRefed<AbortController>
|
||||
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
||||
|
||||
explicit AbortController(nsIGlobalObject* aGlobal);
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
nsIGlobalObject*
|
||||
GetParentObject() const;
|
||||
|
||||
AbortSignal*
|
||||
Signal();
|
||||
|
||||
void
|
||||
Abort();
|
||||
|
||||
private:
|
||||
~AbortController() = default;
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mGlobal;
|
||||
RefPtr<AbortSignal> mSignal;
|
||||
|
||||
bool mAborted;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_AbortController_h
|
||||
@@ -0,0 +1,131 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AbortSignal.h"
|
||||
#include "AbortController.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "mozilla/dom/AbortSignalBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(AbortSignal)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AbortSignal,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mController)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AbortSignal,
|
||||
DOMEventTargetHelper)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mController)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AbortSignal)
|
||||
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(AbortSignal, DOMEventTargetHelper)
|
||||
NS_IMPL_RELEASE_INHERITED(AbortSignal, DOMEventTargetHelper)
|
||||
|
||||
AbortSignal::AbortSignal(AbortController* aController,
|
||||
bool aAborted)
|
||||
: DOMEventTargetHelper(aController->GetParentObject())
|
||||
, mController(aController)
|
||||
, mAborted(aAborted)
|
||||
{}
|
||||
|
||||
AbortSignal::AbortSignal(bool aAborted)
|
||||
: mAborted(aAborted)
|
||||
{}
|
||||
|
||||
JSObject*
|
||||
AbortSignal::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return AbortSignalBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
bool
|
||||
AbortSignal::Aborted() const
|
||||
{
|
||||
return mAborted;
|
||||
}
|
||||
|
||||
void
|
||||
AbortSignal::Abort()
|
||||
{
|
||||
// Re-entrancy guard
|
||||
if (mAborted) {
|
||||
return;
|
||||
}
|
||||
mAborted = true;
|
||||
|
||||
// We might be deleted as a result of aborting a follower, so ensure we
|
||||
// stay alive until all followers have been aborted.
|
||||
RefPtr<AbortSignal> pinThis = this;
|
||||
|
||||
// Let's inform the followers.
|
||||
for (uint32_t i = 0; i < mFollowers.Length(); ++i) {
|
||||
mFollowers[i]->Aborted();
|
||||
}
|
||||
|
||||
EventInit init;
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = false;
|
||||
|
||||
RefPtr<Event> event =
|
||||
Event::Constructor(this, NS_LITERAL_STRING("abort"), init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
bool dummy;
|
||||
DispatchEvent(event, &dummy);
|
||||
}
|
||||
|
||||
void
|
||||
AbortSignal::AddFollower(AbortSignal::Follower* aFollower)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aFollower);
|
||||
if (!mFollowers.Contains(aFollower)) {
|
||||
mFollowers.AppendElement(aFollower);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AbortSignal::RemoveFollower(AbortSignal::Follower* aFollower)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aFollower);
|
||||
mFollowers.RemoveElement(aFollower);
|
||||
}
|
||||
|
||||
// AbortSignal::Follower
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
AbortSignal::Follower::~Follower()
|
||||
{
|
||||
Unfollow();
|
||||
}
|
||||
|
||||
void
|
||||
AbortSignal::Follower::Follow(AbortSignal* aSignal)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aSignal);
|
||||
|
||||
Unfollow();
|
||||
|
||||
mFollowingSignal = aSignal;
|
||||
aSignal->AddFollower(this);
|
||||
}
|
||||
|
||||
void
|
||||
AbortSignal::Follower::Unfollow()
|
||||
{
|
||||
if (mFollowingSignal) {
|
||||
mFollowingSignal->RemoveFollower(this);
|
||||
mFollowingSignal = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
@@ -0,0 +1,76 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_AbortSignal_h
|
||||
#define mozilla_dom_AbortSignal_h
|
||||
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AbortController;
|
||||
class AbortSignal;
|
||||
|
||||
class AbortSignal final : public DOMEventTargetHelper
|
||||
{
|
||||
public:
|
||||
// This class must be implemented by objects who want to follow a AbortSignal.
|
||||
class Follower
|
||||
{
|
||||
public:
|
||||
virtual void Aborted() = 0;
|
||||
|
||||
protected:
|
||||
virtual ~Follower();
|
||||
|
||||
void
|
||||
Follow(AbortSignal* aSignal);
|
||||
|
||||
void
|
||||
Unfollow();
|
||||
|
||||
RefPtr<AbortSignal> mFollowingSignal;
|
||||
};
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AbortSignal, DOMEventTargetHelper)
|
||||
|
||||
AbortSignal(AbortController* aController, bool aAborted);
|
||||
explicit AbortSignal(bool aAborted);
|
||||
|
||||
JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
bool
|
||||
Aborted() const;
|
||||
|
||||
void
|
||||
Abort();
|
||||
|
||||
IMPL_EVENT_HANDLER(abort);
|
||||
|
||||
void
|
||||
AddFollower(Follower* aFollower);
|
||||
|
||||
void
|
||||
RemoveFollower(Follower* aFollower);
|
||||
|
||||
private:
|
||||
~AbortSignal() = default;
|
||||
|
||||
RefPtr<AbortController> mController;
|
||||
|
||||
// Raw pointers. Follower unregisters itself in the DTOR.
|
||||
nsTArray<Follower*> mFollowers;
|
||||
|
||||
bool mAborted;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_AbortSignal_h
|
||||
@@ -4,18 +4,23 @@
|
||||
# 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/.
|
||||
|
||||
EXPORTS.mozilla.dom.battery += [
|
||||
'Constants.h',
|
||||
'Types.h',
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Core", "DOM")
|
||||
|
||||
TEST_DIRS += ['tests']
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'AbortController.h',
|
||||
'AbortSignal.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'BatteryManager.cpp',
|
||||
'AbortController.cpp',
|
||||
'AbortSignal.cpp',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
LOCAL_INCLUDES += [
|
||||
'../workers',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
@@ -0,0 +1,113 @@
|
||||
<script>
|
||||
function ok(a, msg) {
|
||||
parent.postMessage({ type: "check", status: !!a, message: msg }, "*");
|
||||
}
|
||||
|
||||
function is(a, b, msg) {
|
||||
ok(a === b, msg);
|
||||
}
|
||||
|
||||
function testWebIDL() {
|
||||
ok("FetchController" in self, "We have a FetchController prototype");
|
||||
ok("FetchSignal" in self, "We have a FetchSignal prototype");
|
||||
|
||||
var fc = new FetchController();
|
||||
ok(!!fc, "FetchController can be created");
|
||||
ok(fc instanceof FetchController, "FetchController is a FetchController");
|
||||
|
||||
ok(!!fc.signal, "FetchController has a signal");
|
||||
ok(fc.signal instanceof FetchSignal, "fetchSignal is a FetchSignal");
|
||||
is(fc.signal.aborted, false, "By default FetchSignal.aborted is false");
|
||||
next();
|
||||
}
|
||||
|
||||
function testUpdateData() {
|
||||
var fc = new FetchController();
|
||||
|
||||
is(fc.signal.aborted, false, "By default FetchSignal.aborted is false");
|
||||
|
||||
fc.abort();
|
||||
is(fc.signal.aborted, true, "Signal is aborted");
|
||||
|
||||
next();
|
||||
}
|
||||
|
||||
function testAbortEvent() {
|
||||
var fc = new FetchController();
|
||||
fc.signal.onabort = function(e) {
|
||||
is(e.type, "abort", "Abort received");
|
||||
next();
|
||||
}
|
||||
fc.abort();
|
||||
}
|
||||
|
||||
function testAbortedFetch() {
|
||||
var fc = new FetchController();
|
||||
fc.abort();
|
||||
|
||||
fetch('slow.sjs', { signal: fc.signal }).then(() => {
|
||||
ok(false, "Fetch should not return a resolved promise");
|
||||
}, e => {
|
||||
is(e.name, "AbortError", "We have an abort error");
|
||||
}).then(next);
|
||||
}
|
||||
|
||||
function testFetchAndAbort() {
|
||||
var fc = new FetchController();
|
||||
|
||||
var p = fetch('slow.sjs', { signal: fc.signal });
|
||||
fc.abort();
|
||||
|
||||
p.then(() => {
|
||||
ok(false, "Fetch should not return a resolved promise");
|
||||
}, e => {
|
||||
is(e.name, "AbortError", "We have an abort error");
|
||||
}).then(next);
|
||||
}
|
||||
|
||||
function testWorkerAbortedFetch() {
|
||||
var w = new Worker('worker_fetch_controller.js');
|
||||
w.onmessage = function(e) {
|
||||
ok(e.data, "Abort + Fetch works in workers");
|
||||
next();
|
||||
}
|
||||
w.postMessage('testWorkerAbortedFetch');
|
||||
}
|
||||
|
||||
function testWorkerFetchAndAbort() {
|
||||
var w = new Worker('worker_fetch_controller.js');
|
||||
w.onmessage = function(e) {
|
||||
ok(e.data, "Abort + Fetch works in workers");
|
||||
next();
|
||||
}
|
||||
w.postMessage('testWorkerFetchAndAbort');
|
||||
}
|
||||
|
||||
var steps = [
|
||||
// Simple stuff
|
||||
testWebIDL,
|
||||
testUpdateData,
|
||||
|
||||
// Event propagation
|
||||
testAbortEvent,
|
||||
|
||||
// fetch + signaling
|
||||
testAbortedFetch,
|
||||
testFetchAndAbort,
|
||||
testWorkerAbortedFetch,
|
||||
testWorkerFetchAndAbort,
|
||||
];
|
||||
|
||||
function next() {
|
||||
if (!steps.length) {
|
||||
parent.postMessage({ type: "finish" }, "*");
|
||||
return;
|
||||
}
|
||||
|
||||
var step = steps.shift();
|
||||
step();
|
||||
}
|
||||
|
||||
next();
|
||||
|
||||
</script>
|
||||
@@ -0,0 +1,6 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
file_abort_controller.html
|
||||
worker_fetch_controller.js
|
||||
|
||||
[test_abort_controller.html]
|
||||
@@ -4,4 +4,5 @@
|
||||
# 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/.
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
MOCHITEST_MANIFESTS += ['mochitest.ini']
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test FetchController</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.fetchController.enabled", true ]]}, () => {
|
||||
let ifr = document.createElement('iframe');
|
||||
ifr.src = "file_fetch_controller.html";
|
||||
document.body.appendChild(ifr);
|
||||
|
||||
onmessage = function(e) {
|
||||
if (e.data.type == "finish") {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.data.type == "check") {
|
||||
ok(e.data.status, e.data.message);
|
||||
return;
|
||||
}
|
||||
|
||||
ok(false, "Something when wrong.");
|
||||
}
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
function testWorkerAbortedFetch() {
|
||||
var fc = new AbortController();
|
||||
fc.abort();
|
||||
|
||||
fetch('slow.sjs', { signal: fc.signal }).then(() => {
|
||||
postMessage(false);
|
||||
}, e => {
|
||||
postMessage(e.name == "AbortError");
|
||||
});
|
||||
}
|
||||
|
||||
function testWorkerFetchAndAbort() {
|
||||
var fc = new AbortController();
|
||||
|
||||
var p = fetch('slow.sjs', { signal: fc.signal });
|
||||
fc.abort();
|
||||
|
||||
p.then(() => {
|
||||
postMessage(false);
|
||||
}, e => {
|
||||
postMessage(e.name == "AbortError");
|
||||
});
|
||||
}
|
||||
|
||||
onmessage = function(e) {
|
||||
self[e.data]();
|
||||
}
|
||||
@@ -38,8 +38,6 @@ struct AnimationPerformanceWarning
|
||||
std::initializer_list<int32_t> aParams)
|
||||
: mType(aType)
|
||||
{
|
||||
// FIXME: Once std::initializer_list::size() become a constexpr function,
|
||||
// we should use static_assert here.
|
||||
MOZ_ASSERT(aParams.size() <= kMaxParamsForLocalization,
|
||||
"The length of parameters should be less than "
|
||||
"kMaxParamsForLocalization");
|
||||
@@ -49,11 +47,11 @@ struct AnimationPerformanceWarning
|
||||
// Maximum number of parameters passed to
|
||||
// nsContentUtils::FormatLocalizedString to localize warning messages.
|
||||
//
|
||||
// NOTE: This constexpr can't be forward declared, so if you want to use
|
||||
// NOTE: This can't be forward declared, so if you want to use
|
||||
// this variable, please include this header file directly.
|
||||
// This value is the same as the limit of nsStringBundle::FormatString.
|
||||
// See the implementation of nsStringBundle::FormatString.
|
||||
static constexpr uint8_t kMaxParamsForLocalization = 10;
|
||||
static const uint8_t kMaxParamsForLocalization = 10;
|
||||
|
||||
// Indicates why this property could not be animated on the compositor.
|
||||
Type mType;
|
||||
|
||||
@@ -75,11 +75,6 @@ const gMozillaSpecificProperties = {
|
||||
from: "ignore",
|
||||
to: "stretch-to-fit"
|
||||
},
|
||||
"-moz-tab-size": {
|
||||
// https://drafts.csswg.org/css-text-3/#propdef-tab-size
|
||||
from: "1",
|
||||
to: "5"
|
||||
},
|
||||
"-moz-text-size-adjust": {
|
||||
// https://drafts.csswg.org/css-size-adjust/#propdef-text-size-adjust
|
||||
from: "none",
|
||||
|
||||
@@ -166,8 +166,11 @@ NS_INTERFACE_MAP_END
|
||||
/* static */ bool
|
||||
CustomElementRegistry::IsCustomElementEnabled(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
return false;
|
||||
/*
|
||||
return Preferences::GetBool("dom.webcomponents.customelements.enabled") ||
|
||||
Preferences::GetBool("dom.webcomponents.enabled");
|
||||
*/
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<CustomElementRegistry>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#define mozilla_dom_ElementInlines_h
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "ImportManager.h"
|
||||
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/EventListenerManager.h"
|
||||
#include "HTMLLinkElement.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
@@ -18,7 +19,6 @@
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -156,7 +156,7 @@ ImportLoader::Updater::UpdateMainReferrer(uint32_t aNewIdx)
|
||||
// Our nearest predecessor has changed. So let's add the ScriptLoader to the
|
||||
// new one if there is any. And remove it from the old one.
|
||||
RefPtr<ImportManager> manager = mLoader->Manager();
|
||||
nsScriptLoader* loader = mLoader->mDocument->ScriptLoader();
|
||||
ScriptLoader* loader = mLoader->mDocument->ScriptLoader();
|
||||
ImportLoader*& pred = mLoader->mBlockingPredecessor;
|
||||
ImportLoader* newPred = manager->GetNearestPredecessor(newMainReferrer);
|
||||
if (pred) {
|
||||
@@ -339,7 +339,7 @@ ImportLoader::DispatchEventIfFinished(nsINode* aNode)
|
||||
}
|
||||
|
||||
void
|
||||
ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader)
|
||||
ImportLoader::AddBlockedScriptLoader(ScriptLoader* aScriptLoader)
|
||||
{
|
||||
if (mBlockedScriptLoaders.Contains(aScriptLoader)) {
|
||||
return;
|
||||
@@ -352,7 +352,7 @@ ImportLoader::AddBlockedScriptLoader(nsScriptLoader* aScriptLoader)
|
||||
}
|
||||
|
||||
bool
|
||||
ImportLoader::RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader)
|
||||
ImportLoader::RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader)
|
||||
{
|
||||
aScriptLoader->RemoveParserBlockingScriptExecutionBlocker();
|
||||
return mBlockedScriptLoaders.RemoveElement(aScriptLoader);
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIWeakReferenceUtils.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsURIHashKey.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
|
||||
class nsIDocument;
|
||||
class nsIPrincipal;
|
||||
@@ -184,8 +184,8 @@ public:
|
||||
// and wait for that to run its scripts. We keep track of all the
|
||||
// ScriptRunners that are waiting for this import. NOTE: updating
|
||||
// the main referrer might change this list.
|
||||
void AddBlockedScriptLoader(nsScriptLoader* aScriptLoader);
|
||||
bool RemoveBlockedScriptLoader(nsScriptLoader* aScriptLoader);
|
||||
void AddBlockedScriptLoader(ScriptLoader* aScriptLoader);
|
||||
bool RemoveBlockedScriptLoader(ScriptLoader* aScriptLoader);
|
||||
void SetBlockingPredecessor(ImportLoader* aLoader);
|
||||
|
||||
private:
|
||||
@@ -230,7 +230,7 @@ private:
|
||||
|
||||
// List of pending ScriptLoaders that are waiting for this import
|
||||
// to finish.
|
||||
nsTArray<RefPtr<nsScriptLoader>> mBlockedScriptLoaders;
|
||||
nsTArray<RefPtr<ScriptLoader>> mBlockedScriptLoaders;
|
||||
|
||||
// There is always exactly one referrer link that is flagged as
|
||||
// the main referrer the primary link. This is the one that is
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
#include "mozilla/Likely.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/dom/LocationBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
+1
-235
@@ -30,7 +30,6 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "BatteryManager.h"
|
||||
#ifdef MOZ_GAMEPAD
|
||||
#include "mozilla/dom/GamepadServiceTest.h"
|
||||
#endif
|
||||
@@ -99,11 +98,6 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
static bool sVibratorEnabled = false;
|
||||
static uint32_t sMaxVibrateMS = 0;
|
||||
static uint32_t sMaxVibrateListLen = 0;
|
||||
static const char* kVibrationPermissionType = "vibration";
|
||||
|
||||
static void
|
||||
AddPermission(nsIPrincipal* aPrincipal, const char* aType, uint32_t aPermission,
|
||||
uint32_t aExpireType, int64_t aExpireTime)
|
||||
@@ -154,12 +148,7 @@ GetPermission(nsIPrincipal* aPrincipal, const char* aType)
|
||||
void
|
||||
Navigator::Init()
|
||||
{
|
||||
Preferences::AddBoolVarCache(&sVibratorEnabled,
|
||||
"dom.vibrator.enabled", true);
|
||||
Preferences::AddUintVarCache(&sMaxVibrateMS,
|
||||
"dom.vibrator.max_vibrate_ms", 10000);
|
||||
Preferences::AddUintVarCache(&sMaxVibrateListLen,
|
||||
"dom.vibrator.max_vibrate_list_len", 128);
|
||||
// Add any Preferences::Add*VarCache(&sPref, "pref", default) here if needed.
|
||||
}
|
||||
|
||||
Navigator::Navigator(nsPIDOMWindowInner* aWindow)
|
||||
@@ -197,8 +186,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
|
||||
@@ -249,13 +236,6 @@ Navigator::Invalidate()
|
||||
mNotification = nullptr;
|
||||
}
|
||||
|
||||
if (mBatteryManager) {
|
||||
mBatteryManager->Shutdown();
|
||||
mBatteryManager = nullptr;
|
||||
}
|
||||
|
||||
mBatteryPromise = nullptr;
|
||||
|
||||
if (mPowerManager) {
|
||||
mPowerManager->Shutdown();
|
||||
mPowerManager = nullptr;
|
||||
@@ -716,82 +696,6 @@ Navigator::RefreshMIMEArray()
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class VibrateWindowListener : public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
VibrateWindowListener(nsPIDOMWindowInner* aWindow, nsIDocument* aDocument)
|
||||
{
|
||||
mWindow = do_GetWeakReference(aWindow);
|
||||
mDocument = do_GetWeakReference(aDocument);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
|
||||
aDocument->AddSystemEventListener(visibilitychange,
|
||||
this, /* listener */
|
||||
true, /* use capture */
|
||||
false /* wants untrusted */);
|
||||
}
|
||||
|
||||
void RemoveListener();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
private:
|
||||
virtual ~VibrateWindowListener()
|
||||
{
|
||||
}
|
||||
|
||||
nsWeakPtr mWindow;
|
||||
nsWeakPtr mDocument;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(VibrateWindowListener, nsIDOMEventListener)
|
||||
|
||||
StaticRefPtr<VibrateWindowListener> gVibrateWindowListener;
|
||||
|
||||
static bool
|
||||
MayVibrate(nsIDocument* doc) {
|
||||
// Hidden documents cannot start or stop a vibration.
|
||||
return (doc && !doc->Hidden());
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
VibrateWindowListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDocument> doc =
|
||||
do_QueryInterface(aEvent->InternalDOMEvent()->GetTarget());
|
||||
|
||||
if (!MayVibrate(doc)) {
|
||||
// It's important that we call CancelVibrate(), not Vibrate() with an
|
||||
// empty list, because Vibrate() will fail if we're no longer focused, but
|
||||
// CancelVibrate() will succeed, so long as nobody else has started a new
|
||||
// vibration pattern.
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryReferent(mWindow);
|
||||
hal::CancelVibrate(window);
|
||||
RemoveListener();
|
||||
gVibrateWindowListener = nullptr;
|
||||
// Careful: The line above might have deleted |this|!
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
VibrateWindowListener::RemoveListener()
|
||||
{
|
||||
nsCOMPtr<EventTarget> target = do_QueryReferent(mDocument);
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
NS_NAMED_LITERAL_STRING(visibilitychange, "visibilitychange");
|
||||
target->RemoveSystemEventListener(visibilitychange, this,
|
||||
true /* use capture */);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void
|
||||
Navigator::AddIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
||||
{
|
||||
@@ -820,111 +724,6 @@ Navigator::RemoveIdleObserver(MozIdleObserver& aIdleObserver, ErrorResult& aRv)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Navigator::SetVibrationPermission(bool aPermitted, bool aPersistent)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsTArray<uint32_t> pattern;
|
||||
pattern.SwapElements(mRequestedVibrationPattern);
|
||||
|
||||
if (!mWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
||||
|
||||
if (!MayVibrate(doc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPermitted) {
|
||||
// Add a listener to cancel the vibration if the document becomes hidden,
|
||||
// and remove the old visibility listener, if there was one.
|
||||
if (!gVibrateWindowListener) {
|
||||
// If gVibrateWindowListener is null, this is the first time we've vibrated,
|
||||
// and we need to register a listener to clear gVibrateWindowListener on
|
||||
// shutdown.
|
||||
ClearOnShutdown(&gVibrateWindowListener);
|
||||
} else {
|
||||
gVibrateWindowListener->RemoveListener();
|
||||
}
|
||||
gVibrateWindowListener = new VibrateWindowListener(mWindow, doc);
|
||||
hal::Vibrate(pattern, mWindow);
|
||||
}
|
||||
|
||||
if (aPersistent) {
|
||||
AddPermission(doc->NodePrincipal(), kVibrationPermissionType,
|
||||
aPermitted ? nsIPermissionManager::ALLOW_ACTION :
|
||||
nsIPermissionManager::DENY_ACTION,
|
||||
nsIPermissionManager::EXPIRE_SESSION, 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Navigator::Vibrate(uint32_t aDuration)
|
||||
{
|
||||
AutoTArray<uint32_t, 1> pattern;
|
||||
pattern.AppendElement(aDuration);
|
||||
return Vibrate(pattern);
|
||||
}
|
||||
|
||||
bool
|
||||
Navigator::Vibrate(const nsTArray<uint32_t>& aPattern)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!mWindow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mWindow->GetExtantDoc();
|
||||
|
||||
if (!MayVibrate(doc)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTArray<uint32_t> pattern(aPattern);
|
||||
|
||||
if (pattern.Length() > sMaxVibrateListLen) {
|
||||
pattern.SetLength(sMaxVibrateListLen);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pattern.Length(); ++i) {
|
||||
pattern[i] = std::min(sMaxVibrateMS, pattern[i]);
|
||||
}
|
||||
|
||||
// The spec says we check sVibratorEnabled after we've done the sanity
|
||||
// checking on the pattern.
|
||||
if (!sVibratorEnabled) {
|
||||
return true;
|
||||
}
|
||||
|
||||
mRequestedVibrationPattern.SwapElements(pattern);
|
||||
uint32_t permission = GetPermission(mWindow, kVibrationPermissionType);
|
||||
|
||||
if (permission == nsIPermissionManager::ALLOW_ACTION ||
|
||||
mRequestedVibrationPattern.IsEmpty() ||
|
||||
(mRequestedVibrationPattern.Length() == 1 &&
|
||||
mRequestedVibrationPattern[0] == 0)) {
|
||||
// Always allow cancelling vibration and respect session permissions.
|
||||
SetVibrationPermission(true /* permitted */, false /* persistent */);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (!obs || permission == nsIPermissionManager::DENY_ACTION) {
|
||||
// Abort without observer service or on denied session permission.
|
||||
SetVibrationPermission(false /* permitted */, false /* persistent */);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Request user permission.
|
||||
obs->NotifyObservers(ToSupports(this), "Vibration:Request", nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Pointer Events interface
|
||||
//*****************************************************************************
|
||||
@@ -1321,39 +1120,6 @@ Navigator::GetMozNotification(ErrorResult& aRv)
|
||||
return mNotification;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Navigator::nsINavigatorBattery
|
||||
//*****************************************************************************
|
||||
|
||||
Promise*
|
||||
Navigator::GetBattery(ErrorResult& aRv)
|
||||
{
|
||||
if (mBatteryPromise) {
|
||||
return mBatteryPromise;
|
||||
}
|
||||
|
||||
if (!mWindow || !mWindow->GetDocShell()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
|
||||
RefPtr<Promise> batteryPromise = Promise::Create(go, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
mBatteryPromise = batteryPromise;
|
||||
|
||||
if (!mBatteryManager) {
|
||||
mBatteryManager = new battery::BatteryManager(mWindow);
|
||||
mBatteryManager->Init();
|
||||
}
|
||||
|
||||
mBatteryPromise->MaybeResolve(mBatteryManager);
|
||||
|
||||
return mBatteryPromise;
|
||||
}
|
||||
|
||||
PowerManager*
|
||||
Navigator::GetMozPower(ErrorResult& aRv)
|
||||
{
|
||||
|
||||
@@ -51,10 +51,6 @@ namespace dom {
|
||||
|
||||
class Permissions;
|
||||
|
||||
namespace battery {
|
||||
class BatteryManager;
|
||||
} // namespace battery
|
||||
|
||||
class Promise;
|
||||
|
||||
class DesktopNotificationCenter;
|
||||
@@ -136,7 +132,6 @@ public:
|
||||
Permissions* GetPermissions(ErrorResult& aRv);
|
||||
// The XPCOM GetDoNotTrack is ok
|
||||
Geolocation* GetGeolocation(ErrorResult& aRv);
|
||||
Promise* GetBattery(ErrorResult& aRv);
|
||||
|
||||
static void AppName(nsAString& aAppName, bool aUsePrefOverriddenValue);
|
||||
|
||||
@@ -155,9 +150,6 @@ public:
|
||||
// NavigatorBinding::ClearCachedUserAgentValue(this);
|
||||
void ClearUserAgentCache();
|
||||
|
||||
bool Vibrate(uint32_t aDuration);
|
||||
bool Vibrate(const nsTArray<uint32_t>& aDuration);
|
||||
void SetVibrationPermission(bool aPermitted, bool aPersistent);
|
||||
uint32_t MaxTouchPoints();
|
||||
void GetAppCodeName(nsString& aAppCodeName, ErrorResult& aRv)
|
||||
{
|
||||
@@ -269,8 +261,6 @@ private:
|
||||
RefPtr<Permissions> mPermissions;
|
||||
RefPtr<Geolocation> mGeolocation;
|
||||
RefPtr<DesktopNotificationCenter> mNotification;
|
||||
RefPtr<battery::BatteryManager> mBatteryManager;
|
||||
RefPtr<Promise> mBatteryPromise;
|
||||
RefPtr<PowerManager> mPowerManager;
|
||||
RefPtr<network::Connection> mConnection;
|
||||
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/ResizeObserver.h"
|
||||
|
||||
#include "mozilla/dom/DOMRect.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsSVGUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserver)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserver)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(ResizeObserver)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservationMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservationMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
already_AddRefed<ResizeObserver>
|
||||
ResizeObserver::Constructor(const GlobalObject& aGlobal,
|
||||
ResizeObserverCallback& aCb,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||
do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> document = window->GetExtantDoc();
|
||||
|
||||
if (!document) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ResizeObserver> observer = new ResizeObserver(window.forget(), aCb);
|
||||
document->AddResizeObserver(observer);
|
||||
|
||||
return observer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::Observe(Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!aTarget) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ResizeObservation> observation;
|
||||
|
||||
if (!mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
|
||||
observation = new ResizeObservation(this, aTarget);
|
||||
|
||||
mObservationMap.Put(aTarget, observation);
|
||||
mObservationList.insertBack(observation);
|
||||
|
||||
// Per the spec, we need to trigger notification in event loop that
|
||||
// contains ResizeObserver observe call even when resize/reflow does
|
||||
// not happen.
|
||||
aTarget->OwnerDoc()->ScheduleResizeObserversNotification();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::Unobserve(Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!aTarget) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ResizeObservation> observation;
|
||||
|
||||
if (mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
|
||||
mObservationMap.Remove(aTarget);
|
||||
|
||||
MOZ_ASSERT(!mObservationList.isEmpty(),
|
||||
"If ResizeObservation found for an element, observation list "
|
||||
"must be not empty.");
|
||||
|
||||
observation->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::Disconnect()
|
||||
{
|
||||
mObservationMap.Clear();
|
||||
mObservationList.clear();
|
||||
mActiveTargets.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::GatherActiveObservations(uint32_t aDepth)
|
||||
{
|
||||
mActiveTargets.Clear();
|
||||
mHasSkippedTargets = false;
|
||||
|
||||
for (auto observation : mObservationList) {
|
||||
if (observation->IsActive()) {
|
||||
uint32_t targetDepth =
|
||||
nsContentUtils::GetNodeDepth(observation->Target());
|
||||
|
||||
if (targetDepth > aDepth) {
|
||||
mActiveTargets.AppendElement(observation);
|
||||
} else {
|
||||
mHasSkippedTargets = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserver::HasActiveObservations() const
|
||||
{
|
||||
return !mActiveTargets.IsEmpty();
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserver::HasSkippedObservations() const
|
||||
{
|
||||
return mHasSkippedTargets;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ResizeObserver::BroadcastActiveObservations()
|
||||
{
|
||||
uint32_t shallowestTargetDepth = UINT32_MAX;
|
||||
|
||||
if (HasActiveObservations()) {
|
||||
Sequence<OwningNonNull<ResizeObserverEntry>> entries;
|
||||
|
||||
for (auto observation : mActiveTargets) {
|
||||
RefPtr<ResizeObserverEntry> entry =
|
||||
new ResizeObserverEntry(this, observation->Target());
|
||||
|
||||
nsRect rect = observation->GetTargetRect();
|
||||
entry->SetContentRect(rect);
|
||||
|
||||
if (!entries.AppendElement(entry.forget(), fallible)) {
|
||||
// Out of memory.
|
||||
break;
|
||||
}
|
||||
|
||||
// Sync the broadcast size of observation so the next size inspection
|
||||
// will be based on the updated size from last delivered observations.
|
||||
observation->UpdateBroadcastSize(rect);
|
||||
|
||||
uint32_t targetDepth =
|
||||
nsContentUtils::GetNodeDepth(observation->Target());
|
||||
|
||||
if (targetDepth < shallowestTargetDepth) {
|
||||
shallowestTargetDepth = targetDepth;
|
||||
}
|
||||
}
|
||||
|
||||
mCallback->Call(this, entries, *this);
|
||||
mActiveTargets.Clear();
|
||||
mHasSkippedTargets = false;
|
||||
}
|
||||
|
||||
return shallowestTargetDepth;
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserverEntry)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserverEntry)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserverEntry)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObserverEntry,
|
||||
mTarget, mContentRect,
|
||||
mOwner)
|
||||
|
||||
already_AddRefed<ResizeObserverEntry>
|
||||
ResizeObserverEntry::Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<ResizeObserverEntry> observerEntry =
|
||||
new ResizeObserverEntry(aGlobal.GetAsSupports(), aTarget);
|
||||
return observerEntry.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverEntry::SetContentRect(nsRect aRect)
|
||||
{
|
||||
RefPtr<DOMRect> contentRect = new DOMRect(mTarget);
|
||||
nsIFrame* frame = mTarget->GetPrimaryFrame();
|
||||
|
||||
if (frame) {
|
||||
nsMargin padding = frame->GetUsedPadding();
|
||||
|
||||
// Per the spec, we need to include padding in contentRect of
|
||||
// ResizeObserverEntry.
|
||||
aRect.x = padding.left;
|
||||
aRect.y = padding.top;
|
||||
}
|
||||
|
||||
contentRect->SetLayoutRect(aRect);
|
||||
mContentRect = contentRect.forget();
|
||||
}
|
||||
|
||||
ResizeObserverEntry::~ResizeObserverEntry()
|
||||
{
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObservation)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObservation)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObservation)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObservation,
|
||||
mTarget, mOwner)
|
||||
|
||||
already_AddRefed<ResizeObservation>
|
||||
ResizeObservation::Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<ResizeObservation> observation =
|
||||
new ResizeObservation(aGlobal.GetAsSupports(), aTarget);
|
||||
return observation.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObservation::IsActive() const
|
||||
{
|
||||
nsRect rect = GetTargetRect();
|
||||
return (rect.width != mBroadcastWidth || rect.height != mBroadcastHeight);
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObservation::UpdateBroadcastSize(nsRect aRect)
|
||||
{
|
||||
mBroadcastWidth = aRect.width;
|
||||
mBroadcastHeight = aRect.height;
|
||||
}
|
||||
|
||||
nsRect
|
||||
ResizeObservation::GetTargetRect() const
|
||||
{
|
||||
nsRect rect;
|
||||
nsIFrame* frame = mTarget->GetPrimaryFrame();
|
||||
|
||||
if (frame) {
|
||||
if (mTarget->IsSVGElement()) {
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(frame);
|
||||
rect.width = NSFloatPixelsToAppUnits(bbox.width, AppUnitsPerCSSPixel());
|
||||
rect.height = NSFloatPixelsToAppUnits(bbox.height, AppUnitsPerCSSPixel());
|
||||
} else {
|
||||
// Per the spec, non-replaced inline Elements will always have an empty
|
||||
// content rect.
|
||||
if (frame->IsFrameOfType(nsIFrame::eReplaced) ||
|
||||
!frame->IsFrameOfType(nsIFrame::eLineParticipant)) {
|
||||
rect = frame->GetContentRectRelativeToSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
ResizeObservation::~ResizeObservation()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,254 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ResizeObserver_h
|
||||
#define mozilla_dom_ResizeObserver_h
|
||||
|
||||
#include "mozilla/dom/ResizeObserverBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* ResizeObserver interfaces and algorithms are based on
|
||||
* https://wicg.github.io/ResizeObserver/#api
|
||||
*/
|
||||
class ResizeObserver final
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserver)
|
||||
|
||||
ResizeObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
|
||||
ResizeObserverCallback& aCb)
|
||||
: mOwner(aOwner)
|
||||
, mCallback(&aCb)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner window");
|
||||
}
|
||||
|
||||
static already_AddRefed<ResizeObserver>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
ResizeObserverCallback& aCb,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return ResizeObserverBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
void Observe(Element* aTarget, ErrorResult& aRv);
|
||||
|
||||
void Unobserve(Element* aTarget, ErrorResult& aRv);
|
||||
|
||||
void Disconnect();
|
||||
|
||||
/*
|
||||
* Gather all observations which have an observed target with size changed
|
||||
* since last BroadcastActiveObservations() in this ResizeObserver.
|
||||
* An observation will be skipped if the depth of its observed target is less
|
||||
* or equal than aDepth. All gathered observations will be added to
|
||||
* mActiveTargets.
|
||||
*/
|
||||
void GatherActiveObservations(uint32_t aDepth);
|
||||
|
||||
/*
|
||||
* Returns whether this ResizeObserver has any active observations
|
||||
* since last GatherActiveObservations().
|
||||
*/
|
||||
bool HasActiveObservations() const;
|
||||
|
||||
/*
|
||||
* Returns whether this ResizeObserver has any skipped observations
|
||||
* since last GatherActiveObservations().
|
||||
*/
|
||||
bool HasSkippedObservations() const;
|
||||
|
||||
/*
|
||||
* Deliver the callback function in JavaScript for all active observations
|
||||
* and pass the sequence of ResizeObserverEntry so JavaScript can access them.
|
||||
* The broadcast size of observations will be updated and mActiveTargets will
|
||||
* be cleared. It also returns the shallowest depth of elements from active
|
||||
* observations or UINT32_MAX if there is no any active observations.
|
||||
*/
|
||||
uint32_t BroadcastActiveObservations();
|
||||
|
||||
protected:
|
||||
~ResizeObserver()
|
||||
{
|
||||
mObservationList.clear();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mOwner;
|
||||
RefPtr<ResizeObserverCallback> mCallback;
|
||||
nsTArray<RefPtr<ResizeObservation>> mActiveTargets;
|
||||
bool mHasSkippedTargets;
|
||||
|
||||
// Combination of HashTable and LinkedList so we can iterate through
|
||||
// the elements of HashTable in order of insertion time.
|
||||
// Will be nice if we have our own data structure for this in the future.
|
||||
nsRefPtrHashtable<nsPtrHashKey<Element>, ResizeObservation> mObservationMap;
|
||||
LinkedList<ResizeObservation> mObservationList;
|
||||
};
|
||||
|
||||
/**
|
||||
* ResizeObserverEntry is the entry that contains the information for observed
|
||||
* elements. This object is the one that visible to JavaScript in callback
|
||||
* function that is fired by ResizeObserver.
|
||||
*/
|
||||
class ResizeObserverEntry final
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverEntry)
|
||||
|
||||
ResizeObserverEntry(nsISupports* aOwner, Element* aTarget)
|
||||
: mOwner(aOwner)
|
||||
, mTarget(aTarget)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner");
|
||||
MOZ_ASSERT(mTarget, "Need a non-null target element");
|
||||
}
|
||||
|
||||
static already_AddRefed<ResizeObserverEntry>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return ResizeObserverEntryBinding::Wrap(aCx, this,
|
||||
aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
Element* Target() const
|
||||
{
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the DOMRectReadOnly of target's content rect so it can be
|
||||
* accessed from JavaScript in callback function of ResizeObserver.
|
||||
*/
|
||||
DOMRectReadOnly* GetContentRect() const
|
||||
{
|
||||
return mContentRect;
|
||||
}
|
||||
|
||||
void SetContentRect(nsRect aRect);
|
||||
|
||||
protected:
|
||||
~ResizeObserverEntry();
|
||||
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsCOMPtr<Element> mTarget;
|
||||
RefPtr<DOMRectReadOnly> mContentRect;
|
||||
};
|
||||
|
||||
/**
|
||||
* We use ResizeObservation to store and sync the size information of one
|
||||
* observed element so we can decide whether an observation should be fired
|
||||
* or not.
|
||||
*/
|
||||
class ResizeObservation final
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
, public LinkedListElement<ResizeObservation>
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObservation)
|
||||
|
||||
ResizeObservation(nsISupports* aOwner, Element* aTarget)
|
||||
: mOwner(aOwner)
|
||||
, mTarget(aTarget)
|
||||
, mBroadcastWidth(0)
|
||||
, mBroadcastHeight(0)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner");
|
||||
MOZ_ASSERT(mTarget, "Need a non-null target element");
|
||||
}
|
||||
|
||||
static already_AddRefed<ResizeObservation>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return ResizeObservationBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
Element* Target() const
|
||||
{
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
nscoord BroadcastWidth() const
|
||||
{
|
||||
return mBroadcastWidth;
|
||||
}
|
||||
|
||||
nscoord BroadcastHeight() const
|
||||
{
|
||||
return mBroadcastHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the observed target element size differs from current
|
||||
* BroadcastWidth and BroadcastHeight
|
||||
*/
|
||||
bool IsActive() const;
|
||||
|
||||
/*
|
||||
* Update current BroadcastWidth and BroadcastHeight with size from aRect.
|
||||
*/
|
||||
void UpdateBroadcastSize(nsRect aRect);
|
||||
|
||||
/*
|
||||
* Returns the target's rect in the form of nsRect.
|
||||
* If the target is SVG, width and height are determined from bounding box.
|
||||
*/
|
||||
nsRect GetTargetRect() const;
|
||||
|
||||
protected:
|
||||
~ResizeObservation();
|
||||
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsCOMPtr<Element> mTarget;
|
||||
|
||||
// Broadcast width and broadcast height are the latest recorded size
|
||||
// of observed target.
|
||||
nscoord mBroadcastWidth;
|
||||
nscoord mBroadcastHeight;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ResizeObserver_h
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/ResizeObserverController.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ErrorEvent.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::WillRefresh(TimeStamp aTime)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mOwner, "RefreshObserver should have been de-registered on time, but isn't.");
|
||||
if (mOwner) {
|
||||
mOwner->Notify();
|
||||
}
|
||||
}
|
||||
|
||||
nsRefreshDriver*
|
||||
ResizeObserverNotificationHelper::GetRefreshDriver() const
|
||||
{
|
||||
nsIPresShell* presShell = mOwner->GetShell();
|
||||
if (MOZ_UNLIKELY(!presShell)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
if (MOZ_UNLIKELY(!presContext)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return presContext->RefreshDriver();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::Register()
|
||||
{
|
||||
if (mRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefreshDriver* refreshDriver = GetRefreshDriver();
|
||||
if (!refreshDriver) {
|
||||
// We maybe navigating away from this page or currently in an iframe with
|
||||
// display: none. Just abort the Register(), no need to do notification.
|
||||
return;
|
||||
}
|
||||
|
||||
refreshDriver->AddRefreshObserver(this, Flush_Display);
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::Unregister()
|
||||
{
|
||||
if (!mOwner) {
|
||||
// We've outlived our owner, so there's nothing registered anymore.
|
||||
mRegistered = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefreshDriver* refreshDriver = GetRefreshDriver();
|
||||
MOZ_RELEASE_ASSERT(refreshDriver,
|
||||
"We should not leave a dangling reference to the observer around");
|
||||
|
||||
refreshDriver->RemoveRefreshObserver(this, Flush_Display);
|
||||
mRegistered = false;
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::Disconnect()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!mRegistered, "How can we die when registered?");
|
||||
MOZ_RELEASE_ASSERT(!mOwner, "Forgot to clear weak pointer?");
|
||||
}
|
||||
|
||||
ResizeObserverNotificationHelper::~ResizeObserverNotificationHelper()
|
||||
{
|
||||
Unregister();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::Traverse(nsCycleCollectionTraversalCallback& aCb)
|
||||
{
|
||||
ImplCycleCollectionTraverse(aCb, mResizeObservers, "mResizeObservers");
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::Unlink()
|
||||
{
|
||||
mResizeObservers.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::AddResizeObserver(ResizeObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(aObserver, "AddResizeObserver() should never be called with "
|
||||
"a null parameter");
|
||||
mResizeObservers.AppendElement(aObserver);
|
||||
}
|
||||
|
||||
void ResizeObserverController::DetachFromDocument() {
|
||||
mResizeObserverNotificationHelper->Unregister();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::Notify()
|
||||
{
|
||||
if (mResizeObservers.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hold a strong reference to the document, because otherwise calling
|
||||
// all active observers on it might yank it out from under us.
|
||||
RefPtr<nsIDocument> document(mDocument);
|
||||
|
||||
uint32_t shallowestTargetDepth = 0;
|
||||
|
||||
GatherAllActiveObservations(shallowestTargetDepth);
|
||||
|
||||
while (HasAnyActiveObservations()) {
|
||||
DebugOnly<uint32_t> oldShallowestTargetDepth = shallowestTargetDepth;
|
||||
shallowestTargetDepth = BroadcastAllActiveObservations();
|
||||
NS_ASSERTION(oldShallowestTargetDepth < shallowestTargetDepth,
|
||||
"shallowestTargetDepth should be getting strictly deeper");
|
||||
|
||||
// Flush layout, so that any callback functions' style changes / resizes
|
||||
// get a chance to take effect.
|
||||
mDocument->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
// To avoid infinite resize loop, we only gather all active observations
|
||||
// that have the depth of observed target element more than current
|
||||
// shallowestTargetDepth.
|
||||
GatherAllActiveObservations(shallowestTargetDepth);
|
||||
}
|
||||
|
||||
mResizeObserverNotificationHelper->Unregister();
|
||||
|
||||
// Per spec, we deliver an error if the document has any skipped observations.
|
||||
if (HasAnySkippedObservations()) {
|
||||
RootedDictionary<ErrorEventInit> init(RootingCx());
|
||||
|
||||
init.mMessage.AssignLiteral("ResizeObserver loop completed with undelivered"
|
||||
" notifications.");
|
||||
init.mCancelable = true;
|
||||
init.mBubbles = true;
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||
document->GetWindow()->GetCurrentInnerWindow();
|
||||
|
||||
if (window) {
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
|
||||
MOZ_ASSERT(sgo);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(sgo->HandleScriptError(init, &status)))) {
|
||||
status = nsEventStatus_eIgnore;
|
||||
}
|
||||
} else {
|
||||
// We don't fire error events at any global for non-window JS on the main
|
||||
// thread.
|
||||
}
|
||||
|
||||
// We need to deliver pending notifications in next cycle.
|
||||
ScheduleNotification();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::GatherAllActiveObservations(uint32_t aDepth)
|
||||
{
|
||||
for (auto observer : mResizeObservers) {
|
||||
observer->GatherActiveObservations(aDepth);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ResizeObserverController::BroadcastAllActiveObservations()
|
||||
{
|
||||
uint32_t shallowestTargetDepth = UINT32_MAX;
|
||||
|
||||
// Use a copy of the observers as this invokes the callbacks of the observers
|
||||
// which could register/unregister observers at will.
|
||||
nsTArray<RefPtr<ResizeObserver>> tempObservers(mResizeObservers);
|
||||
|
||||
for (auto observer : tempObservers) {
|
||||
|
||||
uint32_t targetDepth = observer->BroadcastActiveObservations();
|
||||
|
||||
if (targetDepth < shallowestTargetDepth) {
|
||||
shallowestTargetDepth = targetDepth;
|
||||
}
|
||||
}
|
||||
|
||||
return shallowestTargetDepth;
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserverController::HasAnyActiveObservations() const
|
||||
{
|
||||
for (auto observer : mResizeObservers) {
|
||||
if (observer->HasActiveObservations()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserverController::HasAnySkippedObservations() const
|
||||
{
|
||||
for (auto observer : mResizeObservers) {
|
||||
if (observer->HasSkippedObservations()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::ScheduleNotification()
|
||||
{
|
||||
mResizeObserverNotificationHelper->Register();
|
||||
}
|
||||
|
||||
nsIPresShell*
|
||||
ResizeObserverController::GetShell() const
|
||||
{
|
||||
return mDocument->GetShell();
|
||||
}
|
||||
|
||||
ResizeObserverController::~ResizeObserverController()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(
|
||||
!mResizeObserverNotificationHelper->IsRegistered(),
|
||||
"Nothing else should keep a reference to our notification helper when we go away");
|
||||
mResizeObserverNotificationHelper->DetachFromOwner();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ResizeObserverController_h
|
||||
#define mozilla_dom_ResizeObserverController_h
|
||||
|
||||
#include "mozilla/dom/ResizeObserver.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ResizeObserverController;
|
||||
|
||||
/*
|
||||
* ResizeObserverNotificationHelper will trigger ResizeObserver notifications
|
||||
* by registering with the Refresh Driver.
|
||||
*/
|
||||
class ResizeObserverNotificationHelper final : public nsARefreshObserver
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(ResizeObserverNotificationHelper, override)
|
||||
|
||||
explicit ResizeObserverNotificationHelper(ResizeObserverController* aOwner)
|
||||
: mOwner(aOwner)
|
||||
, mRegistered(false)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner");
|
||||
}
|
||||
|
||||
void WillRefresh(TimeStamp aTime) override;
|
||||
|
||||
nsRefreshDriver* GetRefreshDriver() const;
|
||||
|
||||
void Register();
|
||||
|
||||
void Unregister();
|
||||
|
||||
void Disconnect();
|
||||
|
||||
bool IsRegistered() const { return mRegistered; }
|
||||
|
||||
void DetachFromOwner() { mOwner = nullptr; }
|
||||
|
||||
protected:
|
||||
virtual ~ResizeObserverNotificationHelper();
|
||||
|
||||
ResizeObserverController* mOwner;
|
||||
bool mRegistered;
|
||||
};
|
||||
|
||||
/*
|
||||
* ResizeObserverController contains the list of ResizeObservers and controls
|
||||
* the flow of notification.
|
||||
*/
|
||||
class ResizeObserverController final
|
||||
{
|
||||
public:
|
||||
explicit ResizeObserverController(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
, mIsNotificationActive(false)
|
||||
{
|
||||
MOZ_ASSERT(mDocument, "Need a non-null document");
|
||||
mResizeObserverNotificationHelper =
|
||||
new ResizeObserverNotificationHelper(this);
|
||||
}
|
||||
|
||||
// Methods for supporting cycle-collection
|
||||
void Traverse(nsCycleCollectionTraversalCallback& aCb);
|
||||
void Unlink();
|
||||
|
||||
void DetachFromDocument();
|
||||
void AddResizeObserver(ResizeObserver* aObserver);
|
||||
|
||||
/*
|
||||
* Schedule the notification via ResizeObserverNotificationHelper refresh
|
||||
* observer.
|
||||
*/
|
||||
void ScheduleNotification();
|
||||
|
||||
/*
|
||||
* Notify all ResizeObservers by gathering and broadcasting all active
|
||||
* observations.
|
||||
*/
|
||||
void Notify();
|
||||
|
||||
nsIPresShell* GetShell() const;
|
||||
|
||||
~ResizeObserverController();
|
||||
|
||||
private:
|
||||
/*
|
||||
* Calls GatherActiveObservations(aDepth) for all ResizeObservers in this
|
||||
* controller. All observations in each ResizeObserver with element's depth
|
||||
* more than aDepth will be gathered.
|
||||
*/
|
||||
void GatherAllActiveObservations(uint32_t aDepth);
|
||||
|
||||
/*
|
||||
* Calls BroadcastActiveObservations() for all ResizeObservers in this
|
||||
* controller. It also returns the shallowest depth of observed target
|
||||
* elements from all ResizeObserver or UINT32_MAX if there is no any
|
||||
* active obsevations at all.
|
||||
*/
|
||||
uint32_t BroadcastAllActiveObservations();
|
||||
|
||||
/*
|
||||
* Returns whether there is any ResizeObserver that has active observations.
|
||||
*/
|
||||
bool HasAnyActiveObservations() const;
|
||||
|
||||
/*
|
||||
* Returns whether there is any ResizeObserver that has skipped observations.
|
||||
*/
|
||||
bool HasAnySkippedObservations() const;
|
||||
|
||||
protected:
|
||||
// Raw pointer is OK because mDocument strongly owns us & hence must outlive
|
||||
// us.
|
||||
nsIDocument* const mDocument;
|
||||
|
||||
RefPtr<ResizeObserverNotificationHelper> mResizeObserverNotificationHelper;
|
||||
nsTArray<RefPtr<ResizeObserver>> mResizeObservers;
|
||||
bool mIsNotificationActive;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ResizeObserverController_h
|
||||
@@ -15,7 +15,7 @@ namespace dom {
|
||||
class WindowNamedPropertiesHandler : public BaseDOMProxyHandler
|
||||
{
|
||||
public:
|
||||
constexpr WindowNamedPropertiesHandler()
|
||||
WindowNamedPropertiesHandler()
|
||||
: BaseDOMProxyHandler(nullptr, /* hasPrototype = */ true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script>
|
||||
|
||||
var frameRoot;
|
||||
|
||||
function boom()
|
||||
{
|
||||
var frameWin = f.contentWindow;
|
||||
frameRoot = frameWin.document.documentElement;
|
||||
frameWin.location.replace("data:text/html;charset=UTF-8,<body onload='parent.g();'>2");
|
||||
}
|
||||
|
||||
function g()
|
||||
{
|
||||
setTimeout(h, 0);
|
||||
}
|
||||
|
||||
function h()
|
||||
{
|
||||
var newDoc = document.implementation.createDocument('', '', null);
|
||||
newDoc.adoptNode(frameRoot);
|
||||
}
|
||||
|
||||
</script>
|
||||
<body onload="boom();">
|
||||
|
||||
<iframe id="f" src="data:text/html;charset=UTF-8,<marquee>1"></iframe>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
var marquee = document.getElementById("marquee");
|
||||
var span = document.getElementById("span");
|
||||
marquee.appendChild(span);
|
||||
marquee.removeChild(span);
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="setTimeout(boom, 30);">
|
||||
|
||||
<marquee id="marquee" />
|
||||
|
||||
<span id="span"><div>Foo</div><textarea/></span>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,28 +0,0 @@
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var i = 0;
|
||||
function mmf()
|
||||
{
|
||||
if (++i == 2) {
|
||||
document.body.innerHTML = "<marquee>";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
document.documentElement.offsetHeight;
|
||||
for (var j = 0; j < 2; ++j) {
|
||||
var iframe = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
|
||||
iframe.addEventListener("load", mmf, false);
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="setTimeout(init, 0);"></body>
|
||||
</html>
|
||||
+4
-8
@@ -26,7 +26,6 @@ XPIDL_SOURCES += [
|
||||
'nsIObjectLoadingContent.idl',
|
||||
'nsIRemoteWindowContext.idl',
|
||||
'nsIScriptChannel.idl',
|
||||
'nsIScriptLoaderObserver.idl',
|
||||
'nsISelection.idl',
|
||||
'nsISelectionController.idl',
|
||||
'nsISelectionDisplay.idl',
|
||||
@@ -96,7 +95,6 @@ EXPORTS += [
|
||||
'nsINode.h',
|
||||
'nsINodeList.h',
|
||||
'nsIScriptContext.h',
|
||||
'nsIScriptElement.h',
|
||||
'nsIScriptGlobalObject.h',
|
||||
'nsIScriptNameSpaceManager.h',
|
||||
'nsIScriptObjectPrincipal.h',
|
||||
@@ -117,7 +115,6 @@ EXPORTS += [
|
||||
'nsRange.h',
|
||||
'nsReferencedElement.h',
|
||||
'nsSandboxFlags.h',
|
||||
'nsScriptLoader.h',
|
||||
'nsStructuredCloneContainer.h',
|
||||
'nsStubAnimationObserver.h',
|
||||
'nsStubDocumentObserver.h',
|
||||
@@ -205,10 +202,11 @@ EXPORTS.mozilla.dom += [
|
||||
'PartialSHistory.h',
|
||||
'Pose.h',
|
||||
'ProcessGlobal.h',
|
||||
'ResizeObserver.h',
|
||||
'ResizeObserverController.h',
|
||||
'ResponsiveImageSelector.h',
|
||||
'SameProcessMessageQueue.h',
|
||||
'ScreenOrientation.h',
|
||||
'ScriptSettings.h',
|
||||
'ShadowRoot.h',
|
||||
'SimpleTreeIterator.h',
|
||||
'StructuredCloneHolder.h',
|
||||
@@ -328,8 +326,6 @@ SOURCES += [
|
||||
'nsRange.cpp',
|
||||
'nsReferencedElement.cpp',
|
||||
'nsScreen.cpp',
|
||||
'nsScriptElement.cpp',
|
||||
'nsScriptLoader.cpp',
|
||||
'nsScriptNameSpaceManager.cpp',
|
||||
'nsStructuredCloneContainer.cpp',
|
||||
'nsStubAnimationObserver.cpp',
|
||||
@@ -353,10 +349,11 @@ SOURCES += [
|
||||
'Pose.cpp',
|
||||
'PostMessageEvent.cpp',
|
||||
'ProcessGlobal.cpp',
|
||||
'ResizeObserver.cpp',
|
||||
'ResizeObserverController.cpp',
|
||||
'ResponsiveImageSelector.cpp',
|
||||
'SameProcessMessageQueue.cpp',
|
||||
'ScreenOrientation.cpp',
|
||||
'ScriptSettings.cpp',
|
||||
'ShadowRoot.cpp',
|
||||
'StructuredCloneHolder.cpp',
|
||||
'StyleSheetList.cpp',
|
||||
@@ -423,7 +420,6 @@ EXTRA_JS_MODULES += [
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../battery',
|
||||
'../events',
|
||||
'../media',
|
||||
'../network',
|
||||
|
||||
@@ -268,7 +268,7 @@ public:
|
||||
// EnumTable can be initialized either with an int16_t value
|
||||
// or a value of an enumeration type that can fit within an int16_t.
|
||||
|
||||
constexpr EnumTable(const char* aTag, int16_t aValue)
|
||||
EnumTable(const char* aTag, int16_t aValue)
|
||||
: tag(aTag)
|
||||
, value(aValue)
|
||||
{
|
||||
@@ -276,7 +276,7 @@ public:
|
||||
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<std::is_enum<T>::value>::type>
|
||||
constexpr EnumTable(const char* aTag, T aValue)
|
||||
EnumTable(const char* aTag, T aValue)
|
||||
: tag(aTag)
|
||||
, value(static_cast<int16_t>(aValue))
|
||||
{
|
||||
|
||||
@@ -29,9 +29,8 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "ScriptSettings.h"
|
||||
|
||||
using mozilla::Unused; // <snicker>
|
||||
using mozilla::Unused;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
*/
|
||||
|
||||
#include "nsContentSink.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "mozilla/css/Loader.h"
|
||||
@@ -49,6 +48,7 @@
|
||||
#include "nsHTMLDNSPrefetch.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "nsParserConstants.h"
|
||||
#include "nsSandboxFlags.h"
|
||||
|
||||
@@ -789,13 +789,14 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
|
||||
// If this is a fragment parser, we don't want to observe.
|
||||
// We don't support CORS for processing instructions
|
||||
bool isAlternate;
|
||||
bool isExplicitlyEnabled;
|
||||
rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
|
||||
CORS_NONE, mDocument->GetReferrerPolicy(),
|
||||
integrity, mRunsToCompletion ? nullptr : this,
|
||||
&isAlternate);
|
||||
&isAlternate, &isExplicitlyEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!isAlternate && !mRunsToCompletion) {
|
||||
if ((!isAlternate || isExplicitlyEnabled) && !mRunsToCompletion) {
|
||||
++mPendingSheetCount;
|
||||
mScriptLoader->AddParserBlockingScriptExecutionBlocker();
|
||||
}
|
||||
|
||||
@@ -36,13 +36,16 @@ class nsIAtom;
|
||||
class nsIChannel;
|
||||
class nsIContent;
|
||||
class nsNodeInfoManager;
|
||||
class nsScriptLoader;
|
||||
class nsIApplicationCache;
|
||||
|
||||
namespace mozilla {
|
||||
namespace css {
|
||||
class Loader;
|
||||
} // namespace css
|
||||
|
||||
namespace dom {
|
||||
class ScriptLoader;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -273,7 +276,7 @@ protected:
|
||||
nsCOMPtr<nsIDocShell> mDocShell;
|
||||
RefPtr<mozilla::css::Loader> mCSSLoader;
|
||||
RefPtr<nsNodeInfoManager> mNodeInfoManager;
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
|
||||
|
||||
// back off timer notification after count
|
||||
int32_t mBackoffCount;
|
||||
|
||||
@@ -5105,6 +5105,14 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
|
||||
fileName.SetIsVoid(true); // No actionable download attribute was found.
|
||||
}
|
||||
|
||||
// Sanitize fileNames containing control characters by replacing them with
|
||||
// underscores.
|
||||
if (!fileName.IsVoid()) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
fileName.ReplaceChar(char16_t(i), '_');
|
||||
}
|
||||
}
|
||||
|
||||
handler->OnLinkClick(aContent, aLinkURI,
|
||||
fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
|
||||
fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
|
||||
@@ -9835,4 +9843,18 @@ nsContentUtils::IsLocalRefURL(const nsString& aString)
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
nsContentUtils::GetNodeDepth(nsINode* aNode)
|
||||
{
|
||||
uint32_t depth = 1;
|
||||
|
||||
MOZ_ASSERT(aNode, "Node shouldn't be null");
|
||||
|
||||
while ((aNode = aNode->GetParentNode())) {
|
||||
++depth;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
@@ -2745,6 +2745,14 @@ public:
|
||||
static bool
|
||||
IsLocalRefURL(const nsString& aString);
|
||||
|
||||
/**
|
||||
* Returns the length of the parent-traversal path (in terms of the number of
|
||||
* nodes) to an unparented/root node from aNode. An unparented/root node is
|
||||
* considered to have a depth of 1, its children have a depth of 2, etc.
|
||||
* aNode is expected to be non-null.
|
||||
*/
|
||||
static uint32_t GetNodeDepth(nsINode* aNode);
|
||||
|
||||
private:
|
||||
static bool InitializeEventTable();
|
||||
|
||||
|
||||
@@ -3577,7 +3577,8 @@ nsDOMWindowUtils::IsNodeDisabledForEvents(nsIDOMNode* aNode, bool* aRetVal)
|
||||
while (node) {
|
||||
if (node->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
|
||||
nsCOMPtr<nsIFormControl> fc = do_QueryInterface(node);
|
||||
if (fc && fc->IsDisabledForEvents(eVoidEvent)) {
|
||||
WidgetEvent event(true, eVoidEvent);
|
||||
if (fc && fc->IsDisabledForEvents(&event)) {
|
||||
*aRetVal = true;
|
||||
break;
|
||||
}
|
||||
|
||||
+56
-10
@@ -1727,6 +1727,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
cb.NoteXPCOMChild(mql);
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp->mResizeObserverController) {
|
||||
tmp->mResizeObserverController->Traverse(cb);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
|
||||
@@ -1827,11 +1831,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
||||
l != &tmp->mDOMMediaQueryLists; ) {
|
||||
PRCList *next = PR_NEXT_LINK(l);
|
||||
MediaQueryList *mql = static_cast<MediaQueryList*>(l);
|
||||
mql->RemoveAllListeners();
|
||||
mql->Disconnect();
|
||||
l = next;
|
||||
}
|
||||
|
||||
tmp->mInUnlinkOrDeletion = false;
|
||||
|
||||
if (tmp->mResizeObserverController) {
|
||||
tmp->mResizeObserverController->Unlink();
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
nsresult
|
||||
@@ -1880,7 +1888,7 @@ nsDocument::Init()
|
||||
mScopeObject = do_GetWeakReference(global);
|
||||
MOZ_ASSERT(mScopeObject);
|
||||
|
||||
mScriptLoader = new nsScriptLoader(this);
|
||||
mScriptLoader = new dom::ScriptLoader(this);
|
||||
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
@@ -3681,6 +3689,12 @@ nsDocument::DeleteShell()
|
||||
// objects for @font-face rules that came from the style set.
|
||||
RebuildUserFontSet();
|
||||
|
||||
if (mResizeObserverController) {
|
||||
// If the shell is going away, we need to remove any links to this document
|
||||
// from the observer.
|
||||
mResizeObserverController->DetachFromDocument();
|
||||
}
|
||||
|
||||
nsIPresShell* oldShell = mPresShell;
|
||||
mPresShell = nullptr;
|
||||
UpdateFrameRequestCallbackSchedulingState(oldShell);
|
||||
@@ -4685,7 +4699,7 @@ nsDocument::GetWindowInternal() const
|
||||
return win;
|
||||
}
|
||||
|
||||
nsScriptLoader*
|
||||
ScriptLoader*
|
||||
nsDocument::ScriptLoader()
|
||||
{
|
||||
return mScriptLoader;
|
||||
@@ -5709,9 +5723,9 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
|
||||
{
|
||||
JS::Rooted<JSObject*> obj(aCx, aObject);
|
||||
|
||||
if (Preferences::GetBool("dom.webcomponents.enabled")) {
|
||||
return true;
|
||||
}
|
||||
//if (Preferences::GetBool("dom.webcomponents.enabled")) {
|
||||
// return true;
|
||||
//}
|
||||
|
||||
// Check for the webcomponents permission. See Bug 1181555.
|
||||
JSAutoCompartment ac(aCx, obj);
|
||||
@@ -5725,9 +5739,9 @@ nsDocument::IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject)
|
||||
bool
|
||||
nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
|
||||
{
|
||||
if (Preferences::GetBool("dom.webcomponents.enabled")) {
|
||||
return true;
|
||||
}
|
||||
//if (Preferences::GetBool("dom.webcomponents.enabled")) {
|
||||
// return true;
|
||||
//}
|
||||
|
||||
nsIDocument* doc = aNodeInfo->GetDocument();
|
||||
// Use GetScopeObject() here so that data documents work the same way as the
|
||||
@@ -5740,6 +5754,7 @@ nsDocument::IsWebComponentsEnabled(dom::NodeInfo* aNodeInfo)
|
||||
bool
|
||||
nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
|
||||
{
|
||||
/*
|
||||
if (aWindow) {
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPermissionManager> permMgr =
|
||||
@@ -5753,7 +5768,7 @@ nsDocument::IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow)
|
||||
|
||||
return perm == nsIPermissionManager::ALLOW_ACTION;
|
||||
}
|
||||
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -12104,6 +12119,24 @@ nsDocument::QuerySelectorAll(const nsAString& aSelector, nsIDOMNodeList **aRetur
|
||||
return nsINode::QuerySelectorAll(aSelector, aReturn);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::AddResizeObserver(ResizeObserver* aResizeObserver)
|
||||
{
|
||||
if (!mResizeObserverController) {
|
||||
mResizeObserverController = MakeUnique<ResizeObserverController>(this);
|
||||
}
|
||||
|
||||
mResizeObserverController->AddResizeObserver(aResizeObserver);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::ScheduleResizeObserversNotification() const
|
||||
{
|
||||
if (mResizeObserverController) {
|
||||
mResizeObserverController->ScheduleNotification();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDocument>
|
||||
nsIDocument::Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& rv)
|
||||
@@ -12744,3 +12777,16 @@ nsIDocument::GetSelection(ErrorResult& aRv)
|
||||
|
||||
return nsGlobalWindow::Cast(window)->GetSelection(aRv);
|
||||
}
|
||||
|
||||
bool
|
||||
nsIDocument::ModuleScriptsEnabled()
|
||||
{
|
||||
static bool sEnabledForContent = false;
|
||||
static bool sCachedPref = false;
|
||||
if (!sCachedPref) {
|
||||
sCachedPref = true;
|
||||
Preferences::AddBoolVarCache(&sEnabledForContent, "dom.moduleScripts.enabled", false);
|
||||
}
|
||||
|
||||
return nsContentUtils::IsChromeDoc(this) || sEnabledForContent;
|
||||
}
|
||||
+11
-3
@@ -31,7 +31,6 @@
|
||||
#include "nsJSThingHashtable.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsIRadioGroupContainer.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "nsIRequest.h"
|
||||
@@ -60,6 +59,8 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/PendingAnimationTracker.h"
|
||||
#include "mozilla/dom/DOMImplementation.h"
|
||||
#include "mozilla/dom/ResizeObserverController.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
@@ -674,7 +675,7 @@ public:
|
||||
/**
|
||||
* Get the script loader for this document
|
||||
*/
|
||||
virtual nsScriptLoader* ScriptLoader() override;
|
||||
virtual mozilla::dom::ScriptLoader* ScriptLoader() override;
|
||||
|
||||
/**
|
||||
* Add/Remove an element to the document's id and name hashes
|
||||
@@ -1206,6 +1207,10 @@ public:
|
||||
|
||||
virtual void UnblockDOMContentLoaded() override;
|
||||
|
||||
void AddResizeObserver(mozilla::dom::ResizeObserver* aResizeObserver) override;
|
||||
|
||||
void ScheduleResizeObserversNotification() const override;
|
||||
|
||||
protected:
|
||||
friend class nsNodeUtils;
|
||||
friend class nsDocumentOnStack;
|
||||
@@ -1342,6 +1347,9 @@ protected:
|
||||
|
||||
nsTArray<nsIObserver*> mCharSetObservers;
|
||||
|
||||
mozilla::UniquePtr<mozilla::dom::ResizeObserverController>
|
||||
mResizeObserverController;
|
||||
|
||||
PLDHashTable *mSubDocuments;
|
||||
|
||||
// Array of owning references to all children
|
||||
@@ -1417,7 +1425,7 @@ public:
|
||||
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
||||
RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
|
||||
RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
RefPtr<mozilla::dom::ScriptLoader> mScriptLoader;
|
||||
nsDocHeaderData* mHeaderData;
|
||||
/* mIdentifierMap works as follows for IDs:
|
||||
* 1) Attribute changes affect the table immediately (removing and adding
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsIScriptError.h"
|
||||
@@ -38,6 +37,7 @@
|
||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||
#include "mozilla/dom/ProcessGlobal.h"
|
||||
#include "mozilla/dom/SameProcessMessageQueue.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
@@ -1786,9 +1786,9 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
|
||||
if (NS_FAILED(NS_ReadInputStreamToString(input, buffer, avail))) {
|
||||
return;
|
||||
}
|
||||
nsScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
|
||||
EmptyString(), nullptr,
|
||||
dataStringBuf, dataStringLength);
|
||||
ScriptLoader::ConvertToUTF16(channel, (uint8_t*)buffer.get(), avail,
|
||||
EmptyString(), nullptr,
|
||||
dataStringBuf, dataStringLength);
|
||||
}
|
||||
|
||||
JS::SourceBufferHolder srcBuf(dataStringBuf, dataStringLength,
|
||||
|
||||
@@ -580,7 +580,6 @@ GK_ATOM(marginTop, "margin-top")
|
||||
GK_ATOM(marginheight, "marginheight")
|
||||
GK_ATOM(marginwidth, "marginwidth")
|
||||
GK_ATOM(mark, "mark")
|
||||
GK_ATOM(marquee, "marquee")
|
||||
GK_ATOM(match, "match")
|
||||
GK_ATOM(max, "max")
|
||||
GK_ATOM(maxheight, "maxheight")
|
||||
@@ -910,7 +909,9 @@ GK_ATOM(onreadystatechange, "onreadystatechange")
|
||||
GK_ATOM(onreceived, "onreceived")
|
||||
GK_ATOM(onremoteheld, "onremoteheld")
|
||||
GK_ATOM(onremoteresumed, "onremoteresumed")
|
||||
GK_ATOM(onrequestprogress, "onrequestprogress")
|
||||
GK_ATOM(onresourcetimingbufferfull, "onresourcetimingbufferfull")
|
||||
GK_ATOM(onresponseprogress, "onresponseprogress")
|
||||
GK_ATOM(onretrieving, "onretrieving")
|
||||
GK_ATOM(onRequest, "onRequest")
|
||||
GK_ATOM(onrequestmediaplaystatus, "onrequestmediaplaystatus")
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "ScriptSettings.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
@@ -956,7 +956,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(DialogValueHolder)
|
||||
class nsOuterWindowProxy : public js::Wrapper
|
||||
{
|
||||
public:
|
||||
constexpr nsOuterWindowProxy() : js::Wrapper(0) { }
|
||||
nsOuterWindowProxy() : js::Wrapper(0) { }
|
||||
|
||||
virtual bool finalizeInBackground(const JS::Value& priv) const override {
|
||||
return false;
|
||||
@@ -1407,7 +1407,7 @@ nsOuterWindowProxy::singleton;
|
||||
class nsChromeOuterWindowProxy : public nsOuterWindowProxy
|
||||
{
|
||||
public:
|
||||
constexpr nsChromeOuterWindowProxy() : nsOuterWindowProxy() { }
|
||||
nsChromeOuterWindowProxy() : nsOuterWindowProxy() { }
|
||||
|
||||
virtual const char *className(JSContext *cx, JS::Handle<JSObject*> wrapper) const override;
|
||||
|
||||
|
||||
@@ -91,7 +91,6 @@ class nsIVariant;
|
||||
class nsViewManager;
|
||||
class nsPresContext;
|
||||
class nsRange;
|
||||
class nsScriptLoader;
|
||||
class nsSMILAnimationController;
|
||||
class nsTextNode;
|
||||
class nsWindowSizes;
|
||||
@@ -152,6 +151,8 @@ enum class OrientationType : uint32_t;
|
||||
class ProcessingInstruction;
|
||||
class Promise;
|
||||
class Selection;
|
||||
class ScriptLoader;
|
||||
class ResizeObserver;
|
||||
class StyleSheetList;
|
||||
class SVGDocument;
|
||||
class SVGSVGElement;
|
||||
@@ -1290,7 +1291,7 @@ public:
|
||||
/**
|
||||
* Get the script loader for this document
|
||||
*/
|
||||
virtual nsScriptLoader* ScriptLoader() = 0;
|
||||
virtual mozilla::dom::ScriptLoader* ScriptLoader() = 0;
|
||||
|
||||
/**
|
||||
* Add/Remove an element to the document's id and name hashes
|
||||
@@ -2872,6 +2873,12 @@ public:
|
||||
virtual void ScheduleIntersectionObserverNotification() = 0;
|
||||
virtual void NotifyIntersectionObservers() = 0;
|
||||
|
||||
bool ModuleScriptsEnabled();
|
||||
|
||||
virtual void AddResizeObserver(mozilla::dom::ResizeObserver* aResizeObserver) = 0;
|
||||
|
||||
virtual void ScheduleResizeObserversNotification() const = 0;
|
||||
|
||||
protected:
|
||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||
{
|
||||
|
||||
@@ -68,7 +68,7 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
||||
* the image was blocked. This status always refers to the
|
||||
* CURRENT_REQUEST load.
|
||||
*/
|
||||
readonly attribute short imageBlockingStatus;
|
||||
[infallible] readonly attribute short imageBlockingStatus;
|
||||
|
||||
/**
|
||||
* Used to register an image decoder observer. Typically, this will
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
#include "GeometryUtils.h"
|
||||
#include "nsIAnimationObserver.h"
|
||||
#include "nsChildContentList.h"
|
||||
#include "mozilla/dom/NodeBinding.h"
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "mozilla/dom/AccessibleNode.h"
|
||||
@@ -250,6 +251,30 @@ nsINode::GetTextEditorRootContent(nsIEditor** aEditor)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsINode* nsINode::GetRootNode(const GetRootNodeOptions& aOptions)
|
||||
{
|
||||
if (aOptions.mComposed) {
|
||||
if (IsInComposedDoc() && GetComposedDoc()) {
|
||||
return OwnerDoc();
|
||||
}
|
||||
|
||||
nsINode* node = this;
|
||||
ShadowRoot* shadowRootParent = nullptr;
|
||||
while(node) {
|
||||
node = node->SubtreeRoot();
|
||||
shadowRootParent = ShadowRoot::FromNode(node);
|
||||
if (!shadowRootParent) {
|
||||
break;
|
||||
}
|
||||
node = shadowRootParent->GetHost();
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
return SubtreeRoot();
|
||||
}
|
||||
|
||||
nsINode*
|
||||
nsINode::SubtreeRoot() const
|
||||
{
|
||||
|
||||
+6
-4
@@ -83,6 +83,7 @@ template<typename> class Sequence;
|
||||
class Text;
|
||||
class TextOrElementOrDocument;
|
||||
struct DOMPointInit;
|
||||
struct GetRootNodeOptions;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -942,10 +943,11 @@ public:
|
||||
*/
|
||||
nsINode* SubtreeRoot() const;
|
||||
|
||||
nsINode* RootNode() const
|
||||
{
|
||||
return SubtreeRoot();
|
||||
}
|
||||
/*
|
||||
* Get context object's shadow-including root if options's composed is true,
|
||||
* and context object's root otherwise.
|
||||
*/
|
||||
nsINode* GetRootNode(const mozilla::dom::GetRootNodeOptions& aOptions);
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
|
||||
@@ -933,8 +933,12 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
||||
MOZ_ASSERT(!req, "Shouldn't have non-null request here");
|
||||
// If we don't have a current URI, we might as well store this URI so people
|
||||
// know what we tried (and failed) to load.
|
||||
if (!mCurrentRequest)
|
||||
if (!mCurrentRequest) {
|
||||
mCurrentURI = aNewURI;
|
||||
if (mImageBlockingStatus == nsIContentPolicy::ACCEPT) {
|
||||
mImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
FireEvent(NS_LITERAL_STRING("loadend"));
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsScriptLoader.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "xpcpublic.h"
|
||||
#include "nsIMozBrowserFrame.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/dom/SameProcessMessageQueue.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "nsXPCOMCIDInternal.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsTextFormatter.h"
|
||||
#include "ScriptSettings.h"
|
||||
|
||||
#include "xpcpublic.h"
|
||||
|
||||
@@ -55,6 +54,7 @@
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
#include "mozilla/dom/ErrorEvent.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsAXPCNativeCallContext.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
@@ -1161,7 +1161,7 @@ TimeUntilNow(TimeStamp start)
|
||||
|
||||
struct CycleCollectorStats
|
||||
{
|
||||
constexpr CycleCollectorStats() :
|
||||
CycleCollectorStats() :
|
||||
mMaxGCDuration(0), mRanSyncForgetSkippable(false), mSuspected(0),
|
||||
mMaxSkippableDuration(0), mMaxSliceTime(0), mMaxSliceTimeSinceClear(0),
|
||||
mTotalSliceTime(0), mAnyLockedOut(false), mExtraForgetSkippableCalls(0),
|
||||
|
||||
+11
-8
@@ -298,25 +298,28 @@ nsJSUtils::CompileModule(JSContext* aCx,
|
||||
|
||||
NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
|
||||
|
||||
if (!JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aModule)) {
|
||||
bool compileResult = JS::CompileModule(aCx, aCompileOptions, aSrcBuf, aModule);
|
||||
|
||||
if (!compileResult) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSUtils::ModuleDeclarationInstantiation(JSContext* aCx, JS::Handle<JSObject*> aModule)
|
||||
nsJSUtils::ModuleInstantiate(JSContext* aCx, JS::Handle<JSObject*> aModule)
|
||||
{
|
||||
PROFILER_LABEL("nsJSUtils", "ModuleDeclarationInstantiation",
|
||||
PROFILER_LABEL("nsJSUtils", "ModuleInstantiate",
|
||||
js::ProfileEntry::Category::JS);
|
||||
|
||||
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(CycleCollectedJSContext::Get() &&
|
||||
CycleCollectedJSContext::Get()->MicroTaskLevel());
|
||||
|
||||
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
|
||||
|
||||
if (!JS::ModuleDeclarationInstantiation(aCx, aModule)) {
|
||||
if (!JS::ModuleInstantiate(aCx, aModule)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@@ -324,9 +327,9 @@ nsJSUtils::ModuleDeclarationInstantiation(JSContext* aCx, JS::Handle<JSObject*>
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
|
||||
nsJSUtils::ModuleEvaluate(JSContext* aCx, JS::Handle<JSObject*> aModule)
|
||||
{
|
||||
PROFILER_LABEL("nsJSUtils", "ModuleEvaluation",
|
||||
PROFILER_LABEL("nsJSUtils", "ModuleEvaluate",
|
||||
js::ProfileEntry::Category::JS);
|
||||
|
||||
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
|
||||
@@ -335,7 +338,7 @@ nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
|
||||
|
||||
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
|
||||
|
||||
if (!JS::ModuleEvaluation(aCx, aModule)) {
|
||||
if (!JS::ModuleEvaluate(aCx, aModule)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,11 +116,11 @@ public:
|
||||
JS::CompileOptions &aCompileOptions,
|
||||
JS::MutableHandle<JSObject*> aModule);
|
||||
|
||||
static nsresult ModuleDeclarationInstantiation(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aModule);
|
||||
static nsresult ModuleInstantiate(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aModule);
|
||||
|
||||
static nsresult ModuleEvaluation(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aModule);
|
||||
static nsresult ModuleEvaluate(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aModule);
|
||||
|
||||
// Returns false if an exception got thrown on aCx. Passing a null
|
||||
// aElement is allowed; that wil produce an empty aScopeChain.
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIContentSerializer.h"
|
||||
#include "nsIDocumentEncoder.h"
|
||||
#include "nsILineBreaker.h"
|
||||
|
||||
@@ -393,8 +393,9 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
nsAutoString title, type, media;
|
||||
bool isScoped;
|
||||
bool isAlternate;
|
||||
bool isExplicitlyEnabled;
|
||||
|
||||
GetStyleSheetInfo(title, type, media, &isScoped, &isAlternate);
|
||||
GetStyleSheetInfo(title, type, media, &isScoped, &isAlternate, &isExplicitlyEnabled);
|
||||
|
||||
if (!type.LowerCaseEqualsLiteral("text/css")) {
|
||||
return NS_OK;
|
||||
@@ -425,7 +426,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
// Parse the style sheet.
|
||||
rv = doc->CSSLoader()->
|
||||
LoadInlineStyle(thisContent, text, mLineNumber, title, media,
|
||||
scopeElement, aObserver, &doneLoading, &isAlternate);
|
||||
scopeElement, aObserver, &doneLoading, &isAlternate, &isExplicitlyEnabled);
|
||||
}
|
||||
else {
|
||||
nsAutoString integrity;
|
||||
@@ -452,13 +453,14 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
rv = doc->CSSLoader()->
|
||||
LoadStyleLink(thisContent, clonedURI, title, media, isAlternate,
|
||||
GetCORSMode(), referrerPolicy, integrity,
|
||||
aObserver, &isAlternate);
|
||||
aObserver, &isAlternate, &isExplicitlyEnabled);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Don't propagate LoadStyleLink() errors further than this, since some
|
||||
// consumers (e.g. nsXMLContentSink) will completely abort on innocuous
|
||||
// things like a stylesheet load being blocked by the security system.
|
||||
doneLoading = true;
|
||||
isAlternate = false;
|
||||
isExplicitlyEnabled = false;
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,8 @@ protected:
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate) = 0;
|
||||
bool* aIsAlternate,
|
||||
bool* aIsExplicitlyEnabled) = 0;
|
||||
|
||||
virtual mozilla::CORSMode GetCORSMode() const
|
||||
{
|
||||
|
||||
@@ -1385,6 +1385,8 @@ nsTreeSanitizer::SanitizeChildren(nsINode* aRoot)
|
||||
nsAutoString styleText;
|
||||
nsContentUtils::GetNodeTextContent(node, false, styleText);
|
||||
|
||||
RemoveAllAttributesFromDescendants(elt);
|
||||
|
||||
nsAutoString sanitizedStyle;
|
||||
nsCOMPtr<nsIURI> baseURI = node->GetBaseURI();
|
||||
if (SanitizeStyleSheet(styleText,
|
||||
@@ -1480,6 +1482,17 @@ nsTreeSanitizer::RemoveAllAttributes(nsIContent* aElement)
|
||||
}
|
||||
}
|
||||
|
||||
void nsTreeSanitizer::RemoveAllAttributesFromDescendants(mozilla::dom::Element* aElement) {
|
||||
nsIContent* node = aElement->GetFirstChild();
|
||||
while (node) {
|
||||
if (node->IsElement()) {
|
||||
mozilla::dom::Element* elt = node->AsElement();
|
||||
RemoveAllAttributes(elt);
|
||||
}
|
||||
node = node->GetNextNode(aElement);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeSanitizer::InitializeStatics()
|
||||
{
|
||||
|
||||
@@ -183,6 +183,12 @@ class MOZ_STACK_CLASS nsTreeSanitizer {
|
||||
*/
|
||||
void RemoveAllAttributes(nsIContent* aElement);
|
||||
|
||||
/**
|
||||
* Removes all attributes from the descendants of an element but not from
|
||||
* the element itself.
|
||||
*/
|
||||
void RemoveAllAttributesFromDescendants(mozilla::dom::Element* aElement);
|
||||
|
||||
/**
|
||||
* The whitelist of HTML elements.
|
||||
*/
|
||||
|
||||
@@ -4,20 +4,27 @@
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
var wasRun = false;
|
||||
var hadSyntaxError = false;
|
||||
var errorCount = 0;
|
||||
var syntaxErrorCount = 0;
|
||||
var eventCount = 0;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onerror = handleError;
|
||||
|
||||
function handleError(message, url, line, column, error) {
|
||||
hadSyntaxError = error instanceof SyntaxError;
|
||||
errorCount++;
|
||||
if (error instanceof SyntaxError) {
|
||||
syntaxErrorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
function testError() {
|
||||
ok(!wasRun, 'Check script was not run');
|
||||
ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
|
||||
ok(errorCount == 1, 'Check that an error was reported');
|
||||
ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
|
||||
ok(eventCount == 0, 'Check that no error event was fired');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="module_badSyntax.js"></script>
|
||||
<script type="module" src="module_badSyntax.js" onerror="eventCount++"></script>
|
||||
<body onload='testError()'></body>
|
||||
@@ -4,20 +4,27 @@
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
var wasRun = false;
|
||||
var hadSyntaxError = false;
|
||||
var errorCount = 0;
|
||||
var syntaxErrorCount = 0;
|
||||
var eventCount = 0;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onerror = handleError;
|
||||
|
||||
function handleError(message, url, line, column, error) {
|
||||
hadSyntaxError = error instanceof SyntaxError;
|
||||
errorCount++;
|
||||
if (error instanceof SyntaxError) {
|
||||
syntaxErrorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
function testError() {
|
||||
ok(!wasRun, 'Check script was not run');
|
||||
ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
|
||||
ok(errorCount == 1, 'Check that an error was reported');
|
||||
ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
|
||||
ok(eventCount == 0, 'Check that no error event was fired');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="module_badSyntax.js" async></script>
|
||||
<script type="module" src="module_badSyntax.js" async onerror="eventCount++"></script>
|
||||
<body onload='testError()'></body>
|
||||
@@ -4,22 +4,29 @@
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
var wasRun = false;
|
||||
var hadSyntaxError = false;
|
||||
var errorCount = 0;
|
||||
var syntaxErrorCount = 0;
|
||||
var eventCount = 0;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onerror = handleError;
|
||||
|
||||
function handleError(message, url, line, column, error) {
|
||||
hadSyntaxError = error instanceof SyntaxError;
|
||||
errorCount++;
|
||||
if (error instanceof SyntaxError) {
|
||||
syntaxErrorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
function testError() {
|
||||
ok(!wasRun, 'Check script was not run');
|
||||
ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
|
||||
ok(errorCount == 1, 'Check that an error was reported');
|
||||
ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
|
||||
ok(eventCount == 0, 'Check that no error event was fired');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
<script type="module">
|
||||
<script type="module" onerror="eventCount++">
|
||||
// Module with a syntax error.
|
||||
some invalid js syntax;
|
||||
wasRun = true;
|
||||
|
||||
@@ -4,22 +4,29 @@
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
var wasRun = false;
|
||||
var hadSyntaxError = false;
|
||||
var errorCount = 0;
|
||||
var syntaxErrorCount = 0;
|
||||
var eventCount = 0;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onerror = handleError;
|
||||
|
||||
function handleError(message, url, line, column, error) {
|
||||
hadSyntaxError = error instanceof SyntaxError;
|
||||
errorCount++;
|
||||
if (error instanceof SyntaxError) {
|
||||
syntaxErrorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
function testError() {
|
||||
ok(!wasRun, 'Check script was not run');
|
||||
ok(hadSyntaxError, 'Check that a SyntaxError was thrown');
|
||||
ok(errorCount == 1, 'Check that an error was reported');
|
||||
ok(syntaxErrorCount == 1, 'Check that a syntax error was reported');
|
||||
ok(eventCount == 0, 'Check that no error event was fired');
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
<script type="module" async>
|
||||
<script type="module" async onerror="eventCount++">
|
||||
// Module with a syntax error.
|
||||
some invalid js syntax;
|
||||
wasRun = true;
|
||||
|
||||
@@ -15,7 +15,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840098
|
||||
<div id="content" style="display: none">
|
||||
<div id="foo"></div>
|
||||
</div>
|
||||
<marquee id="m">Hello</marquee>
|
||||
<div id="m">Hello</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
<div id="a" contenteditable><span id="test1">abc, abc, abc</span><br>
|
||||
<span id="test2" style="color: blue;">abc, abc, abc</span><br>
|
||||
<textarea id="test3">abc</textarea><input id="test4" value="abcdef"><br><br>
|
||||
<marquee>marquee</marquee>
|
||||
<div>div</div>
|
||||
</div>
|
||||
<input id="test5" value="The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well. Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. She took down a jar from one of the shelves as she passed; it was labelled `ORANGE MARMALADE', but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it." type="text">
|
||||
<input id="test6" type="number" style="width:150px; height:57px;" value="31415"><br>
|
||||
|
||||
@@ -1,913 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=641821
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 641821</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload="runTest()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641821">Mozilla Bug 641821</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 641821 **/
|
||||
|
||||
SimpleTest.requestFlakyTimeout("requestFlakyTimeout is silly. (But make sure marquee has time to initialize itself.)");
|
||||
|
||||
var div = document.createElement("div");
|
||||
|
||||
var M;
|
||||
if ("MozMutationObserver" in window) {
|
||||
M = window.MozMutationObserver;
|
||||
} else if ("WebKitMutationObserver" in window) {
|
||||
M = window.WebKitMutationObserver;
|
||||
} else {
|
||||
M = window.MutationObserver;
|
||||
}
|
||||
|
||||
function log(str) {
|
||||
var d = document.createElement("div");
|
||||
d.textContent = str;
|
||||
if (str.indexOf("PASSED") >= 0) {
|
||||
d.setAttribute("style", "color: green;");
|
||||
} else {
|
||||
d.setAttribute("style", "color: red;");
|
||||
}
|
||||
document.getElementById("log").appendChild(d);
|
||||
}
|
||||
|
||||
// Some helper functions so that this test runs also outside mochitest.
|
||||
if (!("ok" in window)) {
|
||||
window.ok = function(val, str) {
|
||||
log(str + (val ? " PASSED\n" : " FAILED\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!("is" in window)) {
|
||||
window.is = function(val, refVal, str) {
|
||||
log(str + (val == refVal? " PASSED " : " FAILED ") +
|
||||
(val != refVal ? "expected " + refVal + " got " + val + "\n" : "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!("isnot" in window)) {
|
||||
window.isnot = function(val, refVal, str) {
|
||||
log(str + (val != refVal? " PASSED " : " FAILED ") +
|
||||
(val == refVal ? "Didn't expect " + refVal + "\n" : "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!("SimpleTest" in window)) {
|
||||
window.SimpleTest =
|
||||
{
|
||||
finish: function() {
|
||||
document.getElementById("log").appendChild(document.createTextNode("DONE"));
|
||||
},
|
||||
waitForExplicitFinish: function() {}
|
||||
}
|
||||
}
|
||||
|
||||
function then(thenFn) {
|
||||
setTimeout(function() {
|
||||
if (thenFn) {
|
||||
setTimeout(thenFn, 0);
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
var m;
|
||||
var m2;
|
||||
var m3;
|
||||
var m4;
|
||||
|
||||
// Checks basic parameter validation and normal 'this' handling.
|
||||
// Tests also basic attribute handling.
|
||||
function runTest() {
|
||||
m = new M(function(){});
|
||||
ok(m, "MutationObserver supported");
|
||||
|
||||
var e = null;
|
||||
try {
|
||||
m.observe(document, {});
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(e, "Should have thrown an exception");
|
||||
is(e.name, "TypeError", "Should have thrown TypeError");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document, { childList: true, attributeOldValue: true });
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(!e, "Shouldn't have thrown an exception");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document, { childList: true, attributeFilter: ["foo"] });
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(!e, "Shouldn't have thrown an exception");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document, { childList: true, characterDataOldValue: true });
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(!e, "Shouldn't have thrown an exception");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document);
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(e, "Should have thrown an exception");
|
||||
|
||||
m = new M(function(records, observer) {
|
||||
is(observer, m, "2nd parameter should be the mutation observer");
|
||||
is(observer, this, "2nd parameter should be 'this'");
|
||||
is(records.length, 1, "Should have one record.");
|
||||
is(records[0].type, "attributes", "Should have got attributes record");
|
||||
is(records[0].target, div, "Should have got div as target");
|
||||
is(records[0].attributeName, "foo", "Should have got record about foo attribute");
|
||||
observer.disconnect();
|
||||
then(testThisBind);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { attributes: true, attributeFilter: ["foo"] });
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributes, true);
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeFilter.length, 1)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeFilter[0], "foo")
|
||||
div.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
// 'this' handling when fn.bind() is used.
|
||||
function testThisBind() {
|
||||
var child = div.appendChild(document.createElement("div"));
|
||||
var gchild = child.appendChild(document.createElement("div"));
|
||||
m = new M((function(records, observer) {
|
||||
is(observer, m, "2nd parameter should be the mutation observer");
|
||||
isnot(observer, this, "2nd parameter should be 'this'");
|
||||
is(records.length, 3, "Should have one record.");
|
||||
is(records[0].type, "attributes", "Should have got attributes record");
|
||||
is(records[0].target, div, "Should have got div as target");
|
||||
is(records[0].attributeName, "foo", "Should have got record about foo attribute");
|
||||
is(records[0].oldValue, "bar", "oldValue should be bar");
|
||||
is(records[1].type, "attributes", "Should have got attributes record");
|
||||
is(records[1].target, div, "Should have got div as target");
|
||||
is(records[1].attributeName, "foo", "Should have got record about foo attribute");
|
||||
is(records[1].oldValue, "bar2", "oldValue should be bar2");
|
||||
is(records[2].type, "attributes", "Should have got attributes record");
|
||||
is(records[2].target, gchild, "Should have got div as target");
|
||||
is(records[2].attributeName, "foo", "Should have got record about foo attribute");
|
||||
is(records[2].oldValue, null, "oldValue should be bar2");
|
||||
observer.disconnect();
|
||||
then(testCharacterData);
|
||||
m = null;
|
||||
}).bind(window));
|
||||
m.observe(div, { attributes: true, attributeOldValue: true, subtree: true });
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributes, true)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeOldValue, true)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].subtree, true)
|
||||
div.setAttribute("foo", "bar2");
|
||||
div.removeAttribute("foo");
|
||||
div.removeChild(child);
|
||||
child.removeChild(gchild);
|
||||
div.appendChild(gchild);
|
||||
div.removeChild(gchild);
|
||||
gchild.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
function testCharacterData() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "characterData", "Should have got characterData");
|
||||
is(records[0].oldValue, null, "Shouldn't have got oldData");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
});
|
||||
m2 = new M(function(records, observer) {
|
||||
is(records[0].type, "characterData", "Should have got characterData");
|
||||
is(records[0].oldValue, "foo", "Should have got oldData");
|
||||
observer.disconnect();
|
||||
m2 = null;
|
||||
});
|
||||
m3 = new M(function(records, observer) {
|
||||
ok(false, "This should not be called!");
|
||||
observer.disconnect();
|
||||
m3 = null;
|
||||
});
|
||||
m4 = new M(function(records, observer) {
|
||||
is(records[0].oldValue, null, "Shouldn't have got oldData");
|
||||
observer.disconnect();
|
||||
m3.disconnect();
|
||||
m3 = null;
|
||||
then(testChildList);
|
||||
m4 = null;
|
||||
});
|
||||
|
||||
div.appendChild(document.createTextNode("foo"));
|
||||
m.observe(div, { characterData: true, subtree: true });
|
||||
m2.observe(div, { characterData: true, characterDataOldValue: true, subtree: true});
|
||||
// If observing the same node twice, only the latter option should apply.
|
||||
m3.observe(div, { characterData: true, subtree: true });
|
||||
m3.observe(div, { characterData: true, subtree: false });
|
||||
m4.observe(div.firstChild, { characterData: true, subtree: false });
|
||||
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers().length, 3)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[2].getObservingInfo()[0].characterData, true)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[2].getObservingInfo()[0].subtree, false)
|
||||
|
||||
div.firstChild.data = "bar";
|
||||
}
|
||||
|
||||
function testChildList() {
|
||||
var fc = div.firstChild;
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "childList", "Should have got childList");
|
||||
is(records[0].addedNodes.length, 0, "Shouldn't have got addedNodes");
|
||||
is(records[0].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[0].removedNodes[0], fc, "Should have removed a text node");
|
||||
observer.disconnect();
|
||||
then(testChildList2);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true});
|
||||
div.removeChild(div.firstChild);
|
||||
}
|
||||
|
||||
function testChildList2() {
|
||||
div.innerHTML = "<span>1</span><span>2</span>";
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "childList", "Should have got childList");
|
||||
is(records[0].removedNodes.length, 2, "Should have got removedNodes");
|
||||
is(records[0].addedNodes.length, 1, "Should have got addedNodes");
|
||||
observer.disconnect();
|
||||
then(testChildList3);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true });
|
||||
div.innerHTML = "<span><span>foo</span></span>";
|
||||
}
|
||||
|
||||
function testChildList3() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "childList", "Should have got childList");
|
||||
is(records[0].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[0].addedNodes.length, 1, "Should have got addedNodes");
|
||||
observer.disconnect();
|
||||
then(testChildList4);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true });
|
||||
div.textContent = "hello";
|
||||
}
|
||||
|
||||
function testChildList4() {
|
||||
div.textContent = null;
|
||||
var df = document.createDocumentFragment();
|
||||
var t1 = df.appendChild(document.createTextNode("Hello "));
|
||||
var t2 = df.appendChild(document.createTextNode("world!"));
|
||||
var s1 = div.appendChild(document.createElement("span"));
|
||||
s1.textContent = "foo";
|
||||
var s2 = div.appendChild(document.createElement("span"));
|
||||
function callback(records, observer) {
|
||||
is(records.length, 3, "Should have got one record for removing nodes from document fragment and one record for adding them to div");
|
||||
is(records[0].removedNodes.length, 2, "Should have got removedNodes");
|
||||
is(records[0].removedNodes[0], t1, "Should be the 1st textnode");
|
||||
is(records[0].removedNodes[1], t2, "Should be the 2nd textnode");
|
||||
is(records[1].addedNodes.length, 2, "Should have got addedNodes");
|
||||
is(records[1].addedNodes[0], t1, "Should be the 1st textnode");
|
||||
is(records[1].addedNodes[1], t2, "Should be the 2nd textnode");
|
||||
is(records[1].previousSibling, s1, "Should have previousSibling");
|
||||
is(records[1].nextSibling, s2, "Should have nextSibling");
|
||||
is(records[2].type, "characterData", "3rd record should be characterData");
|
||||
is(records[2].target, t1, "target should be the textnode");
|
||||
is(records[2].oldValue, "Hello ", "oldValue was 'Hello '");
|
||||
observer.disconnect();
|
||||
then(testChildList5);
|
||||
m = null;
|
||||
};
|
||||
m = new M(callback);
|
||||
m.observe(df, { childList: true, characterData: true, characterDataOldValue: true, subtree: true });
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].childList, true)
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].characterData, true)
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].characterDataOldValue, true)
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].subtree, true)
|
||||
ok(SpecialPowers.compare(SpecialPowers.wrap(df).getBoundMutationObservers()[0].mutationCallback, callback))
|
||||
m.observe(div, { childList: true });
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo().length, 2)
|
||||
|
||||
// Make sure transient observers aren't leaked.
|
||||
var leakTest = new M(function(){});
|
||||
leakTest.observe(div, { characterData: true, subtree: true });
|
||||
|
||||
div.insertBefore(df, s2);
|
||||
s1.firstChild.data = "bar"; // This should *not* create a record.
|
||||
t1.data = "Hello the whole "; // This should create a record.
|
||||
}
|
||||
|
||||
function testChildList5() {
|
||||
div.textContent = null;
|
||||
var c1 = div.appendChild(document.createElement("div"));
|
||||
var c2 = document.createElement("div");
|
||||
var div2 = document.createElement("div");
|
||||
var c3 = div2.appendChild(document.createElement("div"));
|
||||
var c4 = document.createElement("div");
|
||||
var c5 = document.createElement("div");
|
||||
var df = document.createDocumentFragment();
|
||||
var emptyDF = document.createDocumentFragment();
|
||||
var dfc1 = df.appendChild(document.createElement("div"));
|
||||
var dfc2 = df.appendChild(document.createElement("div"));
|
||||
var dfc3 = df.appendChild(document.createElement("div"));
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 6 , "");
|
||||
is(records[0].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[0].removedNodes[0], c1, "");
|
||||
is(records[0].addedNodes.length, 1, "Should have got addedNodes");
|
||||
is(records[0].addedNodes[0], c2, "");
|
||||
is(records[0].previousSibling, null, "");
|
||||
is(records[0].nextSibling, null, "");
|
||||
is(records[1].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[1].removedNodes[0], c3, "");
|
||||
is(records[1].addedNodes.length, 0, "Shouldn't have got addedNodes");
|
||||
is(records[1].previousSibling, null, "");
|
||||
is(records[1].nextSibling, null, "");
|
||||
is(records[2].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[2].removedNodes[0], c2, "");
|
||||
is(records[2].addedNodes.length, 1, "Should have got addedNodes");
|
||||
is(records[2].addedNodes[0], c3, "");
|
||||
is(records[2].previousSibling, null, "");
|
||||
is(records[2].nextSibling, null, "");
|
||||
// Check document fragment handling
|
||||
is(records[5].removedNodes.length, 1, "");
|
||||
is(records[5].removedNodes[0], c4, "");
|
||||
is(records[5].addedNodes.length, 3, "");
|
||||
is(records[5].addedNodes[0], dfc1, "");
|
||||
is(records[5].addedNodes[1], dfc2, "");
|
||||
is(records[5].addedNodes[2], dfc3, "");
|
||||
is(records[5].previousSibling, c3, "");
|
||||
is(records[5].nextSibling, c5, "");
|
||||
observer.disconnect();
|
||||
then(testAdoptNode);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true, subtree: true });
|
||||
m.observe(div2, { childList: true, subtree: true });
|
||||
div.replaceChild(c2, c1);
|
||||
div.replaceChild(c3, c2);
|
||||
div.appendChild(c4);
|
||||
div.appendChild(c5);
|
||||
div.replaceChild(df, c4);
|
||||
div.appendChild(emptyDF); // empty document shouldn't cause mutation records
|
||||
}
|
||||
|
||||
function testAdoptNode() {
|
||||
var d1 = document.implementation.createHTMLDocument(null);
|
||||
var d2 = document.implementation.createHTMLDocument(null);
|
||||
var addedNode;
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 3, "Should have 2 records");
|
||||
is(records[0].target.ownerDocument, d1, "ownerDocument should be the initial document")
|
||||
is(records[1].target.ownerDocument, d2, "ownerDocument should be the new document");
|
||||
is(records[2].type, "attributes", "Should have got attribute mutation")
|
||||
is(records[2].attributeName, "foo", "Should have got foo attribute mutation")
|
||||
observer.disconnect();
|
||||
then(testOuterHTML);
|
||||
m = null;
|
||||
});
|
||||
m.observe(d1, { childList: true, subtree: true, attributes: true });
|
||||
d2.body.appendChild(d1.body);
|
||||
addedNode = d2.body.lastChild.appendChild(d2.createElement("div"));
|
||||
addedNode.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
function testOuterHTML() {
|
||||
var doc = document.implementation.createHTMLDocument(null);
|
||||
var d1 = doc.body.appendChild(document.createElement("div"));
|
||||
var d2 = doc.body.appendChild(document.createElement("div"));
|
||||
var d3 = doc.body.appendChild(document.createElement("div"));
|
||||
var d4 = doc.body.appendChild(document.createElement("div"));
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 4, "Should have 1 record");
|
||||
is(records[0].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[0].addedNodes.length, 2, "Should have 2 added nodes");
|
||||
is(records[0].previousSibling, null, "");
|
||||
is(records[0].nextSibling, d2, "");
|
||||
is(records[1].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[1].addedNodes.length, 2, "Should have 2 added nodes");
|
||||
is(records[1].previousSibling, records[0].addedNodes[1], "");
|
||||
is(records[1].nextSibling, d3, "");
|
||||
is(records[2].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[2].addedNodes.length, 2, "Should have 2 added nodes");
|
||||
is(records[2].previousSibling, records[1].addedNodes[1], "");
|
||||
is(records[2].nextSibling, d4, "");
|
||||
is(records[3].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[3].addedNodes.length, 0);
|
||||
is(records[3].previousSibling, records[2].addedNodes[1], "");
|
||||
is(records[3].nextSibling, null, "");
|
||||
observer.disconnect();
|
||||
then(testInsertAdjacentHTML);
|
||||
m = null;
|
||||
});
|
||||
m.observe(doc, { childList: true, subtree: true });
|
||||
d1.outerHTML = "<div>1</div><div>1</div>";
|
||||
d2.outerHTML = "<div>2</div><div>2</div>";
|
||||
d3.outerHTML = "<div>3</div><div>3</div>";
|
||||
d4.outerHTML = "";
|
||||
}
|
||||
|
||||
function testInsertAdjacentHTML() {
|
||||
var doc = document.implementation.createHTMLDocument(null);
|
||||
var d1 = doc.body.appendChild(document.createElement("div"));
|
||||
var d2 = doc.body.appendChild(document.createElement("div"));
|
||||
var d3 = doc.body.appendChild(document.createElement("div"));
|
||||
var d4 = doc.body.appendChild(document.createElement("div"));
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 4, "");
|
||||
is(records[0].target, doc.body, "");
|
||||
is(records[0].previousSibling, null, "");
|
||||
is(records[0].nextSibling, d1, "");
|
||||
is(records[1].target, d2, "");
|
||||
is(records[1].previousSibling, null, "");
|
||||
is(records[1].nextSibling, null, "");
|
||||
is(records[2].target, d3, "");
|
||||
is(records[2].previousSibling, null, "");
|
||||
is(records[2].nextSibling, null, "");
|
||||
is(records[3].target, doc.body, "");
|
||||
is(records[3].previousSibling, d4, "");
|
||||
is(records[3].nextSibling, null, "");
|
||||
observer.disconnect();
|
||||
then(testSyncXHR);
|
||||
m = null;
|
||||
});
|
||||
m.observe(doc, { childList: true, subtree: true });
|
||||
d1.insertAdjacentHTML("beforebegin", "<div></div><div></div>");
|
||||
d2.insertAdjacentHTML("afterbegin", "<div></div><div></div>");
|
||||
d3.insertAdjacentHTML("beforeend", "<div></div><div></div>");
|
||||
d4.insertAdjacentHTML("afterend", "<div></div><div></div>");
|
||||
}
|
||||
|
||||
|
||||
var callbackHandled = false;
|
||||
|
||||
function testSyncXHR() {
|
||||
div.textContent = null;
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "");
|
||||
is(records[0].addedNodes.length, 1, "");
|
||||
callbackHandled = true;
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true, subtree: true });
|
||||
div.innerHTML = "<div>hello</div>";
|
||||
var x = new XMLHttpRequest();
|
||||
x.open("GET", window.location, false);
|
||||
x.send();
|
||||
ok(!callbackHandled, "Shouldn't have called the mutation callback!");
|
||||
setTimeout(testSyncXHR2, 0);
|
||||
}
|
||||
|
||||
function testSyncXHR2() {
|
||||
ok(callbackHandled, "Should have called the mutation callback!");
|
||||
then(testTakeRecords);
|
||||
}
|
||||
|
||||
function testTakeRecords() {
|
||||
var s = "<span>1</span><span>2</span>";
|
||||
div.innerHTML = s;
|
||||
var takenRecords;
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 3, "Should have got 3 records");
|
||||
|
||||
is(records[0].type, "attributes", "Should have got attributes");
|
||||
is(records[0].attributeName, "foo", "");
|
||||
is(records[0].attributeNamespace, null, "");
|
||||
is(records[0].prevValue, null, "");
|
||||
is(records[1].type, "childList", "Should have got childList");
|
||||
is(records[1].removedNodes.length, 2, "Should have got removedNodes");
|
||||
is(records[1].addedNodes.length, 2, "Should have got addedNodes");
|
||||
is(records[2].type, "attributes", "Should have got attributes");
|
||||
is(records[2].attributeName, "foo", "");
|
||||
|
||||
is(records.length, takenRecords.length, "Should have had similar mutations");
|
||||
is(records[0].type, takenRecords[0].type, "Should have had similar mutations");
|
||||
is(records[1].type, takenRecords[1].type, "Should have had similar mutations");
|
||||
is(records[2].type, takenRecords[2].type, "Should have had similar mutations");
|
||||
|
||||
is(records[1].removedNodes.length, takenRecords[1].removedNodes.length, "Should have had similar mutations");
|
||||
is(records[1].addedNodes.length, takenRecords[1].addedNodes.length, "Should have had similar mutations");
|
||||
|
||||
is(m.takeRecords().length, 0, "Shouldn't have any records");
|
||||
observer.disconnect();
|
||||
then(testMutationObserverAndEvents);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true, attributes: true });
|
||||
div.setAttribute("foo", "bar");
|
||||
div.innerHTML = s;
|
||||
div.removeAttribute("foo");
|
||||
takenRecords = m.takeRecords();
|
||||
div.setAttribute("foo", "bar");
|
||||
div.innerHTML = s;
|
||||
div.removeAttribute("foo");
|
||||
}
|
||||
|
||||
function testTakeRecords() {
|
||||
function mutationListener(e) {
|
||||
++mutationEventCount;
|
||||
is(e.attrChange, MutationEvent.ADDITION, "unexpected change");
|
||||
}
|
||||
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 2, "Should have got 2 records");
|
||||
is(records[0].type, "attributes", "Should have got attributes");
|
||||
is(records[0].attributeName, "foo", "");
|
||||
is(records[0].oldValue, null, "");
|
||||
is(records[1].type, "attributes", "Should have got attributes");
|
||||
is(records[1].attributeName, "foo", "");
|
||||
is(records[1].oldValue, "bar", "");
|
||||
observer.disconnect();
|
||||
div.removeEventListener("DOMAttrModified", mutationListener);
|
||||
then(testExpandos);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { attributes: true, attributeOldValue: true });
|
||||
// Note, [0] points to a mutation observer which is there for a leak test!
|
||||
ok(SpecialPowers.compare(SpecialPowers.wrap(div).getBoundMutationObservers()[1], m));
|
||||
var mutationEventCount = 0;
|
||||
div.addEventListener("DOMAttrModified", mutationListener);
|
||||
div.setAttribute("foo", "bar");
|
||||
div.setAttribute("foo", "bar");
|
||||
is(mutationEventCount, 1, "Should have got only one mutation event!");
|
||||
}
|
||||
|
||||
function testExpandos() {
|
||||
var m2 = new M(function(records, observer) {
|
||||
is(observer.expandoProperty, true);
|
||||
observer.disconnect();
|
||||
then(testOutsideShadowDOM);
|
||||
});
|
||||
m2.expandoProperty = true;
|
||||
m2.observe(div, { attributes: true });
|
||||
m2 = null;
|
||||
if (SpecialPowers) {
|
||||
// Run GC several times to see if the expando property disappears.
|
||||
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.gc();
|
||||
}
|
||||
div.setAttribute("foo", "bar2");
|
||||
}
|
||||
|
||||
function testOutsideShadowDOM() {
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 1);
|
||||
is(records[0].type, "attributes", "Should have got attributes");
|
||||
observer.disconnect();
|
||||
then(testInsideShadowDOM);
|
||||
});
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
})
|
||||
var sr = div.createShadowRoot();
|
||||
sr.innerHTML = "<div" + ">text</" + "div>";
|
||||
sr.firstChild.setAttribute("foo", "bar");
|
||||
sr.firstChild.firstChild.data = "text2";
|
||||
sr.firstChild.appendChild(document.createElement("div"));
|
||||
div.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
function testInsideShadowDOM() {
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 4);
|
||||
is(records[0].type, "childList");
|
||||
is(records[1].type, "attributes");
|
||||
is(records[2].type, "characterData");
|
||||
is(records[3].type, "childList");
|
||||
observer.disconnect();
|
||||
then(testMarquee);
|
||||
});
|
||||
var sr = div.createShadowRoot();
|
||||
m.observe(sr, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
sr.innerHTML = "<div" + ">text</" + "div>";
|
||||
sr.firstChild.setAttribute("foo", "bar");
|
||||
sr.firstChild.firstChild.data = "text2";
|
||||
sr.firstChild.appendChild(document.createElement("div"));
|
||||
div.setAttribute("foo", "bar2");
|
||||
|
||||
}
|
||||
|
||||
function testMarquee() {
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 1);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].attributeName, "ok");
|
||||
is(records[0].oldValue, null);
|
||||
observer.disconnect();
|
||||
then(testStyleCreate);
|
||||
});
|
||||
var marquee = document.createElement("marquee");
|
||||
m.observe(marquee, {
|
||||
attributes: true,
|
||||
attributeOldValue: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
});
|
||||
document.body.appendChild(marquee);
|
||||
setTimeout(function() {marquee.setAttribute("ok", "ok")}, 500);
|
||||
}
|
||||
|
||||
function testStyleCreate() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "style", "record.attributeName");
|
||||
is(records[0].oldValue, null, "record.oldValue");
|
||||
isnot(div.getAttribute("style"), null, "style attribute after creation");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("style");
|
||||
then(testStyleModify);
|
||||
});
|
||||
m.observe(div, { attributes: true, attributeOldValue: true });
|
||||
is(div.getAttribute("style"), null, "style attribute before creation");
|
||||
div.style.color = "blue";
|
||||
}
|
||||
|
||||
function testStyleModify() {
|
||||
div.style.color = "yellow";
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "style", "record.attributeName");
|
||||
isnot(div.getAttribute("style"), null, "style attribute after modification");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("style");
|
||||
then(testStyleRead);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
isnot(div.getAttribute("style"), null, "style attribute before modification");
|
||||
div.style.color = "blue";
|
||||
}
|
||||
|
||||
function testStyleRead() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "data-test", "record.attributeName");
|
||||
is(div.getAttribute("style"), null, "style attribute after read");
|
||||
observer.disconnect();
|
||||
div.removeAttribute("data-test");
|
||||
m = null;
|
||||
then(testStyleRemoveProperty);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
is(div.getAttribute("style"), null, "style attribute before read");
|
||||
var value = div.style.color; // shouldn't generate any mutation records
|
||||
div.setAttribute("data-test", "a");
|
||||
}
|
||||
|
||||
function testStyleRemoveProperty() {
|
||||
div.style.color = "blue";
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "style", "record.attributeName");
|
||||
isnot(div.getAttribute("style"), null, "style attribute after successful removeProperty");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("style");
|
||||
then(testStyleRemoveProperty2);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
isnot(div.getAttribute("style"), null, "style attribute before successful removeProperty");
|
||||
div.style.removeProperty("color");
|
||||
}
|
||||
|
||||
function testStyleRemoveProperty2() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "data-test", "record.attributeName");
|
||||
is(div.getAttribute("style"), null, "style attribute after unsuccessful removeProperty");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("data-test");
|
||||
then(testAttributeRecordMerging1);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
is(div.getAttribute("style"), null, "style attribute before unsuccessful removeProperty");
|
||||
div.style.removeProperty("color"); // shouldn't generate any mutation records
|
||||
div.setAttribute("data-test", "a");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging1() {
|
||||
ok(true, "testAttributeRecordMerging1");
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 2);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, null);
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, null);
|
||||
observer.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testAttributeRecordMerging2);
|
||||
});
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging2() {
|
||||
ok(true, "testAttributeRecordMerging2");
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 2);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, "initial");
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, "initial");
|
||||
observer.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testAttributeRecordMerging3);
|
||||
});
|
||||
|
||||
div.setAttribute("foo", "initial");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "initial");
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
attributeOldValue: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging3() {
|
||||
ok(true, "testAttributeRecordMerging3");
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 4);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, "initial");
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, "initial");
|
||||
|
||||
is(records[2].type, "attributes");
|
||||
is(records[2].target, div);
|
||||
is(records[2].attributeName, "foo");
|
||||
is(records[2].attributeNamespace, null);
|
||||
is(records[2].oldValue, "bar_1");
|
||||
|
||||
is(records[3].type, "attributes");
|
||||
is(records[3].target, div.firstChild);
|
||||
is(records[3].attributeName, "foo");
|
||||
is(records[3].attributeNamespace, null);
|
||||
is(records[3].oldValue, "bar_1");
|
||||
|
||||
observer.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testAttributeRecordMerging4);
|
||||
});
|
||||
|
||||
div.setAttribute("foo", "initial");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "initial");
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
attributeOldValue: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
// No merging should happen.
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging4() {
|
||||
ok(true, "testAttributeRecordMerging4");
|
||||
var m = new M(function(records, observer) {
|
||||
});
|
||||
|
||||
div.setAttribute("foo", "initial");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "initial");
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
attributeOldValue: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
|
||||
var records = m.takeRecords();
|
||||
|
||||
is(records.length, 2);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, "initial");
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, "initial");
|
||||
m.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testChromeOnly);
|
||||
}
|
||||
|
||||
function testChromeOnly() {
|
||||
// Content can't access nativeAnonymousChildList
|
||||
try {
|
||||
var mo = new M(function(records, observer) { });
|
||||
mo.observe(div, { nativeAnonymousChildList: true });
|
||||
ok(false, "Should have thrown when trying to observe with chrome-only init");
|
||||
} catch (e) {
|
||||
ok(true, "Throws when trying to observe with chrome-only init");
|
||||
}
|
||||
|
||||
then();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<div id="log">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,212 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include "BatteryManager.h"
|
||||
#include "Constants.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/dom/BatteryManagerBinding.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
/**
|
||||
* We have to use macros here because our leak analysis tool things we are
|
||||
* leaking strings when we have |static const nsString|. Sad :(
|
||||
*/
|
||||
#define LEVELCHANGE_EVENT_NAME NS_LITERAL_STRING("levelchange")
|
||||
#define CHARGINGCHANGE_EVENT_NAME NS_LITERAL_STRING("chargingchange")
|
||||
#define DISCHARGINGTIMECHANGE_EVENT_NAME NS_LITERAL_STRING("dischargingtimechange")
|
||||
#define CHARGINGTIMECHANGE_EVENT_NAME NS_LITERAL_STRING("chargingtimechange")
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace battery {
|
||||
|
||||
BatteryManager::BatteryManager(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mLevel(kDefaultLevel)
|
||||
, mCharging(kDefaultCharging)
|
||||
, mRemainingTime(kDefaultRemainingTime)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::Init()
|
||||
{
|
||||
hal::RegisterBatteryObserver(this);
|
||||
|
||||
hal::BatteryInformation batteryInfo;
|
||||
hal::GetCurrentBatteryInformation(&batteryInfo);
|
||||
|
||||
UpdateFromBatteryInfo(batteryInfo);
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::Shutdown()
|
||||
{
|
||||
hal::UnregisterBatteryObserver(this);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
BatteryManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return BatteryManagerBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
bool
|
||||
BatteryManager::Charging() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default", false)) {
|
||||
return true;
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.charging", false)) {
|
||||
return true;
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mCharging;
|
||||
}
|
||||
|
||||
double
|
||||
BatteryManager::DischargingTime() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default", false)) {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
|
||||
return 42.0;
|
||||
}
|
||||
|
||||
if (Charging() || mRemainingTime == kUnknownRemainingTime) {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
return mRemainingTime;
|
||||
}
|
||||
|
||||
double
|
||||
BatteryManager::ChargingTime() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default", false)) {
|
||||
return 0.0;
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.charging", false)) {
|
||||
return 42.0;
|
||||
}
|
||||
|
||||
if (!Charging() || mRemainingTime == kUnknownRemainingTime) {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
return mRemainingTime;
|
||||
}
|
||||
|
||||
double
|
||||
BatteryManager::Level() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default")) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return mLevel;
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
|
||||
{
|
||||
mLevel = aBatteryInfo.level();
|
||||
|
||||
// Round to the nearest ten percent for non-chrome and non-certified apps
|
||||
nsIDocument* doc = GetOwner() ? GetOwner()->GetDoc() : nullptr;
|
||||
uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
if (doc) {
|
||||
status = doc->NodePrincipal()->GetAppStatus();
|
||||
}
|
||||
|
||||
mCharging = aBatteryInfo.charging();
|
||||
mRemainingTime = aBatteryInfo.remainingTime();
|
||||
|
||||
if (!nsContentUtils::IsChromeDoc(doc) &&
|
||||
status != nsIPrincipal::APP_STATUS_CERTIFIED)
|
||||
{
|
||||
mLevel = lround(mLevel * 10.0) / 10.0;
|
||||
if (mLevel == 1.0) {
|
||||
mRemainingTime = mCharging ? kDefaultRemainingTime : kUnknownRemainingTime;
|
||||
} else if (mRemainingTime != kUnknownRemainingTime) {
|
||||
// Round the remaining time to a multiple of 15 minutes and never zero
|
||||
const double MINUTES_15 = 15.0 * 60.0;
|
||||
mRemainingTime = fmax(lround(mRemainingTime / MINUTES_15) * MINUTES_15,
|
||||
MINUTES_15);
|
||||
}
|
||||
}
|
||||
|
||||
// Add some guards to make sure the values are coherent.
|
||||
if (mLevel == 1.0 && mCharging == true &&
|
||||
mRemainingTime != kDefaultRemainingTime) {
|
||||
mRemainingTime = kDefaultRemainingTime;
|
||||
NS_ERROR("Battery API: When charging and level at 1.0, remaining time "
|
||||
"should be 0. Please fix your backend!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::Notify(const hal::BatteryInformation& aBatteryInfo)
|
||||
{
|
||||
double previousLevel = mLevel;
|
||||
bool previousCharging = mCharging;
|
||||
double previousRemainingTime = mRemainingTime;
|
||||
|
||||
UpdateFromBatteryInfo(aBatteryInfo);
|
||||
|
||||
if (previousCharging != mCharging) {
|
||||
DispatchTrustedEvent(CHARGINGCHANGE_EVENT_NAME);
|
||||
}
|
||||
|
||||
if (previousLevel != mLevel) {
|
||||
DispatchTrustedEvent(LEVELCHANGE_EVENT_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
* There are a few situations that could happen here:
|
||||
* 1. Charging state changed:
|
||||
* a. Previous remaining time wasn't unkwonw, we have to fire an event for
|
||||
* the change.
|
||||
* b. New remaining time isn't unkwonw, we have to fire an event for it.
|
||||
* 2. Charging state didn't change but remainingTime did, we have to fire
|
||||
* the event that correspond to the current charging state.
|
||||
*/
|
||||
if (mCharging != previousCharging) {
|
||||
if (previousRemainingTime != kUnknownRemainingTime) {
|
||||
DispatchTrustedEvent(previousCharging ? CHARGINGTIMECHANGE_EVENT_NAME
|
||||
: DISCHARGINGTIMECHANGE_EVENT_NAME);
|
||||
}
|
||||
if (mRemainingTime != kUnknownRemainingTime) {
|
||||
DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
|
||||
: DISCHARGINGTIMECHANGE_EVENT_NAME);
|
||||
}
|
||||
} else if (previousRemainingTime != mRemainingTime) {
|
||||
DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
|
||||
: DISCHARGINGTIMECHANGE_EVENT_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace battery
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -1,84 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_battery_BatteryManager_h
|
||||
#define mozilla_dom_battery_BatteryManager_h
|
||||
|
||||
#include "Types.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/Observer.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace hal {
|
||||
class BatteryInformation;
|
||||
} // namespace hal
|
||||
|
||||
namespace dom {
|
||||
namespace battery {
|
||||
|
||||
class BatteryManager : public DOMEventTargetHelper
|
||||
, public BatteryObserver
|
||||
{
|
||||
public:
|
||||
explicit BatteryManager(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
// For IObserver.
|
||||
void Notify(const hal::BatteryInformation& aBatteryInfo) override;
|
||||
|
||||
/**
|
||||
* WebIDL Interface
|
||||
*/
|
||||
|
||||
nsPIDOMWindowInner* GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
bool Charging() const;
|
||||
|
||||
double ChargingTime() const;
|
||||
|
||||
double DischargingTime() const;
|
||||
|
||||
double Level() const;
|
||||
|
||||
IMPL_EVENT_HANDLER(chargingchange)
|
||||
IMPL_EVENT_HANDLER(chargingtimechange)
|
||||
IMPL_EVENT_HANDLER(dischargingtimechange)
|
||||
IMPL_EVENT_HANDLER(levelchange)
|
||||
|
||||
private:
|
||||
/**
|
||||
* Update the battery information stored in the battery manager object using
|
||||
* a battery information object.
|
||||
*/
|
||||
void UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo);
|
||||
|
||||
/**
|
||||
* Represents the battery level, ranging from 0.0 (dead or removed?)
|
||||
* to 1.0 (fully charged)
|
||||
*/
|
||||
double mLevel;
|
||||
bool mCharging;
|
||||
/**
|
||||
* Represents the discharging time or the charging time, depending on the
|
||||
* current battery status (charging or not).
|
||||
*/
|
||||
double mRemainingTime;
|
||||
};
|
||||
|
||||
} // namespace battery
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_battery_BatteryManager_h
|
||||
@@ -1,27 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_battery_Constants_h__
|
||||
#define mozilla_dom_battery_Constants_h__
|
||||
|
||||
/**
|
||||
* A set of constants that might need to be used by battery backends.
|
||||
* It's not part of BatteryManager.h to prevent those backends to include it.
|
||||
*/
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace battery {
|
||||
|
||||
static const double kDefaultLevel = 1.0;
|
||||
static const bool kDefaultCharging = true;
|
||||
static const double kDefaultRemainingTime = 0;
|
||||
static const double kUnknownRemainingTime = -1;
|
||||
|
||||
} // namespace battery
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_battery_Constants_h__
|
||||
@@ -1,23 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_battery_Types_h
|
||||
#define mozilla_dom_battery_Types_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
class BatteryInformation;
|
||||
} // namespace hal
|
||||
|
||||
template <class T>
|
||||
class Observer;
|
||||
|
||||
typedef Observer<hal::BatteryInformation> BatteryObserver;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_battery_Types_h
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[test_battery_basics.html]
|
||||
[test_battery_charging.html]
|
||||
[test_battery_discharging.html]
|
||||
@@ -1 +0,0 @@
|
||||
[test_battery_unprivileged.html]
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** Test for Battery API **/
|
||||
ok("getBattery" in navigator, "navigator.getBattery should exist");
|
||||
ok(!("battery" in navigator), "navigator.battery should not exist");
|
||||
|
||||
navigator.getBattery().then(function (battery) {
|
||||
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.default", true]]}, function () {
|
||||
ok(battery.charging, "Battery should be charging by default");
|
||||
is(battery.chargingTime, 0, "Battery chargingTime " + battery.chargingTime + " should be zero by default");
|
||||
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity by default");
|
||||
is(battery.level, 1.0, "Battery level " + battery.level + " should be 1.0 by default");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** Test for Battery API **/
|
||||
navigator.getBattery().then(function (battery) {
|
||||
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.charging", true]]}, function () {
|
||||
is(battery.charging, true, "Battery should be charging");
|
||||
ok(battery.chargingTime >= 0, "Battery chargingTime " + battery.chargingTime + " should be nonnegative when charging");
|
||||
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity when charging");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** Test for Battery API **/
|
||||
navigator.getBattery().then(function (battery) {
|
||||
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.discharging", true]]}, function () {
|
||||
is(battery.charging, false, "Battery should be discharging");
|
||||
is(battery.chargingTime, Infinity, "Battery chargingTime should be Infinity when discharging");
|
||||
ok(battery.dischargingTime > 0, "Battery dischargingTime " + battery.dischargingTime + " should be positive when discharging");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
/** Test for Battery API **/
|
||||
ok(!("getBattery" in navigator), "navigator.getBattery should not exist for unprivileged web content");
|
||||
ok(!("battery" in navigator), "navigator.battery should not exist");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2487,6 +2487,12 @@ ConstructJSImplementation(const char* aContractId,
|
||||
{
|
||||
AutoNoJSAPI nojsapi;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||
if (!window->IsCurrentInnerWindow()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the XPCOM component containing the JS implementation.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupports> implISupports = do_CreateInstance(aContractId, &rv);
|
||||
@@ -2501,7 +2507,6 @@ ConstructJSImplementation(const char* aContractId,
|
||||
// and our global is a window.
|
||||
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi =
|
||||
do_QueryInterface(implISupports);
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||
if (gpi) {
|
||||
JS::Rooted<JS::Value> initReturn(RootingCx());
|
||||
rv = gpi->Init(window, &initReturn);
|
||||
|
||||
@@ -3071,21 +3071,21 @@ class GetCCParticipant
|
||||
{
|
||||
// Helper for GetCCParticipant for classes that participate in CC.
|
||||
template<class U>
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
GetHelper(int, typename U::NS_CYCLE_COLLECTION_INNERCLASS* dummy=nullptr)
|
||||
{
|
||||
return T::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant();
|
||||
}
|
||||
// Helper for GetCCParticipant for classes that don't participate in CC.
|
||||
template<class U>
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
GetHelper(double)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
Get()
|
||||
{
|
||||
// Passing int() here will try to call the GetHelper that takes an int as
|
||||
@@ -3100,7 +3100,7 @@ template<class T>
|
||||
class GetCCParticipant<T, true>
|
||||
{
|
||||
public:
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
Get()
|
||||
{
|
||||
return nullptr;
|
||||
@@ -3123,7 +3123,7 @@ EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||
template <class T>
|
||||
struct CreateGlobalOptions
|
||||
{
|
||||
static constexpr ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
static const ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
ProtoAndIfaceCache::NonWindowLike;
|
||||
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||
{
|
||||
@@ -3140,7 +3140,7 @@ struct CreateGlobalOptions
|
||||
template <>
|
||||
struct CreateGlobalOptions<nsGlobalWindow>
|
||||
{
|
||||
static constexpr ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
static const ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
ProtoAndIfaceCache::WindowLike;
|
||||
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
|
||||
static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
|
||||
|
||||
@@ -717,6 +717,21 @@ DOMInterfaces = {
|
||||
},
|
||||
},
|
||||
|
||||
'ResizeObservation': {
|
||||
'nativeType': 'mozilla::dom::ResizeObservation',
|
||||
'headerFile': 'mozilla/dom/ResizeObserver.h',
|
||||
},
|
||||
|
||||
'ResizeObserver': {
|
||||
'nativeType': 'mozilla::dom::ResizeObserver',
|
||||
'headerFile': 'mozilla/dom/ResizeObserver.h',
|
||||
},
|
||||
|
||||
'ResizeObserverEntry': {
|
||||
'nativeType': 'mozilla::dom::ResizeObserverEntry',
|
||||
'headerFile': 'mozilla/dom/ResizeObserver.h',
|
||||
},
|
||||
|
||||
'Response': {
|
||||
'binaryNames': { 'headers': 'headers_' },
|
||||
},
|
||||
|
||||
@@ -210,7 +210,7 @@ struct NativePropertiesN {
|
||||
|
||||
const int32_t iteratorAliasMethodIndex;
|
||||
|
||||
constexpr const NativePropertiesN<7>* Upcast() const {
|
||||
const NativePropertiesN<7>* Upcast() const {
|
||||
return reinterpret_cast<const NativePropertiesN<7>*>(this);
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 1498 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user