forked from upstream/UXP-mirror
Compare commits
323
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
451509e2c0 | ||
|
|
7895b8acd9 | ||
|
|
ccff4610c5 | ||
|
|
15a1f78f8b | ||
|
|
8b44473fe6 | ||
|
|
6e0aee959e | ||
|
|
ba5930cc8e | ||
|
|
6376255c0c | ||
|
|
320682148b | ||
|
|
1ed84ac1f8 | ||
|
|
9c9d04e3e0 | ||
|
|
19504d5263 | ||
|
|
533b346f4e | ||
|
|
6afd96c460 | ||
|
|
9858dc03cb | ||
|
|
d21b46fc9c | ||
|
|
55fa46d059 | ||
|
|
b089b365d6 | ||
|
|
0c150945dc | ||
|
|
0fb23389f5 | ||
|
|
7ba07f4a17 | ||
|
|
554183b5dd | ||
|
|
98fe8b0ccb | ||
|
|
519030e688 | ||
|
|
b9531d8e11 | ||
|
|
7605f4b0f8 | ||
|
|
ab0e18135f | ||
|
|
e883ac54e9 | ||
|
|
9cb65e8a77 | ||
|
|
3a3152d54b | ||
|
|
f174801b64 | ||
|
|
3caceeb539 | ||
|
|
216189e6f7 | ||
|
|
bbae11cdd9 | ||
|
|
917447df6e | ||
|
|
244c8ef1f7 | ||
|
|
e1b6493747 | ||
|
|
4e225fc7d1 | ||
|
|
683b1bedea | ||
|
|
11519ee6d2 | ||
|
|
8a343284d9 | ||
|
|
5a34fb5e1d | ||
|
|
16c8dff724 | ||
|
|
3595b9eecf | ||
|
|
594cbca6d1 | ||
|
|
a4ba260904 | ||
|
|
4a8c186eea | ||
|
|
8ff6e8c8a2 | ||
|
|
3652cd0f99 | ||
|
|
b738ccc61b | ||
|
|
1c3a9a40e5 | ||
|
|
0a33733505 | ||
|
|
691878e20f | ||
|
|
bf1fa93b91 | ||
|
|
0ac7481d2e | ||
|
|
168bb31e4f | ||
|
|
ca04b37910 | ||
|
|
f3b26f64fc | ||
|
|
99d23484bb | ||
|
|
376bc050a6 | ||
|
|
9258382b0d | ||
|
|
b6a703907e | ||
|
|
da42871b0e | ||
|
|
c55433ee03 | ||
|
|
d0a2389b43 | ||
|
|
796a14e116 | ||
|
|
ba6e4753b7 | ||
|
|
6d3d69f644 | ||
|
|
fce3132fe8 | ||
|
|
a7da3cf52b | ||
|
|
f5316668a3 | ||
|
|
dc687dbc0b | ||
|
|
216aa2cada | ||
|
|
9d96ad90dd | ||
|
|
b064c95231 | ||
|
|
11eb1f57f4 | ||
|
|
052cb18fff | ||
|
|
d306fe61c5 | ||
|
|
7859a0d693 | ||
|
|
c5d9e1f973 | ||
|
|
2e12bda342 | ||
|
|
9755cd617d | ||
|
|
abaf4d9fb4 | ||
|
|
ae6f407177 | ||
|
|
2a44476795 | ||
|
|
755cf4c7d0 | ||
|
|
47f26a67f4 | ||
|
|
e8aa76713a | ||
|
|
e6ffc4bdb7 | ||
|
|
90bbe7536d | ||
|
|
140750e4e8 | ||
|
|
f2e089d51b | ||
|
|
e1d0ac30ac | ||
|
|
9e8adc25a4 | ||
|
|
7f66e8946a | ||
|
|
c75b8ec714 | ||
|
|
4250d93166 | ||
|
|
37250226d5 | ||
|
|
802a4cfefe | ||
|
|
5641a6d574 | ||
|
|
88d2480356 | ||
|
|
fcb4b997d0 | ||
|
|
79964767f5 | ||
|
|
a4a8d082a3 | ||
|
|
adce88de95 | ||
|
|
974d6ca889 | ||
|
|
e08a4ad1c8 | ||
|
|
39dac57259 | ||
|
|
c2d9ab62f3 | ||
|
|
b9e692af05 | ||
|
|
871e57fdd6 | ||
|
|
03530de64f | ||
|
|
4730da5b27 | ||
|
|
3cb245b749 | ||
|
|
9f5529d1e7 | ||
|
|
26c888208a | ||
|
|
9a52b3b852 | ||
|
|
96afb5250d | ||
|
|
b93afb1ba7 | ||
|
|
277f2116b6 | ||
|
|
d270404436 | ||
|
|
3bec218684 | ||
|
|
6daff43b61 | ||
|
|
eedf9f5ebf | ||
|
|
049dae86d2 | ||
|
|
65ba3cac58 | ||
|
|
1b8788aecb | ||
|
|
747632bd64 | ||
|
|
02327fa745 | ||
|
|
b470422d5a | ||
|
|
449d530a30 | ||
|
|
8bd941d4e3 | ||
|
|
7172fc72a3 | ||
|
|
b977981df6 | ||
|
|
9dc65422ba | ||
|
|
45e8e98031 | ||
|
|
965232ab2f | ||
|
|
980ca14602 | ||
|
|
02519e8575 | ||
|
|
e003547dc5 | ||
|
|
56f8375338 | ||
|
|
2407845ec1 | ||
|
|
3f09b298b0 | ||
|
|
c27830f35c | ||
|
|
99bad1726e | ||
|
|
d86349716a | ||
|
|
64a7c9e2d2 | ||
|
|
514ff21cba | ||
|
|
edb5796d58 | ||
|
|
c23e3b25f8 | ||
|
|
e360caa1a2 | ||
|
|
9eeaeff77b | ||
|
|
a435374873 | ||
|
|
04cfc091da | ||
|
|
b23e7b61c6 | ||
|
|
69b4e77751 | ||
|
|
5657b5c53b | ||
|
|
1037746d00 | ||
|
|
a060401264 | ||
|
|
4e26fc1844 | ||
|
|
2645f9b944 | ||
|
|
88ce149033 | ||
|
|
09655ad6d8 | ||
|
|
4fd0b98c2c | ||
|
|
894b33e53a | ||
|
|
236d425993 | ||
|
|
899e14e945 | ||
|
|
03fda9f0f3 | ||
|
|
3aae828871 | ||
|
|
e7514afc7c | ||
|
|
4adf0d09f7 | ||
|
|
22d0b88e37 | ||
|
|
f7388678bd | ||
|
|
b45f5c435e | ||
|
|
3c73c0805c | ||
|
|
db93b005f5 | ||
|
|
d2aaa74f31 | ||
|
|
702cf42544 | ||
|
|
79a9dc2479 | ||
|
|
ddcc3deddd | ||
|
|
f3b148844a | ||
|
|
51d5d162b7 | ||
|
|
94494805da | ||
|
|
5c7109182c | ||
|
|
68e873ada7 | ||
|
|
a5b05528fe | ||
|
|
ce88d82f4a | ||
|
|
61d3aa9be2 | ||
|
|
a078d9f976 | ||
|
|
3ed2b7a7cc | ||
|
|
9816a810e6 | ||
|
|
9a8068ea3f | ||
|
|
dcd9bbb717 | ||
|
|
ecc0a40688 | ||
|
|
8f40737fc7 | ||
|
|
e7841ab5d7 | ||
|
|
dba09fa5c4 | ||
|
|
afe2b7fa5a | ||
|
|
acaec3f389 | ||
|
|
d2083edba2 | ||
|
|
1ebcc1d7e5 | ||
|
|
cbb61ab832 | ||
|
|
cf288a1847 | ||
|
|
0d1eea2ebf | ||
|
|
af69cb07db | ||
|
|
dc4695406f | ||
|
|
c22a493144 | ||
|
|
d20ca24a07 | ||
|
|
b2ca17a298 | ||
|
|
eb70e6e3d0 | ||
|
|
32ead79529 | ||
|
|
3e59235162 | ||
|
|
7494866cb5 | ||
|
|
19bf63b0ee | ||
|
|
8b539ec9e7 | ||
|
|
ba0011606d | ||
|
|
ec2daa8dc9 | ||
|
|
44c169c9be | ||
|
|
57383be95d | ||
|
|
6ef03f136b | ||
|
|
d6bcaa6491 | ||
|
|
92edec6f58 | ||
|
|
2dea4edfd7 | ||
|
|
54cb1b965e | ||
|
|
a6d1dd183d | ||
|
|
da15aa0fdf | ||
|
|
867737dd4b | ||
|
|
36fc5f674e | ||
|
|
7b30664f59 | ||
|
|
ef71f96a8d | ||
|
|
2b99226680 | ||
|
|
2794f0c48c | ||
|
|
2f23073a3a | ||
|
|
496fbaf738 | ||
|
|
85621ee9b3 | ||
|
|
ee6595e6de | ||
|
|
201be4d8fc | ||
|
|
9e586a1d0e | ||
|
|
009c9dd2f8 | ||
|
|
6407f1abd4 | ||
|
|
28f0155307 | ||
|
|
11ede87242 | ||
|
|
3630fec559 | ||
|
|
d062e7311c | ||
|
|
0313ac74fd | ||
|
|
9612c64265 | ||
|
|
c5d570792d | ||
|
|
10c4e73e56 | ||
|
|
c9fd86cb78 | ||
|
|
550d634ff5 | ||
|
|
bbee80fa1c | ||
|
|
8ffe533b3d | ||
|
|
9670bdb685 | ||
|
|
8fa80e2c8d | ||
|
|
a377d1ecd4 | ||
|
|
1ebbb0af03 | ||
|
|
29b13d3523 | ||
|
|
76476ed75b | ||
|
|
84fc500ff2 | ||
|
|
2560dd2514 | ||
|
|
0e2b0db4d7 | ||
|
|
c4f65de9b2 | ||
|
|
e3148b0a25 | ||
|
|
fe6730c219 | ||
|
|
2e44ddb15e | ||
|
|
da74d1f3f3 | ||
|
|
91be118376 | ||
|
|
2258e09d59 | ||
|
|
30ec922d7e | ||
|
|
1000488a5b | ||
|
|
ffe75592e3 | ||
|
|
0084e71953 | ||
|
|
dbeceecde2 | ||
|
|
9fc28c55c3 | ||
|
|
113a825c1f | ||
|
|
419abfb09f | ||
|
|
4e58dab0a1 | ||
|
|
9e42d9ea2f | ||
|
|
377f54f3fe | ||
|
|
62f39d829d | ||
|
|
28971524e4 | ||
|
|
be37269123 | ||
|
|
8acff5cdbe | ||
|
|
11a4ab0982 | ||
|
|
8c41fcd240 | ||
|
|
27f4e60be8 | ||
|
|
aae1baabe9 | ||
|
|
f620afc446 | ||
|
|
456f4a5891 | ||
|
|
84d99e2996 | ||
|
|
e29301f5d0 | ||
|
|
369ad75fc8 | ||
|
|
37e3135bc5 | ||
|
|
259bd2e977 | ||
|
|
0ebdc99757 | ||
|
|
68d3bc54fb | ||
|
|
2109f36dd4 | ||
|
|
58f10adc97 | ||
|
|
05c68a17a0 | ||
|
|
f78958a020 | ||
|
|
bcd6c96aec | ||
|
|
73289f5389 | ||
|
|
4acc0d58cb | ||
|
|
a1c9dd468d | ||
|
|
0a5acb852a | ||
|
|
c8bbebe59d | ||
|
|
fddc35e438 | ||
|
|
7e4efa4e1f | ||
|
|
84b5515a8d | ||
|
|
6b7fa183dd | ||
|
|
a43d59bcbf | ||
|
|
ac6896b599 | ||
|
|
171053d0b2 | ||
|
|
efd88ee999 | ||
|
|
9a74d53315 | ||
|
|
e2a478072a | ||
|
|
cb06cac81d | ||
|
|
c3d92cd338 | ||
|
|
8ae2267eac | ||
|
|
563dc95cdb | ||
|
|
7e59ac9036 | ||
|
|
f1e40aaa5b | ||
|
|
068372c618 |
No files matched your search
@@ -22,5 +22,5 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for incremental customElements v1 landing
|
||||
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 site](http://developer.palemoon.org).
|
||||
information will be available on the [Pale Moon developer wiki](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
|
||||
|
||||
@@ -347,6 +347,16 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // marquee
|
||||
&nsGkAtoms::marquee,
|
||||
roles::ANIMATION,
|
||||
kUseMapRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eOffLiveAttr,
|
||||
kGenericAccType,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // math
|
||||
&nsGkAtoms::math,
|
||||
roles::FLAT_EQUATION,
|
||||
|
||||
@@ -732,6 +732,8 @@ 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_)
|
||||
@@ -867,6 +869,7 @@ 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,6 +62,7 @@ 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"});
|
||||
@@ -71,6 +72,7 @@ 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"});
|
||||
@@ -78,11 +80,13 @@ 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"});
|
||||
@@ -226,9 +230,11 @@ 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-1', 'image-2', 'image-3']);
|
||||
['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-1', 'image-2', 'image-3',
|
||||
'heading-5', '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,6 +41,7 @@
|
||||
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);
|
||||
@@ -88,6 +89,9 @@
|
||||
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);
|
||||
@@ -215,6 +219,7 @@
|
||||
<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"/>
|
||||
@@ -258,6 +263,7 @@
|
||||
<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_GRAPHIC,
|
||||
children: []
|
||||
role: ROLE_TEXT,
|
||||
children: [ { role: ROLE_TEXT_LEAF } ]
|
||||
};
|
||||
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"; then
|
||||
if test -z "$JS_STANDALONE" -a "$OS_TARGET" != WINNT -a "$MOZ_WIDGET_TOOLKIT" != "android"; then
|
||||
MOZ_ICU_DATA_ARCHIVE=1
|
||||
else
|
||||
MOZ_ICU_DATA_ARCHIVE=
|
||||
|
||||
@@ -436,22 +436,23 @@ nsresult nsChromeRegistry::RefreshWindow(nsPIDOMWindowOuter* aWindow)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
size_t count = document->SheetCount();
|
||||
int32_t count = document->GetNumberOfStyleSheets();
|
||||
|
||||
// Build an array of style sheets we need to reload.
|
||||
nsTArray<RefPtr<StyleSheet>> oldSheets(count);
|
||||
nsTArray<RefPtr<StyleSheet>> newSheets(count);
|
||||
|
||||
// Iterate over the style sheets.
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
// Get the style sheet
|
||||
oldSheets.AppendElement(document->SheetAt(i));
|
||||
StyleSheet* styleSheet = document->GetStyleSheetAt(i);
|
||||
oldSheets.AppendElement(styleSheet);
|
||||
}
|
||||
|
||||
// Iterate over our old sheets and kick off a sync load of the new
|
||||
// sheet if and only if it's a non-inline sheet with a chrome URL.
|
||||
for (StyleSheet* sheet : oldSheets) {
|
||||
MOZ_ASSERT(sheet, "SheetAt shouldn't return nullptr for "
|
||||
MOZ_ASSERT(sheet, "GetStyleSheetAt shouldn't return nullptr for "
|
||||
"in-range sheet indexes");
|
||||
nsIURI* uri = sheet->GetSheetURI();
|
||||
|
||||
|
||||
Vendored
+6
@@ -40,6 +40,12 @@ 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,7 +112,6 @@ CERT_GetCertChainFromCert
|
||||
CERT_GetCertEmailAddress
|
||||
CERT_GetCertificateDer
|
||||
CERT_GetCertificateRequestExtensions
|
||||
CERT_GetCertKeyType
|
||||
CERT_GetCertTimes
|
||||
CERT_GetCertTrust
|
||||
CERT_GetCommonName
|
||||
@@ -271,7 +270,6 @@ NSS_Init
|
||||
NSS_Initialize
|
||||
NSS_InitWithMerge
|
||||
NSS_IsInitialized
|
||||
NSS_OptionGet
|
||||
NSS_OptionSet
|
||||
NSS_NoDB_Init
|
||||
NSS_SecureMemcmp
|
||||
@@ -385,7 +383,6 @@ 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.6.0
|
||||
4.5.0
|
||||
@@ -33,7 +33,7 @@ function* testTopLeft(inspector, view) {
|
||||
let afterElement = children.nodes[children.nodes.length - 1];
|
||||
yield selectNode(afterElement, inspector);
|
||||
top = getComputedViewPropertyValue(view, "top");
|
||||
is(top, "96px", "The computed view shows the correct top");
|
||||
is(top, "50%", "The computed view shows the correct top");
|
||||
left = getComputedViewPropertyValue(view, "left");
|
||||
is(left, "96px", "The computed view shows the correct left");
|
||||
is(left, "50%", "The computed view shows the correct left");
|
||||
}
|
||||
@@ -1,98 +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 "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
|
||||
@@ -1,59 +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_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
|
||||
@@ -1,124 +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 "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()
|
||||
{
|
||||
MOZ_ASSERT(!mAborted);
|
||||
mAborted = true;
|
||||
|
||||
// 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
|
||||
@@ -1,76 +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_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
|
||||
@@ -1,113 +0,0 @@
|
||||
<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>
|
||||
@@ -1,6 +0,0 @@
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
file_abort_controller.html
|
||||
worker_fetch_controller.js
|
||||
|
||||
[test_abort_controller.html]
|
||||
@@ -1,40 +0,0 @@
|
||||
<!--
|
||||
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>
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
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]();
|
||||
}
|
||||
@@ -356,16 +356,24 @@ EffectCompositor::GetElementToRestyle(dom::Element* aElement,
|
||||
return aElement;
|
||||
}
|
||||
|
||||
nsIFrame* primaryFrame = aElement->GetPrimaryFrame();
|
||||
if (!primaryFrame) {
|
||||
return nullptr;
|
||||
}
|
||||
nsIFrame* pseudoFrame;
|
||||
if (aPseudoType == CSSPseudoElementType::before) {
|
||||
return nsLayoutUtils::GetBeforePseudo(aElement);
|
||||
pseudoFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame);
|
||||
} else if (aPseudoType == CSSPseudoElementType::after) {
|
||||
pseudoFrame = nsLayoutUtils::GetAfterFrame(primaryFrame);
|
||||
} else {
|
||||
NS_NOTREACHED("Should not try to get the element to restyle for a pseudo "
|
||||
"other that :before or :after");
|
||||
return nullptr;
|
||||
}
|
||||
if (aPseudoType == CSSPseudoElementType::after) {
|
||||
return nsLayoutUtils::GetAfterPseudo(aElement);
|
||||
if (!pseudoFrame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("Should not try to get the element to restyle for a pseudo "
|
||||
"other that :before or :after");
|
||||
return nullptr;
|
||||
return pseudoFrame->GetContent()->AsElement();
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -1107,17 +1107,19 @@ KeyframeEffectReadOnly::GetAnimationFrame() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIFrame* frame;
|
||||
nsIFrame* frame = mTarget->mElement->GetPrimaryFrame();
|
||||
if (!frame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mTarget->mPseudoType == CSSPseudoElementType::before) {
|
||||
frame = nsLayoutUtils::GetBeforeFrame(mTarget->mElement);
|
||||
frame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
} else if (mTarget->mPseudoType == CSSPseudoElementType::after) {
|
||||
frame = nsLayoutUtils::GetAfterFrame(mTarget->mElement);
|
||||
frame = nsLayoutUtils::GetAfterFrame(frame);
|
||||
} else {
|
||||
frame = mTarget->mElement->GetPrimaryFrame();
|
||||
MOZ_ASSERT(mTarget->mPseudoType == CSSPseudoElementType::NotPseudo,
|
||||
"unknown mTarget->mPseudoType");
|
||||
}
|
||||
|
||||
if (!frame) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@ ArchiveRequest::~ArchiveRequest()
|
||||
}
|
||||
|
||||
nsresult
|
||||
ArchiveRequest::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
ArchiveRequest::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = true;
|
||||
aVisitor.SetParentTarget(nullptr, false);
|
||||
aVisitor.mParentTarget = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,7 @@ public:
|
||||
ArchiveReader* aReader);
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult GetEventTargetParent(
|
||||
EventChainPreVisitor& aVisitor) override;
|
||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
||||
|
||||
public:
|
||||
// This is called by the DOMArchiveRequestEvent
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "AnonymousContent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/AnonymousContentBinding.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMHTMLCollection.h"
|
||||
@@ -209,31 +208,5 @@ AnonymousContent::WrapObject(JSContext* aCx,
|
||||
return AnonymousContentBinding::Wrap(aCx, this, aGivenProto, aReflector);
|
||||
}
|
||||
|
||||
void
|
||||
AnonymousContent::GetComputedStylePropertyValue(const nsAString& aElementId,
|
||||
const nsAString& aPropertyName,
|
||||
DOMString& aResult,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Element* element = GetElementById(aElementId);
|
||||
if (!element) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIPresShell* shell = element->OwnerDoc()->GetShell();
|
||||
if (!shell) {
|
||||
aRv.Throw(NS_ERROR_NOT_AVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<nsComputedDOMStyle> cs =
|
||||
new nsComputedDOMStyle(element,
|
||||
NS_LITERAL_STRING(""),
|
||||
element->OwnerDoc(),
|
||||
nsComputedDOMStyle::eAll);
|
||||
aRv = cs->GetPropertyValue(aPropertyName, aResult);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -68,11 +68,6 @@ public:
|
||||
const Sequence<OwningNonNull<DOMRect>>& aRects,
|
||||
ErrorResult& aError);
|
||||
|
||||
void GetComputedStylePropertyValue(const nsAString& aElementId,
|
||||
const nsAString& aPropertyName,
|
||||
DOMString& aResult,
|
||||
ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
~AnonymousContent();
|
||||
nsCOMPtr<Element> mContentNode;
|
||||
|
||||
+1
-1
@@ -344,7 +344,7 @@ Attr::RemoveChildAt(uint32_t aIndex, bool aNotify)
|
||||
}
|
||||
|
||||
nsresult
|
||||
Attr::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
Attr::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mCanHandle = true;
|
||||
return NS_OK;
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ public:
|
||||
// nsIDOMAttr interface
|
||||
NS_DECL_NSIDOMATTR
|
||||
|
||||
virtual nsresult GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override;
|
||||
|
||||
// nsIAttribute interface
|
||||
void SetMap(nsDOMAttributeMap *aMap) override;
|
||||
|
||||
+2
-2
@@ -4,11 +4,11 @@
|
||||
* 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 <stdint.h>
|
||||
|
||||
#ifndef CORSMode_h_
|
||||
#define CORSMode_h_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum CORSMode : uint8_t {
|
||||
|
||||
+179
-122
@@ -6,27 +6,61 @@
|
||||
|
||||
#include "ChildIterator.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "mozilla/dom/HTMLSlotElement.h"
|
||||
#include "mozilla/dom/XBLChildrenElement.h"
|
||||
#include "mozilla/dom/HTMLContentElement.h"
|
||||
#include "mozilla/dom/HTMLShadowElement.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "nsIAnonymousContentCreator.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsCSSAnonBoxes.h"
|
||||
#include "nsDocument.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
ExplicitChildIterator::ExplicitChildIterator(const nsIContent* aParent,
|
||||
bool aStartAtBeginning)
|
||||
: mParent(aParent),
|
||||
mChild(nullptr),
|
||||
mDefaultChild(nullptr),
|
||||
mIsFirst(aStartAtBeginning),
|
||||
mIndexInInserted(0)
|
||||
class MatchedNodes {
|
||||
public:
|
||||
explicit MatchedNodes(HTMLContentElement* aInsertionPoint)
|
||||
: mIsContentElement(true), mContentElement(aInsertionPoint) {}
|
||||
|
||||
explicit MatchedNodes(XBLChildrenElement* aInsertionPoint)
|
||||
: mIsContentElement(false), mChildrenElement(aInsertionPoint) {}
|
||||
|
||||
uint32_t Length() const
|
||||
{
|
||||
return mIsContentElement ? mContentElement->MatchedNodes().Length()
|
||||
: mChildrenElement->InsertedChildrenLength();
|
||||
}
|
||||
|
||||
nsIContent* operator[](int32_t aIndex) const
|
||||
{
|
||||
return mIsContentElement ? mContentElement->MatchedNodes()[aIndex]
|
||||
: mChildrenElement->InsertedChild(aIndex);
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return mIsContentElement ? mContentElement->MatchedNodes().IsEmpty()
|
||||
: !mChildrenElement->HasInsertedChildren();
|
||||
}
|
||||
protected:
|
||||
bool mIsContentElement;
|
||||
union {
|
||||
HTMLContentElement* mContentElement;
|
||||
XBLChildrenElement* mChildrenElement;
|
||||
};
|
||||
};
|
||||
|
||||
static inline MatchedNodes
|
||||
GetMatchedNodesForPoint(nsIContent* aContent)
|
||||
{
|
||||
mParentAsSlot = nsDocument::IsWebComponentsEnabled(mParent) ?
|
||||
HTMLSlotElement::FromContent(mParent) : nullptr;
|
||||
if (aContent->NodeInfo()->Equals(nsGkAtoms::children, kNameSpaceID_XBL)) {
|
||||
// XBL case
|
||||
return MatchedNodes(static_cast<XBLChildrenElement*>(aContent));
|
||||
}
|
||||
|
||||
// Web components case
|
||||
MOZ_ASSERT(aContent->IsHTMLElement(nsGkAtoms::content));
|
||||
return MatchedNodes(HTMLContentElement::FromContent(aContent));
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
@@ -35,29 +69,30 @@ ExplicitChildIterator::GetNextChild()
|
||||
// If we're already in the inserted-children array, look there first
|
||||
if (mIndexInInserted) {
|
||||
MOZ_ASSERT(mChild);
|
||||
MOZ_ASSERT(nsContentUtils::IsContentInsertionPoint(mChild));
|
||||
MOZ_ASSERT(!mDefaultChild);
|
||||
|
||||
if (mParentAsSlot) {
|
||||
const nsTArray<RefPtr<nsINode>>& assignedNodes =
|
||||
mParentAsSlot->AssignedNodes();
|
||||
|
||||
mChild = (mIndexInInserted < assignedNodes.Length()) ?
|
||||
assignedNodes[mIndexInInserted++]->AsContent() : nullptr;
|
||||
return mChild;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mChild->IsActiveChildrenElement());
|
||||
auto* childrenElement =
|
||||
static_cast<XBLChildrenElement*>(mChild);
|
||||
if (mIndexInInserted < childrenElement->InsertedChildrenLength()) {
|
||||
return childrenElement->InsertedChild(mIndexInInserted++);
|
||||
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
|
||||
if (mIndexInInserted < assignedChildren.Length()) {
|
||||
return assignedChildren[mIndexInInserted++];
|
||||
}
|
||||
mIndexInInserted = 0;
|
||||
mChild = mChild->GetNextSibling();
|
||||
} else if (mShadowIterator) {
|
||||
// If we're inside of a <shadow> element, look through the
|
||||
// explicit children of the projected ShadowRoot via
|
||||
// the mShadowIterator.
|
||||
nsIContent* nextChild = mShadowIterator->GetNextChild();
|
||||
if (nextChild) {
|
||||
return nextChild;
|
||||
}
|
||||
|
||||
mShadowIterator = nullptr;
|
||||
mChild = mChild->GetNextSibling();
|
||||
} else if (mDefaultChild) {
|
||||
// If we're already in default content, check if there are more nodes there
|
||||
MOZ_ASSERT(mChild);
|
||||
MOZ_ASSERT(mChild->IsActiveChildrenElement());
|
||||
MOZ_ASSERT(nsContentUtils::IsContentInsertionPoint(mChild));
|
||||
|
||||
mDefaultChild = mDefaultChild->GetNextSibling();
|
||||
if (mDefaultChild) {
|
||||
@@ -66,19 +101,6 @@ ExplicitChildIterator::GetNextChild()
|
||||
|
||||
mChild = mChild->GetNextSibling();
|
||||
} else if (mIsFirst) { // at the beginning of the child list
|
||||
// For slot parent, iterate over assigned nodes if not empty, otherwise
|
||||
// fall through and iterate over direct children (fallback content).
|
||||
if (mParentAsSlot) {
|
||||
const nsTArray<RefPtr<nsINode>>& assignedNodes =
|
||||
mParentAsSlot->AssignedNodes();
|
||||
if (!assignedNodes.IsEmpty()) {
|
||||
mIndexInInserted = 1;
|
||||
mChild = assignedNodes[0]->AsContent();
|
||||
mIsFirst = false;
|
||||
return mChild;
|
||||
}
|
||||
}
|
||||
|
||||
mChild = mParent->GetFirstChild();
|
||||
mIsFirst = false;
|
||||
} else if (mChild) { // in the middle of the child list
|
||||
@@ -88,16 +110,31 @@ ExplicitChildIterator::GetNextChild()
|
||||
// Iterate until we find a non-insertion point, or an insertion point with
|
||||
// content.
|
||||
while (mChild) {
|
||||
if (mChild->IsActiveChildrenElement()) {
|
||||
// If the current child being iterated is a shadow insertion point then
|
||||
// the iterator needs to go into the projected ShadowRoot.
|
||||
if (ShadowRoot::IsShadowInsertionPoint(mChild)) {
|
||||
// Look for the next child in the projected ShadowRoot for the <shadow>
|
||||
// element.
|
||||
HTMLShadowElement* shadowElem = HTMLShadowElement::FromContent(mChild);
|
||||
ShadowRoot* projectedShadow = shadowElem->GetOlderShadowRoot();
|
||||
if (projectedShadow) {
|
||||
mShadowIterator = new ExplicitChildIterator(projectedShadow);
|
||||
nsIContent* nextChild = mShadowIterator->GetNextChild();
|
||||
if (nextChild) {
|
||||
return nextChild;
|
||||
}
|
||||
mShadowIterator = nullptr;
|
||||
}
|
||||
mChild = mChild->GetNextSibling();
|
||||
} else if (nsContentUtils::IsContentInsertionPoint(mChild)) {
|
||||
// If the current child being iterated is a content insertion point
|
||||
// then the iterator needs to return the nodes distributed into
|
||||
// the content insertion point.
|
||||
auto* childrenElement =
|
||||
static_cast<XBLChildrenElement*>(mChild);
|
||||
if (childrenElement->HasInsertedChildren()) {
|
||||
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
|
||||
if (!assignedChildren.IsEmpty()) {
|
||||
// Iterate through elements projected on insertion point.
|
||||
mIndexInInserted = 1;
|
||||
return childrenElement->InsertedChild(0);
|
||||
return assignedChildren[0];
|
||||
}
|
||||
|
||||
// Insertion points inside fallback/default content
|
||||
@@ -155,17 +192,19 @@ FlattenedChildIterator::Init(bool aIgnoreXBL)
|
||||
}
|
||||
|
||||
bool
|
||||
ExplicitChildIterator::Seek(const nsIContent* aChildToFind)
|
||||
ExplicitChildIterator::Seek(nsIContent* aChildToFind)
|
||||
{
|
||||
if (aChildToFind->GetParent() == mParent &&
|
||||
!aChildToFind->IsRootOfAnonymousSubtree()) {
|
||||
// Fast path: just point ourselves to aChildToFind, which is a
|
||||
// normal DOM child of ours.
|
||||
mChild = const_cast<nsIContent*>(aChildToFind);
|
||||
MOZ_ASSERT(!ShadowRoot::IsShadowInsertionPoint(aChildToFind));
|
||||
MOZ_ASSERT(!nsContentUtils::IsContentInsertionPoint(aChildToFind));
|
||||
mChild = aChildToFind;
|
||||
mIndexInInserted = 0;
|
||||
mShadowIterator = nullptr;
|
||||
mDefaultChild = nullptr;
|
||||
mIsFirst = false;
|
||||
MOZ_ASSERT(!mChild->IsActiveChildrenElement());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -181,18 +220,12 @@ ExplicitChildIterator::Get() const
|
||||
{
|
||||
MOZ_ASSERT(!mIsFirst);
|
||||
|
||||
// When mParentAsSlot is set, mChild is always set to the current child. It
|
||||
// does not matter whether mChild is an assigned node or a fallback content.
|
||||
if (mParentAsSlot) {
|
||||
return mChild;
|
||||
}
|
||||
|
||||
if (mIndexInInserted) {
|
||||
MOZ_ASSERT(mChild->IsActiveChildrenElement());
|
||||
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
|
||||
return childrenElement->InsertedChild(mIndexInInserted - 1);
|
||||
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
|
||||
return assignedChildren[mIndexInInserted - 1];
|
||||
} else if (mShadowIterator) {
|
||||
return mShadowIterator->Get();
|
||||
}
|
||||
|
||||
return mDefaultChild ? mDefaultChild : mChild;
|
||||
}
|
||||
|
||||
@@ -201,28 +234,20 @@ ExplicitChildIterator::GetPreviousChild()
|
||||
{
|
||||
// If we're already in the inserted-children array, look there first
|
||||
if (mIndexInInserted) {
|
||||
|
||||
if (mParentAsSlot) {
|
||||
const nsTArray<RefPtr<nsINode>>& assignedNodes =
|
||||
mParentAsSlot->AssignedNodes();
|
||||
|
||||
mChild = (--mIndexInInserted) ?
|
||||
assignedNodes[mIndexInInserted - 1]->AsContent() : nullptr;
|
||||
|
||||
if (!mChild) {
|
||||
mIsFirst = true;
|
||||
}
|
||||
return mChild;
|
||||
}
|
||||
|
||||
// NB: mIndexInInserted points one past the last returned child so we need
|
||||
// to look *two* indices back in order to return the previous child.
|
||||
MOZ_ASSERT(mChild->IsActiveChildrenElement());
|
||||
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
|
||||
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
|
||||
if (--mIndexInInserted) {
|
||||
return childrenElement->InsertedChild(mIndexInInserted - 1);
|
||||
return assignedChildren[mIndexInInserted - 1];
|
||||
}
|
||||
mChild = mChild->GetPreviousSibling();
|
||||
} else if (mShadowIterator) {
|
||||
nsIContent* previousChild = mShadowIterator->GetPreviousChild();
|
||||
if (previousChild) {
|
||||
return previousChild;
|
||||
}
|
||||
mShadowIterator = nullptr;
|
||||
mChild = mChild->GetPreviousSibling();
|
||||
} else if (mDefaultChild) {
|
||||
// If we're already in default content, check if there are more nodes there
|
||||
mDefaultChild = mDefaultChild->GetPreviousSibling();
|
||||
@@ -236,32 +261,35 @@ ExplicitChildIterator::GetPreviousChild()
|
||||
} else if (mChild) { // in the middle of the child list
|
||||
mChild = mChild->GetPreviousSibling();
|
||||
} else { // at the end of the child list
|
||||
// For slot parent, iterate over assigned nodes if not empty, otherwise
|
||||
// fall through and iterate over direct children (fallback content).
|
||||
if (mParentAsSlot) {
|
||||
const nsTArray<RefPtr<nsINode>>& assignedNodes =
|
||||
mParentAsSlot->AssignedNodes();
|
||||
if (!assignedNodes.IsEmpty()) {
|
||||
mIndexInInserted = assignedNodes.Length();
|
||||
mChild = assignedNodes[mIndexInInserted - 1]->AsContent();
|
||||
return mChild;
|
||||
}
|
||||
}
|
||||
|
||||
mChild = mParent->GetLastChild();
|
||||
}
|
||||
|
||||
// Iterate until we find a non-insertion point, or an insertion point with
|
||||
// content.
|
||||
while (mChild) {
|
||||
if (mChild->IsActiveChildrenElement()) {
|
||||
if (ShadowRoot::IsShadowInsertionPoint(mChild)) {
|
||||
// If the current child being iterated is a shadow insertion point then
|
||||
// the iterator needs to go into the projected ShadowRoot.
|
||||
HTMLShadowElement* shadowElem = HTMLShadowElement::FromContent(mChild);
|
||||
ShadowRoot* projectedShadow = shadowElem->GetOlderShadowRoot();
|
||||
if (projectedShadow) {
|
||||
// Create a ExplicitChildIterator that begins iterating from the end.
|
||||
mShadowIterator = new ExplicitChildIterator(projectedShadow, false);
|
||||
nsIContent* previousChild = mShadowIterator->GetPreviousChild();
|
||||
if (previousChild) {
|
||||
return previousChild;
|
||||
}
|
||||
mShadowIterator = nullptr;
|
||||
}
|
||||
mChild = mChild->GetPreviousSibling();
|
||||
} else if (nsContentUtils::IsContentInsertionPoint(mChild)) {
|
||||
// If the current child being iterated is a content insertion point
|
||||
// then the iterator needs to return the nodes distributed into
|
||||
// the content insertion point.
|
||||
auto* childrenElement = static_cast<XBLChildrenElement*>(mChild);
|
||||
if (childrenElement->HasInsertedChildren()) {
|
||||
mIndexInInserted = childrenElement->InsertedChildrenLength();
|
||||
return childrenElement->InsertedChild(mIndexInInserted - 1);
|
||||
MatchedNodes assignedChildren = GetMatchedNodesForPoint(mChild);
|
||||
if (!assignedChildren.IsEmpty()) {
|
||||
mIndexInInserted = assignedChildren.Length();
|
||||
return assignedChildren[mIndexInInserted - 1];
|
||||
}
|
||||
|
||||
mDefaultChild = mChild->GetLastChild();
|
||||
@@ -289,9 +317,11 @@ AllChildrenIterator::Get() const
|
||||
{
|
||||
switch (mPhase) {
|
||||
case eAtBeforeKid: {
|
||||
Element* before = nsLayoutUtils::GetBeforePseudo(mOriginalContent);
|
||||
MOZ_ASSERT(before, "No content before frame at eAtBeforeKid phase");
|
||||
return before;
|
||||
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
|
||||
MOZ_ASSERT(frame, "No frame at eAtBeforeKid phase");
|
||||
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
MOZ_ASSERT(beforeFrame, "No content before frame at eAtBeforeKid phase");
|
||||
return beforeFrame->GetContent();
|
||||
}
|
||||
|
||||
case eAtExplicitKids:
|
||||
@@ -301,9 +331,11 @@ AllChildrenIterator::Get() const
|
||||
return mAnonKids[mAnonKidsIdx];
|
||||
|
||||
case eAtAfterKid: {
|
||||
Element* after = nsLayoutUtils::GetAfterPseudo(mOriginalContent);
|
||||
MOZ_ASSERT(after, "No content after frame at eAtAfterKid phase");
|
||||
return after;
|
||||
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
|
||||
MOZ_ASSERT(frame, "No frame at eAtAfterKid phase");
|
||||
nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame);
|
||||
MOZ_ASSERT(afterFrame, "No content before frame at eAtBeforeKid phase");
|
||||
return afterFrame->GetContent();
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -313,14 +345,19 @@ AllChildrenIterator::Get() const
|
||||
|
||||
|
||||
bool
|
||||
AllChildrenIterator::Seek(const nsIContent* aChildToFind)
|
||||
AllChildrenIterator::Seek(nsIContent* aChildToFind)
|
||||
{
|
||||
if (mPhase == eAtBegin || mPhase == eAtBeforeKid) {
|
||||
mPhase = eAtExplicitKids;
|
||||
Element* beforePseudo = nsLayoutUtils::GetBeforePseudo(mOriginalContent);
|
||||
if (beforePseudo && beforePseudo == aChildToFind) {
|
||||
mPhase = eAtBeforeKid;
|
||||
return true;
|
||||
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
if (beforeFrame) {
|
||||
if (beforeFrame->GetContent() == aChildToFind) {
|
||||
mPhase = eAtBeforeKid;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,10 +383,12 @@ AllChildrenIterator::AppendNativeAnonymousChildren()
|
||||
|
||||
// The root scroll frame is not the primary frame of the root element.
|
||||
// Detect and handle this case.
|
||||
if (!(mFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
|
||||
mOriginalContent == mOriginalContent->OwnerDoc()->GetRootElement()) {
|
||||
nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
|
||||
mOriginalContent->OwnerDoc(), mAnonKids);
|
||||
if (mOriginalContent == mOriginalContent->OwnerDoc()->GetRootElement()) {
|
||||
nsIPresShell* presShell = mOriginalContent->OwnerDoc()->GetShell();
|
||||
nsIFrame* scrollFrame = presShell ? presShell->GetRootScrollFrame() : nullptr;
|
||||
if (scrollFrame) {
|
||||
AppendNativeAnonymousChildrenFromFrame(scrollFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,10 +406,13 @@ AllChildrenIterator::GetNextChild()
|
||||
{
|
||||
if (mPhase == eAtBegin) {
|
||||
mPhase = eAtExplicitKids;
|
||||
Element* beforeContent = nsLayoutUtils::GetBeforePseudo(mOriginalContent);
|
||||
if (beforeContent) {
|
||||
mPhase = eAtBeforeKid;
|
||||
return beforeContent;
|
||||
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
if (beforeFrame) {
|
||||
mPhase = eAtBeforeKid;
|
||||
return beforeFrame->GetContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,10 +448,13 @@ AllChildrenIterator::GetNextChild()
|
||||
return mAnonKids[mAnonKidsIdx];
|
||||
}
|
||||
|
||||
Element* afterContent = nsLayoutUtils::GetAfterPseudo(mOriginalContent);
|
||||
if (afterContent) {
|
||||
mPhase = eAtAfterKid;
|
||||
return afterContent;
|
||||
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame);
|
||||
if (afterFrame) {
|
||||
mPhase = eAtAfterKid;
|
||||
return afterFrame->GetContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,10 +468,13 @@ AllChildrenIterator::GetPreviousChild()
|
||||
if (mPhase == eAtEnd) {
|
||||
MOZ_ASSERT(mAnonKidsIdx == mAnonKids.Length());
|
||||
mPhase = eAtAnonKids;
|
||||
Element* afterContent = nsLayoutUtils::GetAfterPseudo(mOriginalContent);
|
||||
if (afterContent) {
|
||||
mPhase = eAtAfterKid;
|
||||
return afterContent;
|
||||
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(frame);
|
||||
if (afterFrame) {
|
||||
mPhase = eAtAfterKid;
|
||||
return afterFrame->GetContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,10 +503,13 @@ AllChildrenIterator::GetPreviousChild()
|
||||
return kid;
|
||||
}
|
||||
|
||||
Element* beforeContent = nsLayoutUtils::GetBeforePseudo(mOriginalContent);
|
||||
if (beforeContent) {
|
||||
mPhase = eAtBeforeKid;
|
||||
return beforeContent;
|
||||
nsIFrame* frame = mOriginalContent->GetPrimaryFrame();
|
||||
if (frame) {
|
||||
nsIFrame* beforeFrame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
if (beforeFrame) {
|
||||
mPhase = eAtBeforeKid;
|
||||
return beforeFrame->GetContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,6 +585,12 @@ StyleChildrenIterator::IsNeeded(const Element* aElement)
|
||||
return true;
|
||||
}
|
||||
|
||||
// The root element has a scroll frame that is not the primary frame, so we
|
||||
// need to do special checking for that case.
|
||||
if (aElement == aElement->OwnerDoc()->GetRootElement()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+36
-41
@@ -36,20 +36,27 @@ class ExplicitChildIterator
|
||||
{
|
||||
public:
|
||||
explicit ExplicitChildIterator(const nsIContent* aParent,
|
||||
bool aStartAtBeginning = true);
|
||||
bool aStartAtBeginning = true)
|
||||
: mParent(aParent),
|
||||
mChild(nullptr),
|
||||
mDefaultChild(nullptr),
|
||||
mIndexInInserted(0),
|
||||
mIsFirst(aStartAtBeginning)
|
||||
{
|
||||
}
|
||||
|
||||
ExplicitChildIterator(const ExplicitChildIterator& aOther)
|
||||
: mParent(aOther.mParent),
|
||||
mParentAsSlot(aOther.mParentAsSlot),
|
||||
mChild(aOther.mChild),
|
||||
: mParent(aOther.mParent), mChild(aOther.mChild),
|
||||
mDefaultChild(aOther.mDefaultChild),
|
||||
mShadowIterator(aOther.mShadowIterator ?
|
||||
new ExplicitChildIterator(*aOther.mShadowIterator) :
|
||||
nullptr),
|
||||
mIndexInInserted(aOther.mIndexInInserted), mIsFirst(aOther.mIsFirst) {}
|
||||
|
||||
ExplicitChildIterator(ExplicitChildIterator&& aOther)
|
||||
: mParent(aOther.mParent),
|
||||
mParentAsSlot(aOther.mParentAsSlot),
|
||||
mChild(aOther.mChild),
|
||||
: mParent(aOther.mParent), mChild(aOther.mChild),
|
||||
mDefaultChild(aOther.mDefaultChild),
|
||||
mShadowIterator(Move(aOther.mShadowIterator)),
|
||||
mIndexInInserted(aOther.mIndexInInserted), mIsFirst(aOther.mIsFirst) {}
|
||||
|
||||
nsIContent* GetNextChild();
|
||||
@@ -58,13 +65,13 @@ public:
|
||||
// found. This version can take shortcuts that the two-argument version
|
||||
// can't, so can be faster (and in fact can be O(1) instead of O(N) in many
|
||||
// cases).
|
||||
bool Seek(const nsIContent* aChildToFind);
|
||||
bool Seek(nsIContent* aChildToFind);
|
||||
|
||||
// Looks for aChildToFind respecting insertion points until aChildToFind is found.
|
||||
// or aBound is found. If aBound is nullptr then the seek is unbounded. Returns
|
||||
// whether aChildToFind was found as an explicit child prior to encountering
|
||||
// aBound.
|
||||
bool Seek(const nsIContent* aChildToFind, nsIContent* aBound)
|
||||
bool Seek(nsIContent* aChildToFind, nsIContent* aBound)
|
||||
{
|
||||
// It would be nice to assert that we find aChildToFind, but bz thinks that
|
||||
// we might not find aChildToFind when called from ContentInserted
|
||||
@@ -95,10 +102,6 @@ protected:
|
||||
// the <xbl:content> element for the binding.
|
||||
const nsIContent* mParent;
|
||||
|
||||
// If parent is a slot element, this points to the parent as HTMLSlotElement,
|
||||
// otherwise, it's null.
|
||||
const HTMLSlotElement* mParentAsSlot;
|
||||
|
||||
// The current child. When we encounter an insertion point,
|
||||
// mChild remains as the insertion point whose content we're iterating (and
|
||||
// our state is controled by mDefaultChild or mIndexInInserted depending on
|
||||
@@ -111,6 +114,11 @@ protected:
|
||||
// to null, we continue iterating at mChild's next sibling.
|
||||
nsIContent* mDefaultChild;
|
||||
|
||||
// If non-null, this points to an iterator of the explicit children of
|
||||
// the ShadowRoot projected by the current shadow element that we're
|
||||
// iterating.
|
||||
nsAutoPtr<ExplicitChildIterator> mShadowIterator;
|
||||
|
||||
// If not zero, we're iterating inserted children for an insertion point. This
|
||||
// is an index into mChild's inserted children array (mChild must be an
|
||||
// nsXBLChildrenElement). The index is one past the "current" child (as
|
||||
@@ -131,29 +139,19 @@ class FlattenedChildIterator : public ExplicitChildIterator
|
||||
public:
|
||||
explicit FlattenedChildIterator(const nsIContent* aParent,
|
||||
bool aStartAtBeginning = true)
|
||||
: ExplicitChildIterator(aParent, aStartAtBeginning)
|
||||
, mXBLInvolved(false)
|
||||
, mOriginalContent(aParent)
|
||||
: ExplicitChildIterator(aParent, aStartAtBeginning), mXBLInvolved(false)
|
||||
{
|
||||
Init(false);
|
||||
}
|
||||
|
||||
FlattenedChildIterator(FlattenedChildIterator&& aOther)
|
||||
: ExplicitChildIterator(Move(aOther))
|
||||
, mXBLInvolved(aOther.mXBLInvolved)
|
||||
, mOriginalContent(aOther.mOriginalContent)
|
||||
{}
|
||||
: ExplicitChildIterator(Move(aOther)), mXBLInvolved(aOther.mXBLInvolved) {}
|
||||
|
||||
FlattenedChildIterator(const FlattenedChildIterator& aOther)
|
||||
: ExplicitChildIterator(aOther)
|
||||
, mXBLInvolved(aOther.mXBLInvolved)
|
||||
, mOriginalContent(aOther.mOriginalContent)
|
||||
{}
|
||||
: ExplicitChildIterator(aOther), mXBLInvolved(aOther.mXBLInvolved) {}
|
||||
|
||||
bool XBLInvolved() { return mXBLInvolved; }
|
||||
|
||||
const nsIContent* Parent() const { return mOriginalContent; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* This constructor is a hack to help AllChildrenIterator which sometimes
|
||||
@@ -161,9 +159,7 @@ protected:
|
||||
*/
|
||||
FlattenedChildIterator(const nsIContent* aParent, uint32_t aFlags,
|
||||
bool aStartAtBeginning = true)
|
||||
: ExplicitChildIterator(aParent, aStartAtBeginning)
|
||||
, mXBLInvolved(false)
|
||||
, mOriginalContent(aParent)
|
||||
: ExplicitChildIterator(aParent, aStartAtBeginning), mXBLInvolved(false)
|
||||
{
|
||||
bool ignoreXBL = aFlags & nsIContent::eAllButXBL;
|
||||
Init(ignoreXBL);
|
||||
@@ -174,8 +170,6 @@ protected:
|
||||
// For certain optimizations, nsCSSFrameConstructor needs to know if the
|
||||
// child list of the element that we're iterating matches its .childNodes.
|
||||
bool mXBLInvolved;
|
||||
|
||||
const nsIContent* mOriginalContent;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -193,11 +187,12 @@ public:
|
||||
AllChildrenIterator(const nsIContent* aNode, uint32_t aFlags,
|
||||
bool aStartAtBeginning = true) :
|
||||
FlattenedChildIterator(aNode, aFlags, aStartAtBeginning),
|
||||
mAnonKidsIdx(aStartAtBeginning ? UINT32_MAX : 0),
|
||||
mOriginalContent(aNode), mAnonKidsIdx(aStartAtBeginning ? UINT32_MAX : 0),
|
||||
mFlags(aFlags), mPhase(aStartAtBeginning ? eAtBegin : eAtEnd) { }
|
||||
|
||||
AllChildrenIterator(AllChildrenIterator&& aOther)
|
||||
: FlattenedChildIterator(Move(aOther)),
|
||||
mOriginalContent(aOther.mOriginalContent),
|
||||
mAnonKids(Move(aOther.mAnonKids)), mAnonKidsIdx(aOther.mAnonKidsIdx),
|
||||
mFlags(aOther.mFlags), mPhase(aOther.mPhase)
|
||||
#ifdef DEBUG
|
||||
@@ -216,10 +211,11 @@ public:
|
||||
// Seeks the given node in children of a parent element, starting from
|
||||
// the current iterator's position, and sets the iterator at the given child
|
||||
// node if it was found.
|
||||
bool Seek(const nsIContent* aChildToFind);
|
||||
bool Seek(nsIContent* aChildToFind);
|
||||
|
||||
nsIContent* GetNextChild();
|
||||
nsIContent* GetPreviousChild();
|
||||
const nsIContent* Parent() const { return mOriginalContent; }
|
||||
|
||||
enum IteratorPhase
|
||||
{
|
||||
@@ -237,6 +233,8 @@ private:
|
||||
void AppendNativeAnonymousChildren();
|
||||
void AppendNativeAnonymousChildrenFromFrame(nsIFrame* aFrame);
|
||||
|
||||
const nsIContent* mOriginalContent;
|
||||
|
||||
// mAnonKids is an array of native anonymous children, mAnonKidsIdx is index
|
||||
// in the array. If mAnonKidsIdx < mAnonKids.Length() and mPhase is
|
||||
// eAtAnonKids then the iterator points at a child at mAnonKidsIdx index. If
|
||||
@@ -258,11 +256,10 @@ private:
|
||||
/**
|
||||
* StyleChildrenIterator traverses the children of the element from the
|
||||
* perspective of the style system, particularly the children we need to traverse
|
||||
* during restyle. This is identical to AllChildrenIterator with
|
||||
* (eAllChildren | eSkipDocumentLevelNativeAnonymousContent), _except_ that we
|
||||
* detect and skip any native anonymous children that are used to implement
|
||||
* pseudo-elements (since the style system needs to cascade those using
|
||||
* different algorithms).
|
||||
* during restyle. This is identical to AllChildrenIterator with eAllChildren,
|
||||
* _except_ that we detect and skip any native anonymous children that are used
|
||||
* to implement pseudo-elements (since the style system needs to cascade those
|
||||
* using different algorithms).
|
||||
*
|
||||
* Note: it assumes that no mutation of the DOM or frame tree takes place during
|
||||
* iteration, and will break horribly if that is not true.
|
||||
@@ -270,9 +267,7 @@ private:
|
||||
class StyleChildrenIterator : private AllChildrenIterator {
|
||||
public:
|
||||
explicit StyleChildrenIterator(const nsIContent* aContent)
|
||||
: AllChildrenIterator(aContent,
|
||||
nsIContent::eAllChildren |
|
||||
nsIContent::eSkipDocumentLevelNativeAnonymousContent)
|
||||
: AllChildrenIterator(aContent, nsIContent::eAllChildren)
|
||||
{
|
||||
MOZ_COUNT_CTOR(StyleChildrenIterator);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "mozilla/dom/ChromeNodeList.h"
|
||||
#include "mozilla/dom/ChromeNodeListBinding.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
|
||||
+354
-675
File diff suppressed because it is too large.
Load diff
@@ -7,16 +7,13 @@
|
||||
#ifndef mozilla_dom_CustomElementRegistry_h
|
||||
#define mozilla_dom_CustomElementRegistry_h
|
||||
|
||||
#include "js/GCHashTable.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
#include "mozilla/dom/WebComponentsBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsGenericHTMLElement.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/dom/FunctionBinding.h"
|
||||
|
||||
class nsDocument;
|
||||
|
||||
@@ -25,9 +22,8 @@ namespace dom {
|
||||
|
||||
struct CustomElementData;
|
||||
struct ElementDefinitionOptions;
|
||||
struct LifecycleCallbacks;
|
||||
class CallbackFunction;
|
||||
class CustomElementReaction;
|
||||
class DocGroup;
|
||||
class Function;
|
||||
class Promise;
|
||||
|
||||
@@ -36,13 +32,6 @@ struct LifecycleCallbackArgs
|
||||
nsString name;
|
||||
nsString oldValue;
|
||||
nsString newValue;
|
||||
nsString namespaceURI;
|
||||
};
|
||||
|
||||
struct LifecycleAdoptedCallbackArgs
|
||||
{
|
||||
nsCOMPtr<nsIDocument> mOldDocument;
|
||||
nsCOMPtr<nsIDocument> mNewDocument;
|
||||
};
|
||||
|
||||
class CustomElementCallback
|
||||
@@ -50,7 +39,8 @@ class CustomElementCallback
|
||||
public:
|
||||
CustomElementCallback(Element* aThisObject,
|
||||
nsIDocument::ElementCallbackType aCallbackType,
|
||||
CallbackFunction* aCallback);
|
||||
CallbackFunction* aCallback,
|
||||
CustomElementData* aOwnerData);
|
||||
void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
|
||||
void Call();
|
||||
void SetArgs(LifecycleCallbackArgs& aArgs)
|
||||
@@ -60,13 +50,6 @@ public:
|
||||
mArgs = aArgs;
|
||||
}
|
||||
|
||||
void SetAdoptedCallbackArgs(LifecycleAdoptedCallbackArgs& aAdoptedCallbackArgs)
|
||||
{
|
||||
MOZ_ASSERT(mType == nsIDocument::eAdopted,
|
||||
"Arguments are only used by adopted callback.");
|
||||
mAdoptedCallbackArgs = aAdoptedCallbackArgs;
|
||||
}
|
||||
|
||||
private:
|
||||
// The this value to use for invocation of the callback.
|
||||
RefPtr<Element> mThisObject;
|
||||
@@ -76,19 +59,9 @@ private:
|
||||
// Arguments to be passed to the callback,
|
||||
// used by the attribute changed callback.
|
||||
LifecycleCallbackArgs mArgs;
|
||||
LifecycleAdoptedCallbackArgs mAdoptedCallbackArgs;
|
||||
};
|
||||
|
||||
class CustomElementConstructor final : public CallbackFunction
|
||||
{
|
||||
public:
|
||||
explicit CustomElementConstructor(CallbackFunction* aOther)
|
||||
: CallbackFunction(aOther)
|
||||
{
|
||||
MOZ_ASSERT(JS::IsConstructor(mCallback));
|
||||
}
|
||||
|
||||
already_AddRefed<Element> Construct(const char* aExecutionReason, ErrorResult& aRv);
|
||||
// CustomElementData that contains this callback in the
|
||||
// callback queue.
|
||||
CustomElementData* mOwnerData;
|
||||
};
|
||||
|
||||
// Each custom element has an associated callback queue and an element is
|
||||
@@ -97,299 +70,63 @@ struct CustomElementData
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(CustomElementData)
|
||||
|
||||
// https://dom.spec.whatwg.org/#concept-element-custom-element-state
|
||||
// CustomElementData is only created on the element which is a custom element
|
||||
// or an upgrade candidate, so the state of an element without
|
||||
// CustomElementData is "uncustomized".
|
||||
enum class State {
|
||||
eUndefined,
|
||||
eFailed,
|
||||
eCustom
|
||||
};
|
||||
|
||||
explicit CustomElementData(nsIAtom* aType);
|
||||
CustomElementData(nsIAtom* aType, State aState);
|
||||
// Objects in this array are transient and empty after each microtask
|
||||
// checkpoint.
|
||||
nsTArray<nsAutoPtr<CustomElementCallback>> mCallbackQueue;
|
||||
// Custom element type, for <button is="x-button"> or <x-button>
|
||||
// this would be x-button.
|
||||
nsCOMPtr<nsIAtom> mType;
|
||||
// The callback that is next to be processed upon calling RunCallbackQueue.
|
||||
int32_t mCurrentCallback;
|
||||
// Element is being created flag as described in the custom elements spec.
|
||||
bool mElementIsBeingCreated;
|
||||
// Flag to determine if the created callback has been invoked, thus it
|
||||
// determines if other callbacks can be enqueued.
|
||||
bool mCreatedCallbackInvoked;
|
||||
// The microtask level associated with the callbacks in the callback queue,
|
||||
// it is used to determine if a new queue needs to be pushed onto the
|
||||
// processing stack.
|
||||
int32_t mAssociatedMicroTask;
|
||||
|
||||
// Custom element state as described in the custom element spec.
|
||||
State mState;
|
||||
// custom element reaction queue as described in the custom element spec.
|
||||
// There is 1 reaction in reaction queue, when 1) it becomes disconnected,
|
||||
// 2) it’s adopted into a new document, 3) its attributes are changed,
|
||||
// appended, removed, or replaced.
|
||||
// There are 3 reactions in reaction queue when doing upgrade operation,
|
||||
// e.g., create an element, insert a node.
|
||||
AutoTArray<UniquePtr<CustomElementReaction>, 3> mReactionQueue;
|
||||
|
||||
void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
|
||||
CustomElementDefinition* GetCustomElementDefinition();
|
||||
nsIAtom* GetCustomElementType();
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback& aCb) const;
|
||||
void Unlink();
|
||||
// Empties the callback queue.
|
||||
void RunCallbackQueue();
|
||||
|
||||
private:
|
||||
virtual ~CustomElementData() {}
|
||||
|
||||
// Custom element type, for <button is="x-button"> or <x-button>
|
||||
// this would be x-button.
|
||||
RefPtr<nsIAtom> mType;
|
||||
RefPtr<CustomElementDefinition> mCustomElementDefinition;
|
||||
};
|
||||
|
||||
#define ALEADY_CONSTRUCTED_MARKER nullptr
|
||||
|
||||
// The required information for a custom element as defined in:
|
||||
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-definition
|
||||
struct CustomElementDefinition
|
||||
{
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CustomElementDefinition)
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CustomElementDefinition)
|
||||
|
||||
CustomElementDefinition(nsIAtom* aType,
|
||||
nsIAtom* aLocalName,
|
||||
Function* aConstructor,
|
||||
nsCOMArray<nsIAtom>&& aObservedAttributes,
|
||||
JSObject* aConstructor,
|
||||
JSObject* aPrototype,
|
||||
mozilla::dom::LifecycleCallbacks* aCallbacks,
|
||||
uint32_t aDocOrder);
|
||||
|
||||
// The type (name) for this custom element, for <button is="x-foo"> or <x-foo>
|
||||
// this would be x-foo.
|
||||
// The type (name) for this custom element.
|
||||
nsCOMPtr<nsIAtom> mType;
|
||||
|
||||
// The localname to (e.g. <button is=type> -- this would be button).
|
||||
nsCOMPtr<nsIAtom> mLocalName;
|
||||
|
||||
// The custom element constructor.
|
||||
RefPtr<CustomElementConstructor> mConstructor;
|
||||
|
||||
// The list of attributes that this custom element observes.
|
||||
nsCOMArray<nsIAtom> mObservedAttributes;
|
||||
JS::Heap<JSObject *> mConstructor;
|
||||
|
||||
// The prototype to use for new custom elements of this type.
|
||||
JS::Heap<JSObject *> mPrototype;
|
||||
|
||||
// The lifecycle callbacks to call for this custom element.
|
||||
UniquePtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
|
||||
nsAutoPtr<mozilla::dom::LifecycleCallbacks> mCallbacks;
|
||||
|
||||
// A construction stack. Use nullptr to represent an "already constructed marker".
|
||||
nsTArray<RefPtr<nsGenericHTMLElement>> mConstructionStack;
|
||||
// A construction stack.
|
||||
// TODO: Bug 1287348 - Implement construction stack for upgrading an element
|
||||
|
||||
// The document custom element order.
|
||||
uint32_t mDocOrder;
|
||||
|
||||
bool IsCustomBuiltIn()
|
||||
{
|
||||
return mType != mLocalName;
|
||||
}
|
||||
|
||||
bool IsInObservedAttributeList(nsIAtom* aName)
|
||||
{
|
||||
if (mObservedAttributes.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mObservedAttributes.Contains(aName);
|
||||
}
|
||||
|
||||
private:
|
||||
~CustomElementDefinition() {}
|
||||
};
|
||||
|
||||
class CustomElementReaction
|
||||
{
|
||||
public:
|
||||
virtual ~CustomElementReaction() = default;
|
||||
virtual void Invoke(Element* aElement, ErrorResult& aRv) = 0;
|
||||
virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const
|
||||
{
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
bool IsUpgradeReaction()
|
||||
{
|
||||
return mIsUpgradeReaction;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool mIsUpgradeReaction = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
class CustomElementUpgradeReaction final : public CustomElementReaction
|
||||
{
|
||||
public:
|
||||
explicit CustomElementUpgradeReaction(CustomElementDefinition* aDefinition)
|
||||
: mDefinition(aDefinition)
|
||||
{
|
||||
#if DEBUG
|
||||
mIsUpgradeReaction = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void Invoke(Element* aElement, ErrorResult& aRv) override;
|
||||
|
||||
CustomElementDefinition* mDefinition;
|
||||
};
|
||||
|
||||
class CustomElementCallbackReaction final : public CustomElementReaction
|
||||
{
|
||||
public:
|
||||
explicit CustomElementCallbackReaction(UniquePtr<CustomElementCallback> aCustomElementCallback)
|
||||
: mCustomElementCallback(Move(aCustomElementCallback))
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Traverse(nsCycleCollectionTraversalCallback& aCb) const override
|
||||
{
|
||||
mCustomElementCallback->Traverse(aCb);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void Invoke(Element* aElement, ErrorResult& aRv) override;
|
||||
UniquePtr<CustomElementCallback> mCustomElementCallback;
|
||||
};
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/scripting.html#custom-element-reactions-stack
|
||||
class CustomElementReactionsStack
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(CustomElementReactionsStack)
|
||||
|
||||
CustomElementReactionsStack()
|
||||
: mIsBackupQueueProcessing(false)
|
||||
, mRecursionDepth(0)
|
||||
, mIsElementQueuePushedForCurrentRecursionDepth(false)
|
||||
{
|
||||
}
|
||||
|
||||
// Hold a strong reference of Element so that it does not get cycle collected
|
||||
// before the reactions in its reaction queue are invoked.
|
||||
// The element reaction queues are stored in CustomElementData.
|
||||
// We need to lookup ElementReactionQueueMap again to get relevant reaction queue.
|
||||
// The choice of 1 for the auto size here is based on gut feeling.
|
||||
typedef AutoTArray<RefPtr<Element>, 1> ElementQueue;
|
||||
|
||||
/**
|
||||
* Enqueue a custom element upgrade reaction
|
||||
* https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction
|
||||
*/
|
||||
void EnqueueUpgradeReaction(Element* aElement,
|
||||
CustomElementDefinition* aDefinition);
|
||||
|
||||
/**
|
||||
* Enqueue a custom element callback reaction
|
||||
* https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-callback-reaction
|
||||
*/
|
||||
void EnqueueCallbackReaction(Element* aElement,
|
||||
UniquePtr<CustomElementCallback> aCustomElementCallback);
|
||||
|
||||
/**
|
||||
* [CEReactions] Before executing the algorithm's steps.
|
||||
* Increase the current recursion depth, and the element queue is pushed
|
||||
* lazily when we really enqueue reactions.
|
||||
*
|
||||
* @return true if the element queue is pushed for "previous" recursion depth.
|
||||
*/
|
||||
bool EnterCEReactions()
|
||||
{
|
||||
bool temp = mIsElementQueuePushedForCurrentRecursionDepth;
|
||||
mRecursionDepth++;
|
||||
// The is-element-queue-pushed flag is initially false when entering a new
|
||||
// recursion level. The original value will be cached in AutoCEReaction
|
||||
// and restored after leaving this recursion level.
|
||||
mIsElementQueuePushedForCurrentRecursionDepth = false;
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* [CEReactions] After executing the algorithm's steps.
|
||||
* Pop and invoke the element queue if it is created and pushed for current
|
||||
* recursion depth, then decrease the current recursion depth.
|
||||
*
|
||||
* @param aCx JSContext used for handling exception thrown by algorithm's
|
||||
* steps, this could be a nullptr.
|
||||
* aWasElementQueuePushed used for restoring status after leaving
|
||||
* current recursion.
|
||||
*/
|
||||
void LeaveCEReactions(JSContext* aCx, bool aWasElementQueuePushed)
|
||||
{
|
||||
MOZ_ASSERT(mRecursionDepth);
|
||||
|
||||
if (mIsElementQueuePushedForCurrentRecursionDepth) {
|
||||
Maybe<JS::AutoSaveExceptionState> ases;
|
||||
if (aCx) {
|
||||
ases.emplace(aCx);
|
||||
}
|
||||
PopAndInvokeElementQueue();
|
||||
}
|
||||
mRecursionDepth--;
|
||||
// Restore the is-element-queue-pushed flag cached in AutoCEReaction when
|
||||
// leaving the recursion level.
|
||||
mIsElementQueuePushedForCurrentRecursionDepth = aWasElementQueuePushed;
|
||||
|
||||
MOZ_ASSERT_IF(!mRecursionDepth, mReactionsStack.IsEmpty());
|
||||
}
|
||||
|
||||
private:
|
||||
~CustomElementReactionsStack() {};
|
||||
|
||||
/**
|
||||
* Push a new element queue onto the custom element reactions stack.
|
||||
*/
|
||||
void CreateAndPushElementQueue();
|
||||
|
||||
/**
|
||||
* Pop the element queue from the custom element reactions stack, and invoke
|
||||
* custom element reactions in that queue.
|
||||
*/
|
||||
void PopAndInvokeElementQueue();
|
||||
|
||||
// The choice of 8 for the auto size here is based on gut feeling.
|
||||
AutoTArray<UniquePtr<ElementQueue>, 8> mReactionsStack;
|
||||
ElementQueue mBackupQueue;
|
||||
// https://html.spec.whatwg.org/#enqueue-an-element-on-the-appropriate-element-queue
|
||||
bool mIsBackupQueueProcessing;
|
||||
|
||||
void InvokeBackupQueue();
|
||||
|
||||
/**
|
||||
* Invoke custom element reactions
|
||||
* https://html.spec.whatwg.org/multipage/scripting.html#invoke-custom-element-reactions
|
||||
*/
|
||||
void InvokeReactions(ElementQueue* aElementQueue, nsIGlobalObject* aGlobal);
|
||||
|
||||
void Enqueue(Element* aElement, CustomElementReaction* aReaction);
|
||||
|
||||
// Current [CEReactions] recursion depth.
|
||||
uint32_t mRecursionDepth;
|
||||
// True if the element queue is pushed into reaction stack for current
|
||||
// recursion depth. This will be cached in AutoCEReaction when entering a new
|
||||
// CEReaction recursion and restored after leaving the recursion.
|
||||
bool mIsElementQueuePushedForCurrentRecursionDepth;
|
||||
|
||||
private:
|
||||
class BackupQueueMicroTask final : public mozilla::MicroTaskRunnable {
|
||||
public:
|
||||
explicit BackupQueueMicroTask(CustomElementReactionsStack* aReactionStack)
|
||||
: MicroTaskRunnable()
|
||||
, mReactionStack(aReactionStack)
|
||||
{
|
||||
MOZ_ASSERT(!mReactionStack->mIsBackupQueueProcessing,
|
||||
"mIsBackupQueueProcessing should be initially false");
|
||||
mReactionStack->mIsBackupQueueProcessing = true;
|
||||
}
|
||||
|
||||
virtual void Run(AutoSlowOperation& aAso) override
|
||||
{
|
||||
mReactionStack->InvokeBackupQueue();
|
||||
mReactionStack->mIsBackupQueueProcessing = false;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<CustomElementReactionsStack> mReactionStack;
|
||||
};
|
||||
};
|
||||
|
||||
class CustomElementRegistry final : public nsISupports,
|
||||
@@ -405,34 +142,41 @@ public:
|
||||
public:
|
||||
static bool IsCustomElementEnabled(JSContext* aCx = nullptr,
|
||||
JSObject* aObject = nullptr);
|
||||
static already_AddRefed<CustomElementRegistry> Create(nsPIDOMWindowInner* aWindow);
|
||||
static void ProcessTopElementQueue();
|
||||
|
||||
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
|
||||
static void XPCOMShutdown();
|
||||
|
||||
/**
|
||||
* Looking up a custom element definition.
|
||||
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
|
||||
*/
|
||||
CustomElementDefinition* LookupCustomElementDefinition(
|
||||
nsIAtom* aNameAtom, nsIAtom* aTypeAtom) const;
|
||||
|
||||
CustomElementDefinition* LookupCustomElementDefinition(
|
||||
JSContext* aCx, JSObject *aConstructor) const;
|
||||
|
||||
static void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs,
|
||||
LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
|
||||
CustomElementDefinition* aDefinition);
|
||||
const nsAString& aLocalName, const nsAString* aIs = nullptr) const;
|
||||
|
||||
/**
|
||||
* Upgrade an element.
|
||||
* https://html.spec.whatwg.org/multipage/scripting.html#upgrades
|
||||
* Enqueue created callback or register upgrade candidate for
|
||||
* newly created custom elements, possibly extending an existing type.
|
||||
* ex. <x-button>, <button is="x-button> (type extension)
|
||||
*/
|
||||
static void Upgrade(Element* aElement, CustomElementDefinition* aDefinition, ErrorResult& aRv);
|
||||
void SetupCustomElement(Element* aElement, const nsAString* aTypeExtension);
|
||||
|
||||
void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs,
|
||||
CustomElementDefinition* aDefinition);
|
||||
|
||||
void GetCustomPrototype(nsIAtom* aAtom,
|
||||
JS::MutableHandle<JSObject*> aPrototype);
|
||||
|
||||
private:
|
||||
explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
|
||||
~CustomElementRegistry();
|
||||
|
||||
/**
|
||||
* Registers an unresolved custom element that is a candidate for
|
||||
* upgrade. |aTypeName| is the name of the custom element type, if it is not
|
||||
* upgrade when the definition is registered via registerElement.
|
||||
* |aTypeName| is the name of the custom element type, if it is not
|
||||
* provided, then element name is used. |aTypeName| should be provided
|
||||
* when registering a custom element that extends an existing
|
||||
* element. e.g. <button is="x-button">.
|
||||
@@ -440,48 +184,23 @@ public:
|
||||
void RegisterUnresolvedElement(Element* aElement,
|
||||
nsIAtom* aTypeName = nullptr);
|
||||
|
||||
/**
|
||||
* Unregister an unresolved custom element that is a candidate for
|
||||
* upgrade when a custom element is removed from tree.
|
||||
*/
|
||||
void UnregisterUnresolvedElement(Element* aElement,
|
||||
nsIAtom* aTypeName = nullptr);
|
||||
private:
|
||||
~CustomElementRegistry();
|
||||
void UpgradeCandidates(JSContext* aCx,
|
||||
nsIAtom* aKey,
|
||||
CustomElementDefinition* aDefinition);
|
||||
|
||||
static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
|
||||
nsIDocument::ElementCallbackType aType, Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs,
|
||||
LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
|
||||
CustomElementDefinition* aDefinition);
|
||||
|
||||
void UpgradeCandidates(nsIAtom* aKey,
|
||||
CustomElementDefinition* aDefinition,
|
||||
ErrorResult& aRv);
|
||||
|
||||
typedef nsRefPtrHashtable<nsISupportsHashKey, CustomElementDefinition>
|
||||
typedef nsClassHashtable<nsISupportsHashKey, CustomElementDefinition>
|
||||
DefinitionMap;
|
||||
typedef nsClassHashtable<nsISupportsHashKey, nsTArray<nsWeakPtr>>
|
||||
CandidateMap;
|
||||
typedef JS::GCHashMap<JS::Heap<JSObject*>,
|
||||
nsCOMPtr<nsIAtom>,
|
||||
js::MovableCellHasher<JS::Heap<JSObject*>>,
|
||||
js::SystemAllocPolicy> ConstructorMap;
|
||||
|
||||
// Hashtable for custom element definitions in web components.
|
||||
// Custom prototypes are stored in the compartment where definition was
|
||||
// defined.
|
||||
// Custom prototypes are stored in the compartment where
|
||||
// registerElement was called.
|
||||
DefinitionMap mCustomDefinitions;
|
||||
|
||||
// Hashtable for looking up definitions by using constructor as key.
|
||||
// Custom elements' name are stored here and we need to lookup
|
||||
// mCustomDefinitions again to get definitions.
|
||||
ConstructorMap mConstructors;
|
||||
|
||||
typedef nsRefPtrHashtable<nsISupportsHashKey, Promise>
|
||||
WhenDefinedPromiseMap;
|
||||
WhenDefinedPromiseMap mWhenDefinedPromiseMap;
|
||||
|
||||
// The "upgrade candidates map" from the web components spec. Maps from a
|
||||
// namespace id and local name to a list of elements to upgrade if that
|
||||
// element is registered as a custom element.
|
||||
@@ -489,6 +208,14 @@ private:
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mWindow;
|
||||
|
||||
// Array representing the processing stack in the custom elements
|
||||
// specification. The processing stack is conceptually a stack of
|
||||
// element queues. Each queue is represented by a sequence of
|
||||
// CustomElementData in this array, separated by nullptr that
|
||||
// represent the boundaries of the items in the stack. The first
|
||||
// queue in the stack is the base element queue.
|
||||
static mozilla::Maybe<nsTArray<RefPtr<CustomElementData>>> sProcessingStack;
|
||||
|
||||
// It is used to prevent reentrant invocations of element definition.
|
||||
bool mIsCustomDefinitionRunning;
|
||||
|
||||
@@ -514,8 +241,6 @@ private:
|
||||
public:
|
||||
nsISupports* GetParentObject() const;
|
||||
|
||||
DocGroup* GetDocGroup() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
void Define(const nsAString& aName, Function& aFunctionConstructor,
|
||||
@@ -527,31 +252,6 @@ public:
|
||||
already_AddRefed<Promise> WhenDefined(const nsAString& aName, ErrorResult& aRv);
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoCEReaction final {
|
||||
public:
|
||||
// JSContext is allowed to be a nullptr if we are guaranteeing that we're
|
||||
// not doing something that might throw but not finish reporting a JS
|
||||
// exception during the lifetime of the AutoCEReaction.
|
||||
AutoCEReaction(CustomElementReactionsStack* aReactionsStack, JSContext* aCx)
|
||||
: mReactionsStack(aReactionsStack)
|
||||
, mCx(aCx)
|
||||
{
|
||||
mIsElementQueuePushedForPreviousRecursionDepth =
|
||||
mReactionsStack->EnterCEReactions();
|
||||
}
|
||||
|
||||
~AutoCEReaction()
|
||||
{
|
||||
mReactionsStack->LeaveCEReactions(
|
||||
mCx, mIsElementQueuePushedForPreviousRecursionDepth);
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<CustomElementReactionsStack> mReactionsStack;
|
||||
JSContext* mCx;
|
||||
bool mIsElementQueuePushedForPreviousRecursionDepth;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
@@ -728,7 +728,7 @@ WalkDescendantsResetAutoDirection(Element* aElement)
|
||||
{
|
||||
nsIContent* child = aElement->GetFirstChild();
|
||||
while (child) {
|
||||
if (child->IsElement() && child->AsElement()->HasDirAuto()) {
|
||||
if (child->HasDirAuto()) {
|
||||
child = child->GetNextNonChildNode(aElement);
|
||||
continue;
|
||||
}
|
||||
@@ -791,7 +791,7 @@ WalkDescendantsClearAncestorDirAuto(Element* aElement)
|
||||
{
|
||||
nsIContent* child = aElement->GetFirstChild();
|
||||
while (child) {
|
||||
if (child->IsElement() && child->AsElement()->HasDirAuto()) {
|
||||
if (child->HasDirAuto()) {
|
||||
child = child->GetNextNonChildNode(aElement);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
/* 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/DocGroup.h"
|
||||
#include "mozilla/dom/TabGroup.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
@@ -10,14 +6,11 @@
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsDOMMutationObserver.h"
|
||||
#include "nsNetCID.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
AutoTArray<RefPtr<DocGroup>, 2>* DocGroup::sPendingDocGroups = nullptr;
|
||||
|
||||
/* static */ void
|
||||
DocGroup::GetKey(nsIPrincipal* aPrincipal, nsACString& aKey)
|
||||
{
|
||||
@@ -54,31 +47,10 @@ DocGroup::DocGroup(TabGroup* aTabGroup, const nsACString& aKey)
|
||||
DocGroup::~DocGroup()
|
||||
{
|
||||
MOZ_ASSERT(mDocuments.IsEmpty());
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_ReleaseOnMainThread(mReactionsStack.forget());
|
||||
}
|
||||
mTabGroup->mDocGroups.RemoveEntry(mKey);
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(DocGroup, nsISupports)
|
||||
|
||||
void
|
||||
DocGroup::SignalSlotChange(const HTMLSlotElement* aSlot)
|
||||
{
|
||||
if (mSignalSlotList.Contains(aSlot)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSignalSlotList.AppendElement(const_cast<HTMLSlotElement*>(aSlot));
|
||||
|
||||
if (!sPendingDocGroups) {
|
||||
// Queue a mutation observer compound microtask.
|
||||
nsDOMMutationObserver::QueueMutationObserverMicroTask();
|
||||
sPendingDocGroups = new AutoTArray<RefPtr<DocGroup>, 2>;
|
||||
}
|
||||
|
||||
sPendingDocGroups->AppendElement(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+1
-29
@@ -7,6 +7,7 @@
|
||||
#ifndef DocGroup_h
|
||||
#define DocGroup_h
|
||||
|
||||
#include "nsIDocument.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsIPrincipal.h"
|
||||
@@ -14,8 +15,6 @@
|
||||
#include "nsString.h"
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/dom/CustomElementRegistry.h"
|
||||
#include "mozilla/dom/HTMLSlotElement.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@@ -54,14 +53,6 @@ public:
|
||||
{
|
||||
return mTabGroup;
|
||||
}
|
||||
mozilla::dom::CustomElementReactionsStack* CustomElementReactionsStack()
|
||||
{
|
||||
if (!mReactionsStack) {
|
||||
mReactionsStack = new mozilla::dom::CustomElementReactionsStack();
|
||||
}
|
||||
|
||||
return mReactionsStack;
|
||||
}
|
||||
void RemoveDocument(nsIDocument* aWindow);
|
||||
|
||||
// Iterators for iterating over every document within the DocGroup
|
||||
@@ -74,23 +65,6 @@ public:
|
||||
return mDocuments.end();
|
||||
}
|
||||
|
||||
// Append aSlot to the list of signal slot list, if it's not in it already
|
||||
// list, and queue a mutation observer microtask.
|
||||
void SignalSlotChange(const mozilla::dom::HTMLSlotElement* aSlot);
|
||||
|
||||
const nsTArray<RefPtr<HTMLSlotElement>>& SignalSlotList() const
|
||||
{
|
||||
return mSignalSlotList;
|
||||
}
|
||||
|
||||
void ClearSignalSlotList()
|
||||
{
|
||||
mSignalSlotList.Clear();
|
||||
}
|
||||
|
||||
// List of DocGroups that has non-empty signal slot list.
|
||||
static AutoTArray<RefPtr<DocGroup>, 2>* sPendingDocGroups;
|
||||
|
||||
private:
|
||||
DocGroup(TabGroup* aTabGroup, const nsACString& aKey);
|
||||
~DocGroup();
|
||||
@@ -98,8 +72,6 @@ private:
|
||||
nsCString mKey;
|
||||
RefPtr<TabGroup> mTabGroup;
|
||||
nsTArray<nsIDocument*> mDocuments;
|
||||
RefPtr<mozilla::dom::CustomElementReactionsStack> mReactionsStack;
|
||||
nsTArray<RefPtr<HTMLSlotElement>> mSignalSlotList;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -125,8 +125,6 @@ DocumentFragment::Constructor(const GlobalObject& aGlobal,
|
||||
return window->GetDoc()->CreateDocumentFragment();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(DocumentFragment, FragmentOrElement, mHost)
|
||||
|
||||
// QueryInterface implementation for DocumentFragment
|
||||
NS_INTERFACE_MAP_BEGIN(DocumentFragment)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
|
||||
@@ -43,7 +43,6 @@ public:
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DocumentFragment, FragmentOrElement)
|
||||
|
||||
// interface nsIDOMNode
|
||||
NS_FORWARD_NSIDOMNODE_TO_NSINODE
|
||||
@@ -122,9 +121,15 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Element* GetHost() const { return mHost; }
|
||||
nsIContent* GetHost() const
|
||||
{
|
||||
return mHost;
|
||||
}
|
||||
|
||||
void SetHost(Element* aHost) { mHost = aHost; }
|
||||
void SetHost(nsIContent* aHost)
|
||||
{
|
||||
mHost = aHost;
|
||||
}
|
||||
|
||||
static already_AddRefed<DocumentFragment>
|
||||
Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
|
||||
@@ -140,7 +145,7 @@ protected:
|
||||
}
|
||||
|
||||
nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
||||
nsCOMPtr<Element> mHost;
|
||||
nsIContent* mHost; // Weak
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -1,149 +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 "DocumentOrShadowRoot.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "nsDocument.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "ShadowRoot.h"
|
||||
#include "XULDocument.h"
|
||||
|
||||
class nsINode;
|
||||
class nsIDocument;
|
||||
class ShadowRoot;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
DocumentOrShadowRoot::DocumentOrShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot)
|
||||
: mAsNode(aShadowRoot)
|
||||
, mKind(Kind::ShadowRoot)
|
||||
{
|
||||
MOZ_ASSERT(mAsNode);
|
||||
}
|
||||
|
||||
DocumentOrShadowRoot::DocumentOrShadowRoot(nsIDocument* aDoc)
|
||||
: mAsNode(aDoc)
|
||||
, mKind(Kind::Document)
|
||||
{
|
||||
MOZ_ASSERT(mAsNode);
|
||||
}
|
||||
|
||||
StyleSheetList&
|
||||
DocumentOrShadowRoot::EnsureDOMStyleSheets()
|
||||
{
|
||||
if (!mDOMStyleSheets) {
|
||||
mDOMStyleSheets = new StyleSheetList(*this);
|
||||
}
|
||||
return *mDOMStyleSheets;
|
||||
}
|
||||
|
||||
Element*
|
||||
DocumentOrShadowRoot::GetElementById(const nsAString& aElementId)
|
||||
{
|
||||
if (MOZ_UNLIKELY(aElementId.IsEmpty())) {
|
||||
nsContentUtils::ReportEmptyGetElementByIdArg(AsNode().OwnerDoc());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aElementId)) {
|
||||
if (Element* el = entry->GetIdElement()) {
|
||||
return el;
|
||||
}
|
||||
}
|
||||
|
||||
if (MOZ_UNLIKELY(mKind == Kind::Document &&
|
||||
static_cast<nsIDocument&>(AsNode()).IsXULDocument())) {
|
||||
return static_cast<XULDocument&>(AsNode()).GetRefById(aElementId);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
DocumentOrShadowRoot::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName)
|
||||
{
|
||||
ErrorResult rv;
|
||||
RefPtr<nsContentList> list =
|
||||
GetElementsByTagNameNS(aNamespaceURI, aLocalName, rv);
|
||||
if (rv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
return list.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
DocumentOrShadowRoot::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName,
|
||||
mozilla::ErrorResult& aResult)
|
||||
{
|
||||
int32_t nameSpaceId = kNameSpaceID_Wildcard;
|
||||
|
||||
if (!aNamespaceURI.EqualsLiteral("*")) {
|
||||
aResult =
|
||||
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
|
||||
nameSpaceId);
|
||||
if (aResult.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
|
||||
return NS_GetContentList(&AsNode(), nameSpaceId, aLocalName);
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
DocumentOrShadowRoot::GetElementsByClassName(const nsAString& aClasses)
|
||||
{
|
||||
return nsContentUtils::GetElementsByClassName(&AsNode(), aClasses);
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
DocumentOrShadowRoot::Retarget(nsIContent* aContent) const
|
||||
{
|
||||
for (nsIContent* cur = aContent;
|
||||
cur;
|
||||
cur = cur->GetContainingShadowHost()) {
|
||||
if (cur->SubtreeRoot() == &AsNode()) {
|
||||
return cur;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Element*
|
||||
DocumentOrShadowRoot::GetRetargetedFocusedElement()
|
||||
{
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> window = AsNode().OwnerDoc()->GetWindow()) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> focusedWindow;
|
||||
nsIContent* focusedContent =
|
||||
nsFocusManager::GetFocusedDescendant(window,
|
||||
false,
|
||||
getter_AddRefs(focusedWindow));
|
||||
// be safe and make sure the element is from this document
|
||||
if (focusedContent && focusedContent->OwnerDoc() == AsNode().OwnerDoc()) {
|
||||
if (focusedContent->ChromeOnlyAccess()) {
|
||||
focusedContent = focusedContent->FindFirstNonChromeOnlyAccessContent();
|
||||
}
|
||||
|
||||
if (focusedContent) {
|
||||
if (!nsDocument::IsWebComponentsEnabled(focusedContent)) {
|
||||
return focusedContent->AsElement();
|
||||
}
|
||||
|
||||
if (nsIContent* retarget = Retarget(focusedContent)) {
|
||||
return retarget->AsElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,160 +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_DocumentOrShadowRoot_h__
|
||||
#define mozilla_dom_DocumentOrShadowRoot_h__
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsIdentifierMapEntry.h"
|
||||
#include "nsContentListDeclarations.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "mozilla/dom/NameSpaceConstants.h"
|
||||
|
||||
class nsContentList;
|
||||
class nsINode;
|
||||
|
||||
namespace mozilla {
|
||||
class StyleSheet;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class StyleSheetList;
|
||||
class ShadowRoot;
|
||||
|
||||
/**
|
||||
* A class meant to be shared by ShadowRoot and Document, that holds a list of
|
||||
* stylesheets.
|
||||
*
|
||||
* TODO(emilio, bug 1418159): In the future this should hold most of the
|
||||
* relevant style state, this should allow us to fix bug 548397.
|
||||
*/
|
||||
class DocumentOrShadowRoot
|
||||
{
|
||||
enum class Kind {
|
||||
Document,
|
||||
ShadowRoot,
|
||||
};
|
||||
|
||||
public:
|
||||
explicit DocumentOrShadowRoot(nsIDocument*);
|
||||
explicit DocumentOrShadowRoot(mozilla::dom::ShadowRoot*);
|
||||
|
||||
nsINode& AsNode()
|
||||
{
|
||||
return *mAsNode;
|
||||
}
|
||||
|
||||
const nsINode& AsNode() const
|
||||
{
|
||||
return *mAsNode;
|
||||
}
|
||||
|
||||
StyleSheet* SheetAt(size_t aIndex) const
|
||||
{
|
||||
return mStyleSheets.SafeElementAt(aIndex);
|
||||
}
|
||||
|
||||
size_t SheetCount() const
|
||||
{
|
||||
return mStyleSheets.Length();
|
||||
}
|
||||
|
||||
int32_t IndexOfSheet(const StyleSheet& aSheet) const
|
||||
{
|
||||
return mStyleSheets.IndexOf(&aSheet);
|
||||
}
|
||||
|
||||
void InsertSheetAt(size_t aIndex, StyleSheet& aSheet)
|
||||
{
|
||||
mStyleSheets.InsertElementAt(aIndex, &aSheet);
|
||||
}
|
||||
|
||||
void RemoveSheet(StyleSheet& aSheet)
|
||||
{
|
||||
mStyleSheets.RemoveElement(&aSheet);
|
||||
}
|
||||
|
||||
void AppendStyleSheet(StyleSheet& aSheet)
|
||||
{
|
||||
mStyleSheets.AppendElement(&aSheet);
|
||||
}
|
||||
|
||||
StyleSheetList& EnsureDOMStyleSheets();
|
||||
|
||||
Element* GetElementById(const nsAString& aElementId);
|
||||
|
||||
/**
|
||||
* This method returns _all_ the elements in this scope which have id
|
||||
* aElementId, if there are any. Otherwise it returns null.
|
||||
*
|
||||
* This is useful for stuff like QuerySelector optimization and such.
|
||||
*/
|
||||
inline const nsTArray<Element*>*
|
||||
GetAllElementsForId(const nsAString& aElementId) const;
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagName(const nsAString& aTagName)
|
||||
{
|
||||
return NS_GetContentList(&AsNode(), kNameSpaceID_Unknown, aTagName);
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName);
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName,
|
||||
mozilla::ErrorResult&);
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByClassName(const nsAString& aClasses);
|
||||
|
||||
~DocumentOrShadowRoot() = default;
|
||||
|
||||
protected:
|
||||
nsIContent* Retarget(nsIContent* aContent) const;
|
||||
|
||||
/**
|
||||
* If focused element's subtree root is this document or shadow root, return
|
||||
* focused element, otherwise, get the shadow host recursively until the
|
||||
* shadow host's subtree root is this document or shadow root.
|
||||
*/
|
||||
Element* GetRetargetedFocusedElement();
|
||||
|
||||
nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheets;
|
||||
RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
|
||||
|
||||
/*
|
||||
* mIdentifierMap works as follows for IDs:
|
||||
* 1) Attribute changes affect the table immediately (removing and adding
|
||||
* entries as needed).
|
||||
* 2) Removals from the DOM affect the table immediately
|
||||
* 3) Additions to the DOM always update existing entries for names, and add
|
||||
* new ones for IDs.
|
||||
*/
|
||||
nsTHashtable<nsIdentifierMapEntry> mIdentifierMap;
|
||||
|
||||
nsINode* mAsNode;
|
||||
const Kind mKind;
|
||||
};
|
||||
|
||||
inline const nsTArray<Element*>*
|
||||
DocumentOrShadowRoot::GetAllElementsForId(const nsAString& aElementId) const
|
||||
{
|
||||
if (aElementId.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aElementId);
|
||||
return entry ? &entry->GetIdElements() : nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+287
-421
File diff suppressed because it is too large.
Load diff
+61
-231
@@ -41,7 +41,6 @@
|
||||
#include "Units.h"
|
||||
#include "DOMIntersectionObserver.h"
|
||||
|
||||
class mozAutoDocUpdate;
|
||||
class nsIFrame;
|
||||
class nsIDOMMozNamedAttrMap;
|
||||
class nsIURI;
|
||||
@@ -139,12 +138,12 @@ class EventStateManager;
|
||||
|
||||
namespace dom {
|
||||
|
||||
struct CustomElementDefinition;
|
||||
class Animation;
|
||||
class CustomElementRegistry;
|
||||
class Link;
|
||||
class DOMRect;
|
||||
class DOMRectList;
|
||||
class DestinationInsertionPointList;
|
||||
class Grid;
|
||||
|
||||
// IID for the dom::Element interface
|
||||
@@ -255,23 +254,6 @@ public:
|
||||
*/
|
||||
void ClearStyleStateLocks();
|
||||
|
||||
/**
|
||||
* Accessors for the state of our dir attribute.
|
||||
*/
|
||||
bool HasDirAuto() const
|
||||
{
|
||||
return State().HasState(NS_EVENT_STATE_DIR_ATTR_LIKE_AUTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Elements with dir="rtl" or dir="ltr".
|
||||
*/
|
||||
bool HasFixedDir() const
|
||||
{
|
||||
return State().HasAtLeastOneOfStates(NS_EVENT_STATE_DIR_ATTR_LTR |
|
||||
NS_EVENT_STATE_DIR_ATTR_RTL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inline style declaration, if any, for this element.
|
||||
*/
|
||||
@@ -397,48 +379,16 @@ public:
|
||||
|
||||
bool GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult);
|
||||
|
||||
Directionality GetComputedDirectionality() const;
|
||||
|
||||
inline Element* GetFlattenedTreeParentElementForStyle() const;
|
||||
|
||||
/**
|
||||
* Gets the custom element data used by web components custom element.
|
||||
* Custom element data is created at the first attempt to enqueue a callback.
|
||||
*
|
||||
* @return The custom element data or null if none.
|
||||
*/
|
||||
inline CustomElementData* GetCustomElementData() const
|
||||
{
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
if (slots) {
|
||||
return slots->mCustomElementData;
|
||||
}
|
||||
return nullptr;
|
||||
// The bdi element defaults to dir=auto if it has no dir attribute set.
|
||||
// Other elements will only have dir=auto if they have an explicit dir=auto,
|
||||
// which will mean that HasValidDir() returns true but HasFixedDir() returns
|
||||
// false
|
||||
inline bool HasDirAuto() const {
|
||||
return (!HasFixedDir() &&
|
||||
(HasValidDir() || IsHTMLElement(nsGkAtoms::bdi)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the custom element data, ownership of the
|
||||
* callback data is taken by this element.
|
||||
*
|
||||
* @param aData The custom element data.
|
||||
*/
|
||||
void SetCustomElementData(CustomElementData* aData);
|
||||
|
||||
/**
|
||||
* Gets the custom element definition used by web components custom element.
|
||||
*
|
||||
* @return The custom element definition or null if element is not a custom
|
||||
* element or custom element is not defined yet.
|
||||
*/
|
||||
CustomElementDefinition* GetCustomElementDefinition() const;
|
||||
|
||||
/**
|
||||
* Sets the custom element definition, called when custom element is created
|
||||
* or upgraded.
|
||||
*
|
||||
* @param aDefinition The custom element definition.
|
||||
*/
|
||||
void SetCustomElementDefinition(CustomElementDefinition* aDefinition);
|
||||
Directionality GetComputedDirectionality() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -471,9 +421,6 @@ protected:
|
||||
mState &= ~aStates;
|
||||
}
|
||||
|
||||
already_AddRefed<ShadowRoot> AttachShadowInternal(bool aClosed,
|
||||
ErrorResult& aError);
|
||||
|
||||
private:
|
||||
// Need to allow the ESM, nsGlobalWindow, and the focus manager to
|
||||
// set our state
|
||||
@@ -512,16 +459,6 @@ protected:
|
||||
RemoveStatesSilently(aStates);
|
||||
NotifyStateChange(aStates);
|
||||
}
|
||||
virtual void ToggleStates(EventStates aStates, bool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(!aStates.HasAtLeastOneOfStates(INTRINSIC_STATES),
|
||||
"Should only be removing externally-managed states here");
|
||||
mState ^= aStates;
|
||||
if (aNotify) {
|
||||
NotifyStateChange(aStates);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
virtual void UpdateEditableState(bool aNotify) override;
|
||||
|
||||
@@ -544,7 +481,6 @@ public:
|
||||
already_AddRefed<mozilla::dom::NodeInfo>
|
||||
GetExistingAttrNameFromQName(const nsAString& aStr) const;
|
||||
|
||||
MOZ_ALWAYS_INLINE // Avoid a crashy hook from Avast 10 Beta (Bug 1058131)
|
||||
nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAString& aValue, bool aNotify)
|
||||
{
|
||||
@@ -559,57 +495,25 @@ public:
|
||||
* values will not actually be compared if we aren't notifying and we don't
|
||||
* have mutation listeners (in which case it's cheap to just return false
|
||||
* and let the caller go ahead and set the value).
|
||||
* @param aOldValue [out] Set to the old value of the attribute, but only if
|
||||
* there are event listeners. If set, the type of aOldValue will be either
|
||||
* @param aOldValue Set to the old value of the attribute, but only if there
|
||||
* are event listeners. If set, the type of aOldValue will be either
|
||||
* nsAttrValue::eString or nsAttrValue::eAtom.
|
||||
* @param aModType [out] Set to nsIDOMMutationEvent::MODIFICATION or to
|
||||
* @param aModType Set to nsIDOMMutationEvent::MODIFICATION or to
|
||||
* nsIDOMMutationEvent::ADDITION, but only if this helper returns true
|
||||
* @param aHasListeners [out] Set to true if there are mutation event
|
||||
* listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
|
||||
* @param aOldValueSet [out] Indicates whether an old attribute value has been
|
||||
* stored in aOldValue. The bool will be set to true if a value was stored.
|
||||
* @param aHasListeners Set to true if there are mutation event listeners
|
||||
* listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
|
||||
*/
|
||||
bool MaybeCheckSameAttrVal(int32_t aNamespaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix,
|
||||
const nsAttrValueOrString& aValue,
|
||||
bool aNotify, nsAttrValue& aOldValue,
|
||||
uint8_t* aModType, bool* aHasListeners,
|
||||
bool* aOldValueSet);
|
||||
|
||||
/**
|
||||
* Notifies mutation listeners if aNotify is true, there are mutation
|
||||
* listeners, and the attribute value is changing.
|
||||
*
|
||||
* @param aNamespaceID The namespace of the attribute
|
||||
* @param aName The local name of the attribute
|
||||
* @param aPrefix The prefix of the attribute
|
||||
* @param aValue The value that the attribute is being changed to
|
||||
* @param aNotify If true, mutation listeners will be notified if they exist
|
||||
* and the attribute value is changing
|
||||
* @param aOldValue [out] Set to the old value of the attribute, but only if
|
||||
* there are event listeners. If set, the type of aOldValue will be either
|
||||
* nsAttrValue::eString or nsAttrValue::eAtom.
|
||||
* @param aModType [out] Set to nsIDOMMutationEvent::MODIFICATION or to
|
||||
* nsIDOMMutationEvent::ADDITION, but only if this helper returns true
|
||||
* @param aHasListeners [out] Set to true if there are mutation event
|
||||
* listeners listening for NS_EVENT_BITS_MUTATION_ATTRMODIFIED
|
||||
* @param aOldValueSet [out] Indicates whether an old attribute value has been
|
||||
* stored in aOldValue. The bool will be set to true if a value was stored.
|
||||
*/
|
||||
uint8_t* aModType, bool* aHasListeners);
|
||||
|
||||
bool OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
|
||||
nsIAtom* aPrefix,
|
||||
const nsAttrValueOrString& aValue,
|
||||
bool aNotify, nsAttrValue& aOldValue,
|
||||
uint8_t* aModType, bool* aHasListeners,
|
||||
bool* aOldValueSet);
|
||||
|
||||
/**
|
||||
* Sets the class attribute to a value that contains no whitespace.
|
||||
* Assumes that we are not notifying and that the attribute hasn't been
|
||||
* set previously.
|
||||
*/
|
||||
nsresult SetSingleClassFromParser(nsIAtom* aSingleClassName);
|
||||
uint8_t* aModType, bool* aHasListeners);
|
||||
|
||||
virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, nsIAtom* aPrefix,
|
||||
const nsAString& aValue, bool aNotify) override;
|
||||
@@ -646,7 +550,7 @@ public:
|
||||
* guaranteed (e.g. we could have class="").
|
||||
*/
|
||||
const nsAttrValue* GetClasses() const {
|
||||
if (MayHaveClass()) {
|
||||
if (HasFlag(NODE_MAY_HAVE_CLASS)) {
|
||||
return DoGetClasses();
|
||||
}
|
||||
return nullptr;
|
||||
@@ -818,25 +722,6 @@ public:
|
||||
already_AddRefed<nsIHTMLCollection>
|
||||
GetElementsByClassName(const nsAString& aClassNames);
|
||||
|
||||
CSSPseudoElementType GetPseudoElementType() const {
|
||||
if (!HasProperties()) {
|
||||
return CSSPseudoElementType::NotPseudo;
|
||||
}
|
||||
nsresult rv = NS_OK;
|
||||
auto raw = GetProperty(nsGkAtoms::pseudoProperty, &rv);
|
||||
if (rv == NS_PROPTABLE_PROP_NOT_THERE) {
|
||||
return CSSPseudoElementType::NotPseudo;
|
||||
}
|
||||
return CSSPseudoElementType(reinterpret_cast<uintptr_t>(raw));
|
||||
}
|
||||
|
||||
void SetPseudoElementType(CSSPseudoElementType aPseudo) {
|
||||
static_assert(sizeof(CSSPseudoElementType) <= sizeof(uintptr_t),
|
||||
"Need to be able to store this in a void*");
|
||||
MOZ_ASSERT(aPseudo != CSSPseudoElementType::NotPseudo);
|
||||
SetProperty(nsGkAtoms::pseudoProperty, reinterpret_cast<void*>(aPseudo));
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Implement the algorithm specified at
|
||||
@@ -924,19 +809,12 @@ public:
|
||||
already_AddRefed<DOMRectList> GetClientRects();
|
||||
already_AddRefed<DOMRect> GetBoundingClientRect();
|
||||
|
||||
// Shadow DOM v1
|
||||
already_AddRefed<ShadowRoot> AttachShadow(const ShadowRootInit& aInit,
|
||||
ErrorResult& aError);
|
||||
ShadowRoot* GetShadowRootByMode() const;
|
||||
void SetSlot(const nsAString& aName, ErrorResult& aError);
|
||||
void GetSlot(nsAString& aName);
|
||||
|
||||
// [deprecated] Shadow DOM v0
|
||||
already_AddRefed<ShadowRoot> CreateShadowRoot(ErrorResult& aError);
|
||||
already_AddRefed<DestinationInsertionPointList> GetDestinationInsertionPoints();
|
||||
|
||||
ShadowRoot *FastGetShadowRoot() const
|
||||
{
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
nsDOMSlots* slots = GetExistingDOMSlots();
|
||||
return slots ? slots->mShadowRoot.get() : nullptr;
|
||||
}
|
||||
|
||||
@@ -1322,10 +1200,7 @@ protected:
|
||||
* its current value) is !StoresOwnData() --- in which
|
||||
* case the current value is probably already useless.
|
||||
* If the current value is StoresOwnData() (or absent),
|
||||
* aOldValue will not be used. aOldValue will only be set
|
||||
* in certain circumstances (there are mutation
|
||||
* listeners, element is a custom element, attribute was
|
||||
* not previously unset). Otherwise it will be null.
|
||||
* aOldValue will not be used.
|
||||
* @param aParsedValue parsed new value of attribute. Replaced by the
|
||||
* old value of the attribute. This old value is only
|
||||
* useful if either it or the new value is StoresOwnData.
|
||||
@@ -1334,19 +1209,16 @@ protected:
|
||||
* @param aFireMutation should mutation-events be fired?
|
||||
* @param aNotify should we notify document-observers?
|
||||
* @param aCallAfterSetAttr should we call AfterSetAttr?
|
||||
* @param aComposedDocument The current composed document of the element.
|
||||
*/
|
||||
nsresult SetAttrAndNotify(int32_t aNamespaceID,
|
||||
nsIAtom* aName,
|
||||
nsIAtom* aPrefix,
|
||||
const nsAttrValue* aOldValue,
|
||||
const nsAttrValue& aOldValue,
|
||||
nsAttrValue& aParsedValue,
|
||||
uint8_t aModType,
|
||||
bool aFireMutation,
|
||||
bool aNotify,
|
||||
bool aCallAfterSetAttr,
|
||||
nsIDocument* aComposedDocument,
|
||||
const mozAutoDocUpdate& aGuard);
|
||||
bool aCallAfterSetAttr);
|
||||
|
||||
/**
|
||||
* Scroll to a new position using behavior evaluated from CSS and
|
||||
@@ -1384,21 +1256,14 @@ protected:
|
||||
*
|
||||
* @param aDocument the current document of this node (an optimization)
|
||||
* @param aName the name of the attribute
|
||||
* @param aValue the nsAttrValue to set. Will be swapped with the existing
|
||||
* value of the attribute if the attribute already exists.
|
||||
* @param [out] aValueWasSet If the attribute was not set previously,
|
||||
* aValue will be swapped with an empty attribute
|
||||
* and aValueWasSet will be set to false. Otherwise,
|
||||
* aValueWasSet will be set to true and aValue will
|
||||
* contain the previous value set.
|
||||
* @param aValue the nsAttrValue to set
|
||||
* @param [out] aRetval the nsresult status of the operation, if any.
|
||||
* @return true if the setting was attempted, false otherwise.
|
||||
*/
|
||||
virtual bool SetAndSwapMappedAttribute(nsIDocument* aDocument,
|
||||
nsIAtom* aName,
|
||||
nsAttrValue& aValue,
|
||||
bool* aValueWasSet,
|
||||
nsresult* aRetval);
|
||||
virtual bool SetMappedAttribute(nsIDocument* aDocument,
|
||||
nsIAtom* aName,
|
||||
nsAttrValue& aValue,
|
||||
nsresult* aRetval);
|
||||
|
||||
/**
|
||||
* Hook that is called by Element::SetAttr to allow subclasses to
|
||||
@@ -1411,92 +1276,33 @@ protected:
|
||||
* @param aName the localname of the attribute being set
|
||||
* @param aValue the value it's being set to represented as either a string or
|
||||
* a parsed nsAttrValue. Alternatively, if the attr is being removed it
|
||||
* will be null.
|
||||
* will be null. BeforeSetAttr is allowed to modify aValue by parsing
|
||||
* the string to an nsAttrValue (to avoid having to reparse it in
|
||||
* ParseAttribute).
|
||||
* @param aNotify Whether we plan to notify document observers.
|
||||
*/
|
||||
// Note that this is inlined so that when subclasses call it it gets
|
||||
// inlined. Those calls don't go through a vtable.
|
||||
virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
||||
const nsAttrValueOrString* aValue,
|
||||
nsAttrValueOrString* aValue,
|
||||
bool aNotify);
|
||||
|
||||
/**
|
||||
* Hook that is called by Element::SetAttr to allow subclasses to
|
||||
* deal with attribute sets. This will only be called after we have called
|
||||
* SetAndSwapAttr (that is, after we have actually set the attr). It will
|
||||
* always be called under a scriptblocker.
|
||||
* SetAndTakeAttr and AttributeChanged (that is, after we have actually set
|
||||
* the attr). It will always be called under a scriptblocker.
|
||||
*
|
||||
* @param aNamespaceID the namespace of the attr being set
|
||||
* @param aName the localname of the attribute being set
|
||||
* @param aValue the value it's being set to. If null, the attr is being
|
||||
* removed.
|
||||
* @param aOldValue the value that the attribute had previously. If null,
|
||||
* the attr was not previously set. This argument may not have the
|
||||
* correct value for SVG elements, or other cases in which the
|
||||
* attribute value doesn't store its own data
|
||||
* @param aNotify Whether we plan to notify document observers.
|
||||
*/
|
||||
// Note that this is inlined so that when subclasses call it it gets
|
||||
// inlined. Those calls don't go through a vtable.
|
||||
virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue, bool aNotify)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function shall be called just before the id attribute changes. It will
|
||||
* be called after BeforeSetAttr. If the attribute being changed is not the id
|
||||
* attribute, this function does nothing. Otherwise, it will remove the old id
|
||||
* from the document's id cache.
|
||||
*
|
||||
* This must happen after BeforeSetAttr (rather than during) because the
|
||||
* the subclasses' calls to BeforeSetAttr may notify on state changes. If they
|
||||
* incorrectly determine whether the element had an id, the element may not be
|
||||
* restyled properly.
|
||||
*
|
||||
* @param aNamespaceID the namespace of the attr being set
|
||||
* @param aName the localname of the attribute being set
|
||||
* @param aValue the new id value. Will be null if the id is being unset.
|
||||
*/
|
||||
void PreIdMaybeChange(int32_t aNamespaceID, nsIAtom* aName,
|
||||
const nsAttrValueOrString* aValue);
|
||||
|
||||
/**
|
||||
* This function shall be called just after the id attribute changes. It will
|
||||
* be called before AfterSetAttr. If the attribute being changed is not the id
|
||||
* attribute, this function does nothing. Otherwise, it will add the new id to
|
||||
* the document's id cache and properly set the ElementHasID flag.
|
||||
*
|
||||
* This must happen before AfterSetAttr (rather than during) because the
|
||||
* the subclasses' calls to AfterSetAttr may notify on state changes. If they
|
||||
* incorrectly determine whether the element now has an id, the element may
|
||||
* not be restyled properly.
|
||||
*
|
||||
* @param aNamespaceID the namespace of the attr being set
|
||||
* @param aName the localname of the attribute being set
|
||||
* @param aValue the new id value. Will be null if the id is being unset.
|
||||
*/
|
||||
void PostIdMaybeChange(int32_t aNamespaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue);
|
||||
|
||||
/**
|
||||
* Usually, setting an attribute to the value that it already has results in
|
||||
* no action. However, in some cases, setting an attribute to its current
|
||||
* value should have the effect of, for example, forcing a reload of
|
||||
* network data. To address that, this function will be called in this
|
||||
* situation to allow the handling of such a case.
|
||||
*
|
||||
* @param aNamespaceID the namespace of the attr being set
|
||||
* @param aName the localname of the attribute being set
|
||||
* @param aValue the value it's being set to represented as either a string or
|
||||
* a parsed nsAttrValue.
|
||||
* @param aNotify Whether we plan to notify document observers.
|
||||
*/
|
||||
// Note that this is inlined so that when subclasses call it it gets
|
||||
// inlined. Those calls don't go through a vtable.
|
||||
virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsIAtom* aName,
|
||||
const nsAttrValueOrString& aValue,
|
||||
bool aNotify)
|
||||
const nsAttrValue* aValue, bool aNotify)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1555,7 +1361,7 @@ protected:
|
||||
/**
|
||||
* Handle status bar updates before they can be cancelled.
|
||||
*/
|
||||
nsresult GetEventTargetParentForLinks(EventChainPreVisitor& aVisitor);
|
||||
nsresult PreHandleEventForLinks(EventChainPreVisitor& aVisitor);
|
||||
|
||||
/**
|
||||
* Handle default actions for link event if the event isn't consumed yet.
|
||||
@@ -1615,6 +1421,30 @@ private:
|
||||
nsCOMPtr<nsIDocument> mDoc;
|
||||
};
|
||||
|
||||
class DestinationInsertionPointList : public nsINodeList
|
||||
{
|
||||
public:
|
||||
explicit DestinationInsertionPointList(Element* aElement);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DestinationInsertionPointList)
|
||||
|
||||
// nsIDOMNodeList
|
||||
NS_DECL_NSIDOMNODELIST
|
||||
|
||||
// nsINodeList
|
||||
virtual nsIContent* Item(uint32_t aIndex) override;
|
||||
virtual int32_t IndexOf(nsIContent* aContent) override;
|
||||
virtual nsINode* GetParentObject() override { return mParent; }
|
||||
virtual uint32_t Length() const;
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
protected:
|
||||
virtual ~DestinationInsertionPointList();
|
||||
|
||||
RefPtr<Element> mParent;
|
||||
nsCOMArray<nsIContent> mDestinationPoints;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Element, NS_ELEMENT_IID)
|
||||
|
||||
inline bool
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#define mozilla_dom_ElementInlines_h
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
namespace mozilla {
|
||||
@@ -26,17 +25,6 @@ Element::UnregisterActivityObserver()
|
||||
OwnerDoc()->UnregisterActivityObserver(this);
|
||||
}
|
||||
|
||||
inline Element*
|
||||
Element::GetFlattenedTreeParentElementForStyle() const
|
||||
{
|
||||
nsINode* parentNode = GetFlattenedTreeParentNodeForStyle();
|
||||
if MOZ_LIKELY(parentNode && parentNode->IsElement()) {
|
||||
return parentNode->AsElement();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
+157
-222
@@ -123,7 +123,6 @@
|
||||
#include "mozilla/CORSMode.h"
|
||||
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "mozilla/dom/HTMLSlotElement.h"
|
||||
#include "mozilla/dom/HTMLTemplateElement.h"
|
||||
|
||||
#include "nsStyledElement.h"
|
||||
@@ -152,56 +151,8 @@ nsIContent::FindFirstNonChromeOnlyAccessContent() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// https://dom.spec.whatwg.org/#dom-slotable-assignedslot
|
||||
HTMLSlotElement*
|
||||
nsIContent::GetAssignedSlotByMode() const
|
||||
{
|
||||
/**
|
||||
* Get slotable's assigned slot for the result of
|
||||
* find a slot with open flag UNSET [1].
|
||||
*
|
||||
* [1] https://dom.spec.whatwg.org/#assign-a-slot
|
||||
*/
|
||||
HTMLSlotElement* slot = GetAssignedSlot();
|
||||
if (!slot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(GetParent());
|
||||
MOZ_ASSERT(GetParent()->GetShadowRoot());
|
||||
|
||||
/**
|
||||
* Additional check for open flag SET:
|
||||
* If slotable’s parent’s shadow root's mode is not "open",
|
||||
* then return null.
|
||||
*/
|
||||
if (GetParent()->GetShadowRoot()->IsClosed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
nsINode*
|
||||
nsIContent::GetFlattenedTreeParentForMaybeAssignedNode() const
|
||||
{
|
||||
if (HTMLSlotElement* assignedSlot = GetAssignedSlot()) {
|
||||
return assignedSlot;
|
||||
}
|
||||
|
||||
HTMLSlotElement* parentSlot = HTMLSlotElement::FromContent(GetParent());
|
||||
if (!parentSlot) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// If this is not an unassigned node, then it must be a fallback content.
|
||||
MOZ_ASSERT(parentSlot->AssignedNodes().IsEmpty());
|
||||
|
||||
return parentSlot;
|
||||
}
|
||||
|
||||
nsINode*
|
||||
nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const
|
||||
nsIContent::GetFlattenedTreeParentNodeInternal() const
|
||||
{
|
||||
nsINode* parentNode = GetParentNode();
|
||||
if (!parentNode || !parentNode->IsContent()) {
|
||||
@@ -210,51 +161,18 @@ nsIContent::GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const
|
||||
}
|
||||
nsIContent* parent = parentNode->AsContent();
|
||||
|
||||
if (aType == eForStyle &&
|
||||
IsRootOfNativeAnonymousSubtree() &&
|
||||
OwnerDoc()->GetRootElement() == parent) {
|
||||
// When getting the flattened tree parent for style, we return null
|
||||
// for any "document level" native anonymous content subtree root.
|
||||
// This is NAC generated by an ancestor frame of the document element's
|
||||
// primary frame, and includes scrollbar elements created by the root
|
||||
// scroll frame, and the "custom content container" and accessible caret
|
||||
// generated by the nsCanvasFrame. We distinguish document level NAC
|
||||
// from NAC generated by the root element's primary frame below.
|
||||
nsIFrame* parentFrame = parent->GetPrimaryFrame();
|
||||
if (!parentFrame) {
|
||||
// If the root element has no primary frame, it means it can't have
|
||||
// generated any NAC itself. Thus any NAC we have here must have
|
||||
// been generated by an ancestor frame.
|
||||
//
|
||||
// If we are in here, then either the root element is display:none, or
|
||||
// we are in the middle of constructing the root of the frame tree and
|
||||
// we are trying to eagerly restyle document level NAC in
|
||||
// nsCSSFrameConstructor::GetAnonymousContent before the root
|
||||
// element's frame has been constructed.
|
||||
return nullptr;
|
||||
}
|
||||
nsIAnonymousContentCreator* creator = do_QueryFrame(parentFrame);
|
||||
if (!creator) {
|
||||
// If the root element does have a frame, but does not implement
|
||||
// nsIAnonymousContentCreator, then this must be document level NAC.
|
||||
return nullptr;
|
||||
}
|
||||
AutoTArray<nsIContent*, 8> elements;
|
||||
creator->AppendAnonymousContentTo(elements, 0);
|
||||
if (!elements.Contains(this)) {
|
||||
// If the root element does have a frame, and also does implement
|
||||
// nsIAnonymousContentCreator, but didn't create this node, then
|
||||
// it must be document level NAC.
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent && nsContentUtils::HasDistributedChildren(parent) &&
|
||||
nsContentUtils::IsInSameAnonymousTree(parent, this)) {
|
||||
return GetFlattenedTreeParentForMaybeAssignedNode();
|
||||
}
|
||||
|
||||
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
|
||||
// This node is distributed to insertion points, thus we
|
||||
// need to consult the destination insertion points list to
|
||||
// figure out where this node was inserted in the flattened tree.
|
||||
// It may be the case that |parent| distributes its children
|
||||
// but the child does not match any insertion points, thus
|
||||
// the flattened tree parent is nullptr.
|
||||
nsTArray<nsIContent*>* destInsertionPoints = GetExistingDestInsertionPoints();
|
||||
parent = destInsertionPoints && !destInsertionPoints->IsEmpty() ?
|
||||
destInsertionPoints->LastElement()->GetParent() : nullptr;
|
||||
} else if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
|
||||
nsIContent* insertionParent = GetXBLInsertionParent();
|
||||
if (insertionParent) {
|
||||
parent = insertionParent;
|
||||
@@ -612,7 +530,8 @@ nsNodeSupportsWeakRefTearoff::GetWeakReference(nsIWeakReference** aInstancePtr)
|
||||
//----------------------------------------------------------------------
|
||||
FragmentOrElement::nsDOMSlots::nsDOMSlots()
|
||||
: nsINode::nsSlots(),
|
||||
mDataset(nullptr)
|
||||
mDataset(nullptr),
|
||||
mBindingParent(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -624,108 +543,84 @@ FragmentOrElement::nsDOMSlots::~nsDOMSlots()
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
|
||||
FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL)
|
||||
{
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle");
|
||||
cb.NoteXPCOMChild(mStyle.get());
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mSMILOverrideStyle");
|
||||
cb.NoteXPCOMChild(mSMILOverrideStyle.get());
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap");
|
||||
cb.NoteXPCOMChild(mAttributeMap.get());
|
||||
|
||||
if (aIsXUL) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mControllers");
|
||||
cb.NoteXPCOMChild(mControllers);
|
||||
}
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLBinding");
|
||||
cb.NoteNativeChild(mXBLBinding, NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionParent");
|
||||
cb.NoteXPCOMChild(mXBLInsertionParent.get());
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mShadowRoot");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mShadowRoot));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mLabelsList");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mLabelsList));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
|
||||
cb.NoteXPCOMChild(mClassList.get());
|
||||
|
||||
if (!mExtendedSlots) {
|
||||
return;
|
||||
if (mCustomElementData) {
|
||||
for (uint32_t i = 0; i < mCustomElementData->mCallbackQueue.Length(); i++) {
|
||||
mCustomElementData->mCallbackQueue[i]->Traverse(cb);
|
||||
}
|
||||
}
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mSMILOverrideStyle");
|
||||
cb.NoteXPCOMChild(mExtendedSlots->mSMILOverrideStyle.get());
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mControllers");
|
||||
cb.NoteXPCOMChild(mExtendedSlots->mControllers);
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mLabelsList");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*,mExtendedSlots-> mLabelsList));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mShadowRoot");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mShadowRoot));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mContainingShadow");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mContainingShadow));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mAssignedSlot");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mAssignedSlot.get()));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLBinding");
|
||||
cb.NoteNativeChild(mExtendedSlots->mXBLBinding,
|
||||
NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLInsertionParent");
|
||||
cb.NoteXPCOMChild(mExtendedSlots->mXBLInsertionParent.get());
|
||||
|
||||
if (mExtendedSlots->mCustomElementData) {
|
||||
mExtendedSlots->mCustomElementData->Traverse(cb);
|
||||
}
|
||||
|
||||
for (auto iter = mExtendedSlots->mRegisteredIntersectionObservers.Iter();
|
||||
!iter.Done(); iter.Next()) {
|
||||
for (auto iter = mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
|
||||
DOMIntersectionObserver* observer = iter.Key();
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||
"mExtendedSlots->mRegisteredIntersectionObservers[i]");
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mRegisteredIntersectionObservers[i]");
|
||||
cb.NoteXPCOMChild(observer);
|
||||
}
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mFrameLoaderOrOpener");
|
||||
cb.NoteXPCOMChild(mExtendedSlots->mFrameLoaderOrOpener);
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::nsDOMSlots::Unlink()
|
||||
FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL)
|
||||
{
|
||||
mStyle = nullptr;
|
||||
mSMILOverrideStyle = nullptr;
|
||||
if (mAttributeMap) {
|
||||
mAttributeMap->DropReference();
|
||||
mAttributeMap = nullptr;
|
||||
}
|
||||
if (aIsXUL)
|
||||
NS_IF_RELEASE(mControllers);
|
||||
|
||||
MOZ_ASSERT(!mXBLBinding);
|
||||
|
||||
mXBLInsertionParent = nullptr;
|
||||
mShadowRoot = nullptr;
|
||||
mContainingShadow = nullptr;
|
||||
mChildrenList = nullptr;
|
||||
mLabelsList = nullptr;
|
||||
mCustomElementData = nullptr;
|
||||
mClassList = nullptr;
|
||||
|
||||
if (!mExtendedSlots) {
|
||||
return;
|
||||
}
|
||||
|
||||
mExtendedSlots->mSMILOverrideStyle = nullptr;
|
||||
mExtendedSlots->mControllers = nullptr;
|
||||
mExtendedSlots->mLabelsList = nullptr;
|
||||
mExtendedSlots->mShadowRoot = nullptr;
|
||||
mExtendedSlots->mContainingShadow = nullptr;
|
||||
mExtendedSlots->mAssignedSlot = nullptr;
|
||||
MOZ_ASSERT(!(mExtendedSlots->mXBLBinding));
|
||||
mExtendedSlots->mXBLInsertionParent = nullptr;
|
||||
if (mExtendedSlots->mCustomElementData) {
|
||||
mExtendedSlots->mCustomElementData->Unlink();
|
||||
mExtendedSlots->mCustomElementData = nullptr;
|
||||
}
|
||||
mExtendedSlots->mRegisteredIntersectionObservers.Clear();
|
||||
nsCOMPtr<nsIFrameLoader> frameLoader =
|
||||
do_QueryInterface(mExtendedSlots->mFrameLoaderOrOpener);
|
||||
if (frameLoader) {
|
||||
static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
|
||||
}
|
||||
mExtendedSlots->mFrameLoaderOrOpener = nullptr;
|
||||
mRegisteredIntersectionObservers.Clear();
|
||||
}
|
||||
|
||||
size_t
|
||||
FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t n = aMallocSizeOf(this);
|
||||
if (mExtendedSlots) {
|
||||
n += aMallocSizeOf(mExtendedSlots.get());
|
||||
}
|
||||
|
||||
if (mAttributeMap) {
|
||||
n += mAttributeMap->SizeOfIncludingThis(aMallocSizeOf);
|
||||
@@ -746,19 +641,6 @@ FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) c
|
||||
return n;
|
||||
}
|
||||
|
||||
FragmentOrElement::nsExtendedDOMSlots::nsExtendedDOMSlots()
|
||||
: mBindingParent(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots()
|
||||
{
|
||||
nsCOMPtr<nsIFrameLoader> frameLoader = do_QueryInterface(mFrameLoaderOrOpener);
|
||||
if (frameLoader) {
|
||||
static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
FragmentOrElement::FragmentOrElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
|
||||
: nsIContent(aNodeInfo)
|
||||
{
|
||||
@@ -804,7 +686,7 @@ FindChromeAccessOnlySubtreeOwner(nsIContent* aContent)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
nsIContent::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
//FIXME! Document how this event retargeting works, Bug 329124.
|
||||
aVisitor.mCanHandle = true;
|
||||
@@ -813,7 +695,6 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
// Don't propagate mouseover and mouseout events when mouse is moving
|
||||
// inside chrome access only content.
|
||||
bool isAnonForEvents = IsRootOfChromeAccessOnlySubtree();
|
||||
aVisitor.mRootOfClosedTree = isAnonForEvents;
|
||||
if ((aVisitor.mEvent->mMessage == eMouseOver ||
|
||||
aVisitor.mEvent->mMessage == eMouseOut ||
|
||||
aVisitor.mEvent->mMessage == ePointerOver ||
|
||||
@@ -825,7 +706,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
((this == aVisitor.mEvent->mOriginalTarget &&
|
||||
!ChromeOnlyAccess()) || isAnonForEvents || GetShadowRoot())) {
|
||||
nsCOMPtr<nsIContent> relatedTarget =
|
||||
do_QueryInterface(aVisitor.mEvent->AsMouseEvent()->mRelatedTarget);
|
||||
do_QueryInterface(aVisitor.mEvent->AsMouseEvent()->relatedTarget);
|
||||
if (relatedTarget &&
|
||||
relatedTarget->OwnerDoc() == OwnerDoc()) {
|
||||
|
||||
@@ -835,7 +716,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
nsIContent* adjustedTarget =
|
||||
Event::GetShadowRelatedTarget(this, relatedTarget);
|
||||
if (this == adjustedTarget) {
|
||||
aVisitor.SetParentTarget(nullptr, false);
|
||||
aVisitor.mParentTarget = nullptr;
|
||||
aVisitor.mCanHandle = false;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -892,7 +773,7 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
originalTarget->FindFirstNonChromeOnlyAccessContent())
|
||||
? "" : "Wrong event propagation!?!\n");
|
||||
#endif
|
||||
aVisitor.SetParentTarget(nullptr, false);
|
||||
aVisitor.mParentTarget = nullptr;
|
||||
// Event should not propagate to non-anon content.
|
||||
aVisitor.mCanHandle = isAnonForEvents;
|
||||
return NS_OK;
|
||||
@@ -903,10 +784,58 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
// Event parent is the assigned slot, if node is assigned, or node's parent
|
||||
// otherwise.
|
||||
HTMLSlotElement* slot = GetAssignedSlot();
|
||||
nsIContent* parent = slot ? slot : GetParent();
|
||||
nsIContent* parent = GetParent();
|
||||
|
||||
// Web components have a special event chain that need to account
|
||||
// for destination insertion points where nodes have been distributed.
|
||||
nsTArray<nsIContent*>* destPoints = GetExistingDestInsertionPoints();
|
||||
if (destPoints && !destPoints->IsEmpty()) {
|
||||
// Push destination insertion points to aVisitor.mDestInsertionPoints
|
||||
// excluding shadow insertion points.
|
||||
bool didPushNonShadowInsertionPoint = false;
|
||||
for (uint32_t i = 0; i < destPoints->Length(); i++) {
|
||||
nsIContent* point = destPoints->ElementAt(i);
|
||||
if (!ShadowRoot::IsShadowInsertionPoint(point)) {
|
||||
aVisitor.mDestInsertionPoints.AppendElement(point);
|
||||
didPushNonShadowInsertionPoint = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Next node in the event path is the final destination
|
||||
// (non-shadow) insertion point that was pushed.
|
||||
if (didPushNonShadowInsertionPoint) {
|
||||
parent = aVisitor.mDestInsertionPoints.LastElement();
|
||||
aVisitor.mDestInsertionPoints.SetLength(
|
||||
aVisitor.mDestInsertionPoints.Length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
ShadowRoot* thisShadowRoot = ShadowRoot::FromNode(this);
|
||||
if (thisShadowRoot) {
|
||||
if (!aVisitor.mEvent->mFlags.mComposed) {
|
||||
// If we do stop propagation, we still want to propagate
|
||||
// the event to chrome (nsPIDOMWindow::GetParentTarget()).
|
||||
// The load event is special in that we don't ever propagate it
|
||||
// to chrome.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = OwnerDoc()->GetWindow();
|
||||
EventTarget* parentTarget = win && aVisitor.mEvent->mMessage != eLoad
|
||||
? win->GetParentTarget() : nullptr;
|
||||
|
||||
aVisitor.mParentTarget = parentTarget;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!aVisitor.mDestInsertionPoints.IsEmpty()) {
|
||||
parent = aVisitor.mDestInsertionPoints.LastElement();
|
||||
aVisitor.mDestInsertionPoints.SetLength(
|
||||
aVisitor.mDestInsertionPoints.Length() - 1);
|
||||
} else {
|
||||
// The pool host for the youngest shadow root is shadow DOM host,
|
||||
// for older shadow roots, it is the shadow insertion point
|
||||
// where the shadow root is projected, nullptr if none exists.
|
||||
parent = thisShadowRoot->GetPoolHost();
|
||||
}
|
||||
}
|
||||
|
||||
// Event may need to be retargeted if this is the root of a native
|
||||
// anonymous content subtree or event is dispatched somewhere inside XBL.
|
||||
@@ -944,17 +873,11 @@ nsIContent::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
if (!aVisitor.mEvent->mFlags.mComposedInNativeAnonymousContent &&
|
||||
IsRootOfNativeAnonymousSubtree() && OwnerDoc() &&
|
||||
OwnerDoc()->GetWindow()) {
|
||||
aVisitor.SetParentTarget(OwnerDoc()->GetWindow()->GetParentTarget(), true);
|
||||
aVisitor.mParentTarget = OwnerDoc()->GetWindow()->GetParentTarget();
|
||||
} else if (parent) {
|
||||
aVisitor.SetParentTarget(parent, false);
|
||||
if (slot) {
|
||||
ShadowRoot* root = slot->GetContainingShadow();
|
||||
if (root && root->IsClosed()) {
|
||||
aVisitor.mParentIsSlotInClosedTree = true;
|
||||
}
|
||||
}
|
||||
aVisitor.mParentTarget = parent;
|
||||
} else {
|
||||
aVisitor.SetParentTarget(GetComposedDoc(), false);
|
||||
aVisitor.mParentTarget = GetComposedDoc();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -1039,7 +962,7 @@ FragmentOrElement::IsLink(nsIURI** aURI) const
|
||||
nsIContent*
|
||||
FragmentOrElement::GetBindingParent() const
|
||||
{
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
|
||||
if (slots) {
|
||||
return slots->mBindingParent;
|
||||
@@ -1051,7 +974,7 @@ nsXBLBinding*
|
||||
FragmentOrElement::GetXBLBinding() const
|
||||
{
|
||||
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
return slots->mXBLBinding;
|
||||
}
|
||||
@@ -1086,11 +1009,11 @@ FragmentOrElement::SetXBLBinding(nsXBLBinding* aBinding,
|
||||
|
||||
if (aBinding) {
|
||||
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
|
||||
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
|
||||
nsDOMSlots *slots = DOMSlots();
|
||||
slots->mXBLBinding = aBinding;
|
||||
bindingManager->AddBoundContent(this);
|
||||
} else {
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
slots->mXBLBinding = nullptr;
|
||||
}
|
||||
@@ -1105,7 +1028,7 @@ nsIContent*
|
||||
FragmentOrElement::GetXBLInsertionParent() const
|
||||
{
|
||||
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
return slots->mXBLInsertionParent;
|
||||
}
|
||||
@@ -1117,7 +1040,7 @@ FragmentOrElement::GetXBLInsertionParent() const
|
||||
ShadowRoot*
|
||||
FragmentOrElement::GetContainingShadow() const
|
||||
{
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
return slots->mContainingShadow;
|
||||
}
|
||||
@@ -1127,48 +1050,60 @@ FragmentOrElement::GetContainingShadow() const
|
||||
void
|
||||
FragmentOrElement::SetShadowRoot(ShadowRoot* aShadowRoot)
|
||||
{
|
||||
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
|
||||
nsDOMSlots *slots = DOMSlots();
|
||||
slots->mShadowRoot = aShadowRoot;
|
||||
}
|
||||
|
||||
HTMLSlotElement*
|
||||
FragmentOrElement::GetAssignedSlot() const
|
||||
nsTArray<nsIContent*>&
|
||||
FragmentOrElement::DestInsertionPoints()
|
||||
{
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
return slots ? slots->mAssignedSlot.get() : nullptr;
|
||||
nsDOMSlots *slots = DOMSlots();
|
||||
return slots->mDestInsertionPoints;
|
||||
}
|
||||
|
||||
nsIContent*
|
||||
nsIContent::GetContainingShadowHost() const
|
||||
nsTArray<nsIContent*>*
|
||||
FragmentOrElement::GetExistingDestInsertionPoints() const
|
||||
{
|
||||
if (mozilla::dom::ShadowRoot* shadow = GetContainingShadow()) {
|
||||
return shadow->GetHost();
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
return &slots->mDestInsertionPoints;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::SetAssignedSlot(HTMLSlotElement* aSlot)
|
||||
{
|
||||
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
|
||||
slots->mAssignedSlot = aSlot;
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent)
|
||||
{
|
||||
if (aContent) {
|
||||
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
|
||||
nsDOMSlots *slots = DOMSlots();
|
||||
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
|
||||
slots->mXBLInsertionParent = aContent;
|
||||
} else {
|
||||
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
slots->mXBLInsertionParent = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CustomElementData*
|
||||
FragmentOrElement::GetCustomElementData() const
|
||||
{
|
||||
nsDOMSlots *slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
return slots->mCustomElementData;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
FragmentOrElement::SetCustomElementData(CustomElementData* aData)
|
||||
{
|
||||
nsDOMSlots *slots = DOMSlots();
|
||||
MOZ_ASSERT(!slots->mCustomElementData, "Custom element data may not be changed once set.");
|
||||
slots->mCustomElementData = aData;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FragmentOrElement::InsertChildAt(nsIContent* aKid,
|
||||
uint32_t aIndex,
|
||||
@@ -1431,15 +1366,14 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
|
||||
{
|
||||
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
if (slots->mExtendedSlots && tmp->IsElement()) {
|
||||
if (tmp->IsElement()) {
|
||||
Element* elem = tmp->AsElement();
|
||||
for (auto iter = slots->mExtendedSlots->mRegisteredIntersectionObservers.Iter();
|
||||
!iter.Done(); iter.Next()) {
|
||||
for (auto iter = slots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
|
||||
DOMIntersectionObserver* observer = iter.Key();
|
||||
observer->UnlinkTarget(*elem);
|
||||
}
|
||||
}
|
||||
slots->Unlink();
|
||||
slots->Unlink(tmp->IsXULElement());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2004,7 +1938,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
|
||||
{
|
||||
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
slots->Traverse(cb);
|
||||
slots->Traverse(cb, tmp->IsXULElement());
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
@@ -2419,8 +2353,9 @@ FragmentOrElement::SetIsElementInStyleScopeFlagOnShadowTree(bool aInStyleScope)
|
||||
NS_ASSERTION(IsElement(), "calling SetIsElementInStyleScopeFlagOnShadowTree "
|
||||
"on a non-Element is useless");
|
||||
ShadowRoot* shadowRoot = GetShadowRoot();
|
||||
if (shadowRoot) {
|
||||
while (shadowRoot) {
|
||||
shadowRoot->SetIsElementInStyleScopeFlagOnSubtree(aInStyleScope);
|
||||
shadowRoot = shadowRoot->GetOlderShadowRoot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsAttrAndChildArray.h" // member
|
||||
#include "nsCycleCollectionParticipant.h" // NS_DECL_CYCLE_*
|
||||
#include "nsIContent.h" // base class
|
||||
@@ -38,7 +37,6 @@ class nsIURI;
|
||||
namespace mozilla {
|
||||
class DeclarationBlock;
|
||||
namespace dom {
|
||||
struct CustomElementData;
|
||||
class DOMIntersectionObserver;
|
||||
class Element;
|
||||
} // namespace dom
|
||||
@@ -62,7 +60,6 @@ public:
|
||||
// nsIWeakReference
|
||||
NS_DECL_NSIWEAKREFERENCE
|
||||
virtual size_t SizeOfOnlyThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
|
||||
virtual bool IsAlive() const override { return mNode != nullptr; }
|
||||
|
||||
void NoticeNodeDestruction()
|
||||
{
|
||||
@@ -155,13 +152,16 @@ public:
|
||||
virtual void SetXBLBinding(nsXBLBinding* aBinding,
|
||||
nsBindingManager* aOldBindingManager = nullptr) override;
|
||||
virtual ShadowRoot *GetContainingShadow() const override;
|
||||
virtual nsTArray<nsIContent*> &DestInsertionPoints() override;
|
||||
virtual nsTArray<nsIContent*> *GetExistingDestInsertionPoints() const override;
|
||||
virtual void SetShadowRoot(ShadowRoot* aBinding) override;
|
||||
virtual mozilla::dom::HTMLSlotElement* GetAssignedSlot() const override;
|
||||
virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) override;
|
||||
virtual nsIContent *GetXBLInsertionParent() const override;
|
||||
virtual void SetXBLInsertionParent(nsIContent* aContent) override;
|
||||
virtual bool IsLink(nsIURI** aURI) const override;
|
||||
|
||||
virtual CustomElementData *GetCustomElementData() const override;
|
||||
virtual void SetCustomElementData(CustomElementData* aData) override;
|
||||
|
||||
virtual void DestroyContent() override;
|
||||
virtual void SaveSubtreeState() override;
|
||||
|
||||
@@ -241,6 +241,8 @@ protected:
|
||||
nsresult CopyInnerTo(FragmentOrElement* aDest);
|
||||
|
||||
public:
|
||||
// Because of a bug in MS C++ compiler nsDOMSlots must be declared public,
|
||||
// otherwise nsXULElement::nsXULSlots doesn't compile.
|
||||
/**
|
||||
* There are a set of DOM- and scripting-specific instance variables
|
||||
* that may only be instantiated when a content object is accessed
|
||||
@@ -249,13 +251,29 @@ public:
|
||||
* in a side structure that's only allocated when the content is
|
||||
* accessed through the DOM.
|
||||
*/
|
||||
|
||||
class nsExtendedDOMSlots
|
||||
class nsDOMSlots : public nsINode::nsSlots
|
||||
{
|
||||
public:
|
||||
nsExtendedDOMSlots();
|
||||
nsDOMSlots();
|
||||
virtual ~nsDOMSlots();
|
||||
|
||||
~nsExtendedDOMSlots();
|
||||
void Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL);
|
||||
void Unlink(bool aIsXUL);
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
/**
|
||||
* The .style attribute (an interface that forwards to the actual
|
||||
* style rules)
|
||||
* @see nsGenericHTMLElement::GetStyle
|
||||
*/
|
||||
nsCOMPtr<nsICSSDeclaration> mStyle;
|
||||
|
||||
/**
|
||||
* The .dataset attribute.
|
||||
* @see nsGenericHTMLElement::GetDataset
|
||||
*/
|
||||
nsDOMStringMap* mDataset; // [Weak]
|
||||
|
||||
/**
|
||||
* SMIL Overridde style rules (for SMIL animation of CSS properties)
|
||||
@@ -269,17 +287,35 @@ public:
|
||||
RefPtr<mozilla::DeclarationBlock> mSMILOverrideStyleDeclaration;
|
||||
|
||||
/**
|
||||
* The nearest enclosing content node with a binding that created us.
|
||||
* @see FragmentOrElement::GetBindingParent
|
||||
*/
|
||||
nsIContent* mBindingParent; // [Weak]
|
||||
* An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
|
||||
* @see FragmentOrElement::GetAttributes
|
||||
*/
|
||||
RefPtr<nsDOMAttributeMap> mAttributeMap;
|
||||
|
||||
union {
|
||||
/**
|
||||
* The nearest enclosing content node with a binding that created us.
|
||||
* @see FragmentOrElement::GetBindingParent
|
||||
*/
|
||||
nsIContent* mBindingParent; // [Weak]
|
||||
|
||||
/**
|
||||
* The controllers of the XUL Element.
|
||||
*/
|
||||
nsIControllers* mControllers; // [OWNER]
|
||||
};
|
||||
|
||||
/**
|
||||
* The controllers of the XUL Element.
|
||||
*/
|
||||
nsCOMPtr<nsIControllers> mControllers;
|
||||
* An object implementing the .children property for this element.
|
||||
*/
|
||||
RefPtr<nsContentList> mChildrenList;
|
||||
|
||||
/**
|
||||
* An object implementing the .classList property for this element.
|
||||
*/
|
||||
RefPtr<nsDOMTokenList> mClassList;
|
||||
|
||||
/*
|
||||
* An object implementing the .labels property for this element.
|
||||
*/
|
||||
RefPtr<nsLabelsNodeList> mLabelsList;
|
||||
@@ -295,9 +331,10 @@ public:
|
||||
RefPtr<ShadowRoot> mContainingShadow;
|
||||
|
||||
/**
|
||||
* The assigned slot associated with this element.
|
||||
* An array of web component insertion points to which this element
|
||||
* is distributed.
|
||||
*/
|
||||
RefPtr<mozilla::dom::HTMLSlotElement> mAssignedSlot;
|
||||
nsTArray<nsIContent*> mDestInsertionPoints;
|
||||
|
||||
/**
|
||||
* XBL binding installed on the element.
|
||||
@@ -319,55 +356,6 @@ public:
|
||||
*/
|
||||
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>
|
||||
mRegisteredIntersectionObservers;
|
||||
|
||||
/**
|
||||
* For XUL to hold either frameloader or opener.
|
||||
*/
|
||||
nsCOMPtr<nsISupports> mFrameLoaderOrOpener;
|
||||
|
||||
};
|
||||
|
||||
class nsDOMSlots : public nsINode::nsSlots
|
||||
{
|
||||
public:
|
||||
nsDOMSlots();
|
||||
virtual ~nsDOMSlots();
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback &cb);
|
||||
void Unlink();
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
/**
|
||||
* The .style attribute (an interface that forwards to the actual
|
||||
* style rules)
|
||||
* @see nsGenericHTMLElement::GetStyle
|
||||
*/
|
||||
nsCOMPtr<nsICSSDeclaration> mStyle;
|
||||
|
||||
/**
|
||||
* The .dataset attribute.
|
||||
* @see nsGenericHTMLElement::GetDataset
|
||||
*/
|
||||
nsDOMStringMap* mDataset; // [Weak]
|
||||
|
||||
/**
|
||||
* An object implementing nsIDOMMozNamedAttrMap for this content (attributes)
|
||||
* @see FragmentOrElement::GetAttributes
|
||||
*/
|
||||
RefPtr<nsDOMAttributeMap> mAttributeMap;
|
||||
|
||||
/**
|
||||
* An object implementing the .children property for this element.
|
||||
*/
|
||||
RefPtr<nsContentList> mChildrenList;
|
||||
|
||||
/**
|
||||
* An object implementing the .classList property for this element.
|
||||
*/
|
||||
RefPtr<nsDOMTokenList> mClassList;
|
||||
|
||||
mozilla::UniquePtr<nsExtendedDOMSlots> mExtendedSlots;
|
||||
};
|
||||
|
||||
protected:
|
||||
@@ -387,26 +375,6 @@ protected:
|
||||
return static_cast<nsDOMSlots*>(GetExistingSlots());
|
||||
}
|
||||
|
||||
nsExtendedDOMSlots* ExtendedDOMSlots()
|
||||
{
|
||||
nsDOMSlots* slots = DOMSlots();
|
||||
if (!slots->mExtendedSlots) {
|
||||
slots->mExtendedSlots = MakeUnique<nsExtendedDOMSlots>();
|
||||
}
|
||||
|
||||
return slots->mExtendedSlots.get();
|
||||
}
|
||||
|
||||
nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const
|
||||
{
|
||||
nsDOMSlots* slots = GetExistingDOMSlots();
|
||||
if (slots) {
|
||||
return slots->mExtendedSlots.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls SetIsElementInStyleScopeFlagOnSubtree for each shadow tree attached
|
||||
* to this node, which is assumed to be an Element.
|
||||
|
||||
+475
-338
@@ -14,11 +14,9 @@
|
||||
#include "nsIDOMHTMLElement.h"
|
||||
#include "nsIStyleSheetLinkingElement.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLSlotElement.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "mozilla/dom/HTMLContentElement.h"
|
||||
#include "mozilla/dom/HTMLShadowElement.h"
|
||||
#include "nsXBLPrototypeBinding.h"
|
||||
#include "mozilla/BasicEvents.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
|
||||
@@ -29,7 +27,10 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(ShadowRoot)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot,
|
||||
DocumentFragment)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDOMStyleSheets)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPoolHost)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheetList)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOlderShadow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mYoungerShadow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAssociatedBinding)
|
||||
for (auto iter = tmp->mIdentifierMap.ConstIter(); !iter.Done();
|
||||
iter.Next()) {
|
||||
@@ -37,14 +38,18 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot,
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ShadowRoot)
|
||||
if (tmp->GetHost()) {
|
||||
tmp->GetHost()->RemoveMutationObserver(tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ShadowRoot,
|
||||
DocumentFragment)
|
||||
if (tmp->mPoolHost) {
|
||||
tmp->mPoolHost->RemoveMutationObserver(tmp);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDOMStyleSheets)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPoolHost)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mStyleSheetList)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOlderShadow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mYoungerShadow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAssociatedBinding)
|
||||
tmp->mIdentifierMap.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(DocumentFragment)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ShadowRoot)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
|
||||
@@ -54,17 +59,14 @@ NS_INTERFACE_MAP_END_INHERITING(DocumentFragment)
|
||||
NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment)
|
||||
NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment)
|
||||
|
||||
ShadowRoot::ShadowRoot(Element* aElement, bool aClosed,
|
||||
ShadowRoot::ShadowRoot(nsIContent* aContent,
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
nsXBLPrototypeBinding* aProtoBinding)
|
||||
: DocumentFragment(aNodeInfo)
|
||||
, DocumentOrShadowRoot(this)
|
||||
, mProtoBinding(aProtoBinding)
|
||||
, mInsertionPointChanged(false)
|
||||
, mIsComposedDocParticipant(false)
|
||||
: DocumentFragment(aNodeInfo), mPoolHost(aContent),
|
||||
mProtoBinding(aProtoBinding), mShadowElement(nullptr),
|
||||
mInsertionPointChanged(false), mIsComposedDocParticipant(false)
|
||||
{
|
||||
SetHost(aElement);
|
||||
mMode = aClosed ? ShadowRootMode::Closed : ShadowRootMode::Open;
|
||||
SetHost(aContent);
|
||||
|
||||
// Nodes in a shadow tree should never store a value
|
||||
// in the subtree root pointer, nodes in the shadow tree
|
||||
@@ -73,27 +75,29 @@ ShadowRoot::ShadowRoot(Element* aElement, bool aClosed,
|
||||
|
||||
SetFlags(NODE_IS_IN_SHADOW_TREE);
|
||||
|
||||
ExtendedDOMSlots()->mBindingParent = aElement;
|
||||
ExtendedDOMSlots()->mContainingShadow = this;
|
||||
DOMSlots()->mBindingParent = aContent;
|
||||
DOMSlots()->mContainingShadow = this;
|
||||
|
||||
// Add the ShadowRoot as a mutation observer on the host to watch
|
||||
// for mutations because the insertion points in this ShadowRoot
|
||||
// may need to be updated when the host children are modified.
|
||||
GetHost()->AddMutationObserver(this);
|
||||
mPoolHost->AddMutationObserver(this);
|
||||
}
|
||||
|
||||
ShadowRoot::~ShadowRoot()
|
||||
{
|
||||
if (auto* host = GetHost()) {
|
||||
// mHost may have been unlinked or a new ShadowRoot may have been
|
||||
// created, making this one obsolete.
|
||||
host->RemoveMutationObserver(this);
|
||||
if (mPoolHost) {
|
||||
// mPoolHost may have been unlinked or a new ShadowRoot may have been
|
||||
// creating, making this one obsolete.
|
||||
mPoolHost->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
UnsetFlags(NODE_IS_IN_SHADOW_TREE);
|
||||
|
||||
// nsINode destructor expects mSubtreeRoot == this.
|
||||
SetSubtreeRootPointer(this);
|
||||
|
||||
SetHost(nullptr);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
@@ -114,116 +118,13 @@ ShadowRoot::FromNode(nsINode* aNode)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
|
||||
{
|
||||
MOZ_ASSERT(aSlot);
|
||||
|
||||
// Note that if name attribute missing, the slot is a default slot.
|
||||
nsAutoString name;
|
||||
aSlot->GetName(name);
|
||||
|
||||
nsTArray<HTMLSlotElement*>* currentSlots = mSlotMap.LookupOrAdd(name);
|
||||
MOZ_ASSERT(currentSlots);
|
||||
|
||||
HTMLSlotElement* oldSlot = currentSlots->IsEmpty() ?
|
||||
nullptr : currentSlots->ElementAt(0);
|
||||
|
||||
TreeOrderComparator comparator;
|
||||
currentSlots->InsertElementSorted(aSlot, comparator);
|
||||
|
||||
HTMLSlotElement* currentSlot = currentSlots->ElementAt(0);
|
||||
if (currentSlot != aSlot) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool doEnqueueSlotChange = false;
|
||||
if (oldSlot && oldSlot != currentSlot) {
|
||||
// Move assigned nodes from old slot to new slot.
|
||||
const nsTArray<RefPtr<nsINode>>& assignedNodes = oldSlot->AssignedNodes();
|
||||
while (assignedNodes.Length() > 0) {
|
||||
nsINode* assignedNode = assignedNodes[0];
|
||||
|
||||
oldSlot->RemoveAssignedNode(assignedNode);
|
||||
currentSlot->AppendAssignedNode(assignedNode);
|
||||
doEnqueueSlotChange = true;
|
||||
}
|
||||
|
||||
if (doEnqueueSlotChange) {
|
||||
oldSlot->EnqueueSlotChangeEvent();
|
||||
currentSlot->EnqueueSlotChangeEvent();
|
||||
}
|
||||
} else {
|
||||
// Otherwise add appropriate nodes to this slot from the host.
|
||||
for (nsIContent* child = GetHost()->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
nsAutoString slotName;
|
||||
child->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
|
||||
if (child->IsSlotable() && slotName.Equals(name)) {
|
||||
currentSlot->AppendAssignedNode(child);
|
||||
doEnqueueSlotChange = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (doEnqueueSlotChange) {
|
||||
currentSlot->EnqueueSlotChangeEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot)
|
||||
{
|
||||
MOZ_ASSERT(aSlot);
|
||||
|
||||
nsAutoString name;
|
||||
aSlot->GetName(name);
|
||||
|
||||
nsTArray<HTMLSlotElement*>* currentSlots = mSlotMap.Get(name);
|
||||
|
||||
if (currentSlots) {
|
||||
if (currentSlots->Length() == 1) {
|
||||
MOZ_ASSERT(currentSlots->ElementAt(0) == aSlot);
|
||||
mSlotMap.Remove(name);
|
||||
|
||||
if (aSlot->AssignedNodes().Length() > 0) {
|
||||
aSlot->ClearAssignedNodes();
|
||||
aSlot->EnqueueSlotChangeEvent();
|
||||
}
|
||||
} else {
|
||||
bool doEnqueueSlotChange = false;
|
||||
bool doReplaceSlot = currentSlots->ElementAt(0) == aSlot;
|
||||
currentSlots->RemoveElement(aSlot);
|
||||
HTMLSlotElement* replacementSlot = currentSlots->ElementAt(0);
|
||||
|
||||
// Move assigned nodes from removed slot to the next slot in
|
||||
// tree order with the same name.
|
||||
if (doReplaceSlot) {
|
||||
const nsTArray<RefPtr<nsINode>>& assignedNodes = aSlot->AssignedNodes();
|
||||
while (assignedNodes.Length() > 0) {
|
||||
nsINode* assignedNode = assignedNodes[0];
|
||||
|
||||
aSlot->RemoveAssignedNode(assignedNode);
|
||||
replacementSlot->AppendAssignedNode(assignedNode);
|
||||
doEnqueueSlotChange = true;
|
||||
}
|
||||
|
||||
if (doEnqueueSlotChange) {
|
||||
aSlot->EnqueueSlotChangeEvent();
|
||||
replacementSlot->EnqueueSlotChangeEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::StyleSheetChanged()
|
||||
{
|
||||
mProtoBinding->FlushSkinSheets();
|
||||
|
||||
if (nsIPresShell* shell = OwnerDoc()->GetShell()) {
|
||||
nsIPresShell* shell = OwnerDoc()->GetShell();
|
||||
if (shell) {
|
||||
OwnerDoc()->BeginUpdate(UPDATE_STYLE);
|
||||
shell->RecordShadowStyleChange(this);
|
||||
OwnerDoc()->EndUpdate(UPDATE_STYLE);
|
||||
@@ -241,30 +142,16 @@ ShadowRoot::InsertSheet(StyleSheet* aSheet,
|
||||
|
||||
linkingElement->SetStyleSheet(aSheet); // This sets the ownerNode on the sheet
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(mProtoBinding->SheetCount() == DocumentOrShadowRoot::SheetCount());
|
||||
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
||||
// FIXME(emilio, bug 1425759): For now we keep them duplicated, the proto
|
||||
// binding will disappear soon (tm).
|
||||
{
|
||||
size_t i = 0;
|
||||
for (RefPtr<StyleSheet>& sheet : mStyleSheets) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(sheet.get() == mProtoBinding->StyleSheetAt(i++));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find the correct position to insert into the style sheet list (must
|
||||
// be in tree order).
|
||||
for (size_t i = 0; i <= SheetCount(); i++) {
|
||||
if (i == SheetCount()) {
|
||||
AppendStyleSheet(*aSheet);
|
||||
for (size_t i = 0; i <= mProtoBinding->SheetCount(); i++) {
|
||||
if (i == mProtoBinding->SheetCount()) {
|
||||
mProtoBinding->AppendStyleSheet(aSheet);
|
||||
break;
|
||||
}
|
||||
|
||||
nsINode* sheetOwningNode = SheetAt(i)->GetOwnerNode();
|
||||
nsINode* sheetOwningNode = mProtoBinding->StyleSheetAt(i)->GetOwnerNode();
|
||||
if (nsContentUtils::PositionIsBefore(aLinkingContent, sheetOwningNode)) {
|
||||
InsertSheetAt(i, *aSheet);
|
||||
mProtoBinding->InsertStyleSheetAt(i, aSheet);
|
||||
break;
|
||||
}
|
||||
@@ -279,17 +166,48 @@ void
|
||||
ShadowRoot::RemoveSheet(StyleSheet* aSheet)
|
||||
{
|
||||
mProtoBinding->RemoveStyleSheet(aSheet);
|
||||
DocumentOrShadowRoot::RemoveSheet(*aSheet);
|
||||
|
||||
if (aSheet->IsApplicable()) {
|
||||
StyleSheetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
Element*
|
||||
ShadowRoot::GetElementById(const nsAString& aElementId)
|
||||
{
|
||||
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId);
|
||||
return entry ? entry->GetIdElement() : nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
ShadowRoot::GetElementsByTagName(const nsAString& aTagName)
|
||||
{
|
||||
return NS_GetContentList(this, kNameSpaceID_Unknown, aTagName);
|
||||
}
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
ShadowRoot::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName)
|
||||
{
|
||||
int32_t nameSpaceId = kNameSpaceID_Wildcard;
|
||||
|
||||
if (!aNamespaceURI.EqualsLiteral("*")) {
|
||||
nsresult rv =
|
||||
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
|
||||
nameSpaceId);
|
||||
NS_ENSURE_SUCCESS(rv, nullptr);
|
||||
}
|
||||
|
||||
NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
|
||||
|
||||
return NS_GetContentList(this, nameSpaceId, aLocalName);
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::AddToIdTable(Element* aElement, nsIAtom* aId)
|
||||
{
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.PutEntry(aId);
|
||||
nsIdentifierMapEntry *entry =
|
||||
mIdentifierMap.PutEntry(nsDependentAtomString(aId));
|
||||
if (entry) {
|
||||
entry->AddIdElement(aElement);
|
||||
}
|
||||
@@ -298,7 +216,8 @@ ShadowRoot::AddToIdTable(Element* aElement, nsIAtom* aId)
|
||||
void
|
||||
ShadowRoot::RemoveFromIdTable(Element* aElement, nsIAtom* aId)
|
||||
{
|
||||
nsIdentifierMapEntry* entry = mIdentifierMap.GetEntry(aId);
|
||||
nsIdentifierMapEntry *entry =
|
||||
mIdentifierMap.GetEntry(nsDependentAtomString(aId));
|
||||
if (entry) {
|
||||
entry->RemoveIdElement(aElement);
|
||||
if (entry->IsEmpty()) {
|
||||
@@ -307,164 +226,244 @@ ShadowRoot::RemoveFromIdTable(Element* aElement, nsIAtom* aId)
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
ShadowRoot::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
already_AddRefed<nsContentList>
|
||||
ShadowRoot::GetElementsByClassName(const nsAString& aClasses)
|
||||
{
|
||||
aVisitor.mCanHandle = true;
|
||||
aVisitor.mRootOfClosedTree = IsClosed();
|
||||
|
||||
// https://dom.spec.whatwg.org/#ref-for-get-the-parent%E2%91%A6
|
||||
if (!aVisitor.mEvent->mFlags.mComposed) {
|
||||
nsCOMPtr<nsIContent> originalTarget =
|
||||
do_QueryInterface(aVisitor.mEvent->mOriginalTarget);
|
||||
if (originalTarget->GetContainingShadow() == this) {
|
||||
// If we do stop propagation, we still want to propagate
|
||||
// the event to chrome (nsPIDOMWindow::GetParentTarget()).
|
||||
// The load event is special in that we don't ever propagate it
|
||||
// to chrome.
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = OwnerDoc()->GetWindow();
|
||||
EventTarget* parentTarget = win && aVisitor.mEvent->mMessage != eLoad
|
||||
? win->GetParentTarget() : nullptr;
|
||||
|
||||
aVisitor.SetParentTarget(parentTarget, true);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
nsIContent* shadowHost = GetHost();
|
||||
aVisitor.SetParentTarget(shadowHost, false);
|
||||
|
||||
if (aVisitor.mOriginalTargetIsInAnon) {
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(aVisitor.mEvent->mTarget));
|
||||
if (content && content->GetBindingParent() == shadowHost) {
|
||||
aVisitor.mEventTargetAtParent = shadowHost;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return nsContentUtils::GetElementsByClassName(this, aClasses);
|
||||
}
|
||||
|
||||
const HTMLSlotElement*
|
||||
ShadowRoot::AssignSlotFor(nsIContent* aContent)
|
||||
void
|
||||
ShadowRoot::AddInsertionPoint(HTMLContentElement* aInsertionPoint)
|
||||
{
|
||||
nsAutoString slotName;
|
||||
// Note that if slot attribute is missing, assign it to the first default
|
||||
// slot, if exists.
|
||||
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
|
||||
nsTArray<HTMLSlotElement*>* slots = mSlotMap.Get(slotName);
|
||||
if (!slots) {
|
||||
return nullptr;
|
||||
TreeOrderComparator comparator;
|
||||
mInsertionPoints.InsertElementSorted(aInsertionPoint, comparator);
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::RemoveInsertionPoint(HTMLContentElement* aInsertionPoint)
|
||||
{
|
||||
mInsertionPoints.RemoveElement(aInsertionPoint);
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::SetYoungerShadow(ShadowRoot* aYoungerShadow)
|
||||
{
|
||||
mYoungerShadow = aYoungerShadow;
|
||||
mYoungerShadow->mOlderShadow = this;
|
||||
|
||||
ChangePoolHost(mYoungerShadow->GetShadowElement());
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::RemoveDestInsertionPoint(nsIContent* aInsertionPoint,
|
||||
nsTArray<nsIContent*>& aDestInsertionPoints)
|
||||
{
|
||||
// Remove the insertion point from the destination insertion points.
|
||||
// Also remove all succeeding insertion points because it is no longer
|
||||
// possible for the content to be distributed into deeper node trees.
|
||||
int32_t index = aDestInsertionPoints.IndexOf(aInsertionPoint);
|
||||
|
||||
// It's possible that we already removed the insertion point while processing
|
||||
// other insertion point removals.
|
||||
if (index >= 0) {
|
||||
aDestInsertionPoints.SetLength(index);
|
||||
}
|
||||
}
|
||||
|
||||
HTMLSlotElement* slot = slots->ElementAt(0);
|
||||
MOZ_ASSERT(slot);
|
||||
|
||||
// Find the appropriate position in the assigned node list for the
|
||||
// newly assigned content.
|
||||
const nsTArray<RefPtr<nsINode>>& assignedNodes = slot->AssignedNodes();
|
||||
nsIContent* currentContent = GetHost()->GetFirstChild();
|
||||
bool indexFound = false;
|
||||
uint32_t insertionIndex;
|
||||
for (uint32_t i = 0; i < assignedNodes.Length(); i++) {
|
||||
// Seek through the host's explicit children until the
|
||||
// assigned content is found.
|
||||
while (currentContent && currentContent != assignedNodes[i]) {
|
||||
if (currentContent == aContent) {
|
||||
indexFound = true;
|
||||
insertionIndex = i;
|
||||
void
|
||||
ShadowRoot::DistributeSingleNode(nsIContent* aContent)
|
||||
{
|
||||
// Find the insertion point to which the content belongs.
|
||||
HTMLContentElement* insertionPoint = nullptr;
|
||||
for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
|
||||
if (mInsertionPoints[i]->Match(aContent)) {
|
||||
if (mInsertionPoints[i]->MatchedNodes().Contains(aContent)) {
|
||||
// Node is already matched into the insertion point. We are done.
|
||||
return;
|
||||
}
|
||||
|
||||
currentContent = currentContent->GetNextSibling();
|
||||
}
|
||||
|
||||
if (indexFound) {
|
||||
// Matching may cause the insertion point to drop fallback content.
|
||||
if (mInsertionPoints[i]->MatchedNodes().IsEmpty() &&
|
||||
static_cast<nsINode*>(mInsertionPoints[i])->GetFirstChild()) {
|
||||
// This match will cause the insertion point to drop all fallback
|
||||
// content and used matched nodes instead. Give up on the optimization
|
||||
// and just distribute all nodes.
|
||||
DistributeAllNodes();
|
||||
return;
|
||||
}
|
||||
insertionPoint = mInsertionPoints[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (indexFound) {
|
||||
slot->InsertAssignedNode(insertionIndex, aContent);
|
||||
} else {
|
||||
slot->AppendAssignedNode(aContent);
|
||||
}
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
const HTMLSlotElement*
|
||||
ShadowRoot::UnassignSlotFor(nsIContent* aNode, const nsAString& aSlotName)
|
||||
{
|
||||
// Find the insertion point to which the content belongs. Note that if slot
|
||||
// attribute is missing, unassign it from the first default slot, if exists.
|
||||
nsTArray<HTMLSlotElement*>* slots = mSlotMap.Get(aSlotName);
|
||||
if (!slots) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
HTMLSlotElement* slot = slots->ElementAt(0);
|
||||
MOZ_ASSERT(slot);
|
||||
|
||||
if (!slot->AssignedNodes().Contains(aNode)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
slot->RemoveAssignedNode(aNode);
|
||||
return slot;
|
||||
}
|
||||
|
||||
bool
|
||||
ShadowRoot::MaybeReassignElement(Element* aElement,
|
||||
const nsAttrValue* aOldValue)
|
||||
{
|
||||
nsIContent* parent = aElement->GetParent();
|
||||
if (parent && parent == GetHost()) {
|
||||
const HTMLSlotElement* oldSlot = UnassignSlotFor(aElement,
|
||||
aOldValue ? aOldValue->GetStringValue() : EmptyString());
|
||||
const HTMLSlotElement* newSlot = AssignSlotFor(aElement);
|
||||
|
||||
if (oldSlot != newSlot) {
|
||||
if (oldSlot) {
|
||||
oldSlot->EnqueueSlotChangeEvent();
|
||||
// Find the index into the insertion point.
|
||||
if (insertionPoint) {
|
||||
nsCOMArray<nsIContent>& matchedNodes = insertionPoint->MatchedNodes();
|
||||
// Find the appropriate position in the matched node list for the
|
||||
// newly distributed content.
|
||||
bool isIndexFound = false;
|
||||
MOZ_ASSERT(mPoolHost, "Where did the content come from if there is no pool host?");
|
||||
ExplicitChildIterator childIterator(mPoolHost);
|
||||
for (uint32_t i = 0; i < matchedNodes.Length(); i++) {
|
||||
// Seek through the host's explicit children until the inserted content
|
||||
// is found or when the current matched node is reached.
|
||||
if (childIterator.Seek(aContent, matchedNodes[i])) {
|
||||
// aContent was found before the current matched node.
|
||||
insertionPoint->InsertMatchedNode(i, aContent);
|
||||
isIndexFound = true;
|
||||
break;
|
||||
}
|
||||
if (newSlot) {
|
||||
newSlot->EnqueueSlotChangeEvent();
|
||||
}
|
||||
|
||||
if (!isIndexFound) {
|
||||
// We have still not found an index in the insertion point,
|
||||
// thus it must be at the end.
|
||||
MOZ_ASSERT(childIterator.Seek(aContent, nullptr),
|
||||
"Trying to match a node that is not a candidate to be matched");
|
||||
insertionPoint->AppendMatchedNode(aContent);
|
||||
}
|
||||
|
||||
// Handle the case where the parent of the insertion point is a ShadowRoot
|
||||
// that is projected into the younger ShadowRoot's shadow insertion point.
|
||||
// The node distributed into the insertion point must be reprojected
|
||||
// to the shadow insertion point.
|
||||
if (insertionPoint->GetParent() == this &&
|
||||
mYoungerShadow && mYoungerShadow->GetShadowElement()) {
|
||||
mYoungerShadow->GetShadowElement()->DistributeSingleNode(aContent);
|
||||
}
|
||||
|
||||
// Handle the case where the parent of the insertion point has a ShadowRoot.
|
||||
// The node distributed into the insertion point must be reprojected to the
|
||||
// insertion points of the parent's ShadowRoot.
|
||||
ShadowRoot* parentShadow = insertionPoint->GetParent()->GetShadowRoot();
|
||||
if (parentShadow) {
|
||||
parentShadow->DistributeSingleNode(aContent);
|
||||
}
|
||||
|
||||
// Handle the case where the parent of the insertion point is the <shadow>
|
||||
// element. The node distributed into the insertion point must be reprojected
|
||||
// into the older ShadowRoot's insertion points.
|
||||
if (mShadowElement && mShadowElement == insertionPoint->GetParent()) {
|
||||
ShadowRoot* olderShadow = mShadowElement->GetOlderShadowRoot();
|
||||
if (olderShadow) {
|
||||
olderShadow->DistributeSingleNode(aContent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::DistributionChanged()
|
||||
ShadowRoot::RemoveDistributedNode(nsIContent* aContent)
|
||||
{
|
||||
// FIXME(emilio): We could be more granular in a bunch of cases.
|
||||
auto* host = GetHost();
|
||||
if (!host || !host->IsInComposedDoc()) {
|
||||
return;
|
||||
}
|
||||
// Find insertion point containing the content and remove the node.
|
||||
for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
|
||||
if (mInsertionPoints[i]->MatchedNodes().Contains(aContent)) {
|
||||
// Removing the matched node may cause the insertion point to use
|
||||
// fallback content.
|
||||
if (mInsertionPoints[i]->MatchedNodes().Length() == 1 &&
|
||||
static_cast<nsINode*>(mInsertionPoints[i])->GetFirstChild()) {
|
||||
// Removing the matched node will cause fallback content to be
|
||||
// used instead. Give up optimization and distribute all nodes.
|
||||
DistributeAllNodes();
|
||||
return;
|
||||
}
|
||||
|
||||
auto* shell = OwnerDoc()->GetShell();
|
||||
if (!shell) {
|
||||
return;
|
||||
}
|
||||
mInsertionPoints[i]->RemoveMatchedNode(aContent);
|
||||
|
||||
shell->DestroyFramesForAndRestyle(host);
|
||||
// Handle the case where the parent of the insertion point is a ShadowRoot
|
||||
// that is projected into the younger ShadowRoot's shadow insertion point.
|
||||
// The removed node needs to be removed from the shadow insertion point.
|
||||
if (mInsertionPoints[i]->GetParent() == this) {
|
||||
if (mYoungerShadow && mYoungerShadow->GetShadowElement()) {
|
||||
mYoungerShadow->GetShadowElement()->RemoveDistributedNode(aContent);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the case where the parent of the insertion point has a ShadowRoot.
|
||||
// The removed node needs to be removed from the insertion points of the
|
||||
// parent's ShadowRoot.
|
||||
ShadowRoot* parentShadow = mInsertionPoints[i]->GetParent()->GetShadowRoot();
|
||||
if (parentShadow) {
|
||||
parentShadow->RemoveDistributedNode(aContent);
|
||||
}
|
||||
|
||||
// Handle the case where the parent of the insertion point is the <shadow>
|
||||
// element. The removed node must be removed from the older ShadowRoot's
|
||||
// insertion points.
|
||||
if (mShadowElement && mShadowElement == mInsertionPoints[i]->GetParent()) {
|
||||
ShadowRoot* olderShadow = mShadowElement->GetOlderShadowRoot();
|
||||
if (olderShadow) {
|
||||
olderShadow->RemoveDistributedNode(aContent);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::DistributeAllNodes()
|
||||
{
|
||||
//XXX Handle <slot>.
|
||||
// Create node pool.
|
||||
nsTArray<nsIContent*> nodePool;
|
||||
|
||||
DistributionChanged();
|
||||
}
|
||||
// Make sure there is a pool host, an older shadow may not have
|
||||
// one if the younger shadow does not have a <shadow> element.
|
||||
if (mPoolHost) {
|
||||
ExplicitChildIterator childIterator(mPoolHost);
|
||||
for (nsIContent* content = childIterator.GetNextChild();
|
||||
content;
|
||||
content = childIterator.GetNextChild()) {
|
||||
nodePool.AppendElement(content);
|
||||
}
|
||||
}
|
||||
|
||||
Element*
|
||||
ShadowRoot::GetActiveElement()
|
||||
{
|
||||
return GetRetargetedFocusedElement();
|
||||
nsTArray<ShadowRoot*> shadowsToUpdate;
|
||||
|
||||
for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
|
||||
mInsertionPoints[i]->ClearMatchedNodes();
|
||||
// Assign matching nodes from node pool.
|
||||
for (uint32_t j = 0; j < nodePool.Length(); j++) {
|
||||
if (mInsertionPoints[i]->Match(nodePool[j])) {
|
||||
mInsertionPoints[i]->AppendMatchedNode(nodePool[j]);
|
||||
nodePool.RemoveElementAt(j--);
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of instances where the content insertion point is distributed
|
||||
// (parent of insertion point has a ShadowRoot).
|
||||
nsIContent* insertionParent = mInsertionPoints[i]->GetParent();
|
||||
MOZ_ASSERT(insertionParent, "The only way for an insertion point to be in the"
|
||||
"mInsertionPoints array is to be a descendant of a"
|
||||
"ShadowRoot, in which case, it should have a parent");
|
||||
|
||||
// If the parent of the insertion point has a ShadowRoot, the nodes distributed
|
||||
// to the insertion point must be reprojected to the insertion points of the
|
||||
// parent's ShadowRoot.
|
||||
ShadowRoot* parentShadow = insertionParent->GetShadowRoot();
|
||||
if (parentShadow && !shadowsToUpdate.Contains(parentShadow)) {
|
||||
shadowsToUpdate.AppendElement(parentShadow);
|
||||
}
|
||||
}
|
||||
|
||||
// If there is a shadow insertion point in this ShadowRoot, the children
|
||||
// of the shadow insertion point needs to be distributed into the insertion
|
||||
// points of the older ShadowRoot.
|
||||
if (mShadowElement && mOlderShadow) {
|
||||
mOlderShadow->DistributeAllNodes();
|
||||
}
|
||||
|
||||
// If there is a younger ShadowRoot with a shadow insertion point,
|
||||
// then the children of this ShadowRoot needs to be distributed to
|
||||
// the younger ShadowRoot's shadow insertion point.
|
||||
if (mYoungerShadow && mYoungerShadow->GetShadowElement()) {
|
||||
mYoungerShadow->GetShadowElement()->DistributeAllNodes();
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < shadowsToUpdate.Length(); i++) {
|
||||
shadowsToUpdate[i]->DistributeAllNodes();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -508,6 +507,105 @@ ShadowRoot::SetApplyAuthorStyles(bool aApplyAuthorStyles)
|
||||
}
|
||||
}
|
||||
|
||||
StyleSheetList*
|
||||
ShadowRoot::StyleSheets()
|
||||
{
|
||||
if (!mStyleSheetList) {
|
||||
mStyleSheetList = new ShadowRootStyleSheetList(this);
|
||||
}
|
||||
|
||||
return mStyleSheetList;
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::SetShadowElement(HTMLShadowElement* aShadowElement)
|
||||
{
|
||||
// If there is already a shadow element point, remove
|
||||
// the projected shadow because it is no longer an insertion
|
||||
// point.
|
||||
if (mShadowElement) {
|
||||
mShadowElement->SetProjectedShadow(nullptr);
|
||||
}
|
||||
|
||||
if (mOlderShadow) {
|
||||
// Nodes for distribution will come from the new shadow element.
|
||||
mOlderShadow->ChangePoolHost(aShadowElement);
|
||||
}
|
||||
|
||||
// Set the new shadow element to project the older ShadowRoot because
|
||||
// it is the current shadow insertion point.
|
||||
mShadowElement = aShadowElement;
|
||||
if (mShadowElement) {
|
||||
mShadowElement->SetProjectedShadow(mOlderShadow);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::ChangePoolHost(nsIContent* aNewHost)
|
||||
{
|
||||
if (mPoolHost) {
|
||||
mPoolHost->RemoveMutationObserver(this);
|
||||
}
|
||||
|
||||
// Clear the nodes matched to content insertion points
|
||||
// because it is no longer relevant.
|
||||
for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
|
||||
mInsertionPoints[i]->ClearMatchedNodes();
|
||||
}
|
||||
|
||||
mPoolHost = aNewHost;
|
||||
if (mPoolHost) {
|
||||
mPoolHost->AddMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ShadowRoot::IsShadowInsertionPoint(nsIContent* aContent)
|
||||
{
|
||||
if (!aContent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HTMLShadowElement* shadowElem = HTMLShadowElement::FromContent(aContent);
|
||||
return shadowElem && shadowElem->IsInsertionPoint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the web components pool population algorithm
|
||||
* on the host would contain |aContent|. This function ignores
|
||||
* insertion points in the pool, thus should only be used to
|
||||
* test nodes that have not yet been distributed.
|
||||
*/
|
||||
bool
|
||||
ShadowRoot::IsPooledNode(nsIContent* aContent, nsIContent* aContainer,
|
||||
nsIContent* aHost)
|
||||
{
|
||||
if (nsContentUtils::IsContentInsertionPoint(aContent) ||
|
||||
IsShadowInsertionPoint(aContent)) {
|
||||
// Insertion points never end up in the pool.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aContainer == aHost &&
|
||||
nsContentUtils::IsInSameAnonymousTree(aContainer, aContent)) {
|
||||
// Children of the host will end up in the pool. We check to ensure
|
||||
// that the content is in the same anonymous tree as the container
|
||||
// because anonymous content may report its container as the host
|
||||
// but it may not be in the host's child list.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (aContainer) {
|
||||
// Fallback content will end up in pool if its parent is a child of the host.
|
||||
HTMLContentElement* content = HTMLContentElement::FromContent(aContainer);
|
||||
return content && content->IsInsertionPoint() &&
|
||||
content->MatchedNodes().IsEmpty() &&
|
||||
aContainer->GetParentNode() == aHost;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::AttributeChanged(nsIDocument* aDocument,
|
||||
Element* aElement,
|
||||
@@ -516,26 +614,13 @@ ShadowRoot::AttributeChanged(nsIDocument* aDocument,
|
||||
int32_t aModType,
|
||||
const nsAttrValue* aOldValue)
|
||||
{
|
||||
if (aNameSpaceID != kNameSpaceID_None || aAttribute != nsGkAtoms::slot) {
|
||||
if (!IsPooledNode(aElement, aElement->GetParent(), mPoolHost)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Attributes may change insertion point matching, find its new distribution.
|
||||
if (!MaybeReassignElement(aElement, aOldValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aElement->IsInComposedDoc()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* shell = OwnerDoc()->GetShell();
|
||||
if (!shell) {
|
||||
return;
|
||||
}
|
||||
|
||||
//XXX optimize this!
|
||||
shell->DestroyFramesForAndRestyle(aElement);
|
||||
RemoveDistributedNode(aElement);
|
||||
DistributeSingleNode(aElement);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -544,10 +629,29 @@ ShadowRoot::ContentAppended(nsIDocument* aDocument,
|
||||
nsIContent* aFirstNewContent,
|
||||
int32_t aNewIndexInContainer)
|
||||
{
|
||||
for (nsIContent* content = aFirstNewContent;
|
||||
content;
|
||||
content = content->GetNextSibling()) {
|
||||
ContentInserted(aDocument, aContainer, aFirstNewContent, aNewIndexInContainer);
|
||||
if (mInsertionPointChanged) {
|
||||
DistributeAllNodes();
|
||||
mInsertionPointChanged = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Watch for new nodes added to the pool because the node
|
||||
// may need to be added to an insertion point.
|
||||
nsIContent* currentChild = aFirstNewContent;
|
||||
while (currentChild) {
|
||||
// Add insertion point to destination insertion points of fallback content.
|
||||
if (nsContentUtils::IsContentInsertionPoint(aContainer)) {
|
||||
HTMLContentElement* content = HTMLContentElement::FromContent(aContainer);
|
||||
if (content->MatchedNodes().IsEmpty()) {
|
||||
currentChild->DestInsertionPoints().AppendElement(aContainer);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsPooledNode(currentChild, aContainer, mPoolHost)) {
|
||||
DistributeSingleNode(currentChild);
|
||||
}
|
||||
|
||||
currentChild = currentChild->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -557,30 +661,24 @@ ShadowRoot::ContentInserted(nsIDocument* aDocument,
|
||||
nsIContent* aChild,
|
||||
int32_t aIndexInContainer)
|
||||
{
|
||||
// Check to ensure that the content is in the same anonymous tree
|
||||
// as the container because anonymous content may report its container
|
||||
// as the host but it may not be in the host's child list.
|
||||
if (!nsContentUtils::IsInSameAnonymousTree(aContainer, aChild)) {
|
||||
if (mInsertionPointChanged) {
|
||||
DistributeAllNodes();
|
||||
mInsertionPointChanged = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aChild->IsSlotable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aContainer && aContainer == GetHost()) {
|
||||
if (const HTMLSlotElement* slot = AssignSlotFor(aChild)) {
|
||||
slot->EnqueueSlotChangeEvent();
|
||||
// Watch for new nodes added to the pool because the node
|
||||
// may need to be added to an insertion point.
|
||||
if (IsPooledNode(aChild, aContainer, mPoolHost)) {
|
||||
// Add insertion point to destination insertion points of fallback content.
|
||||
if (nsContentUtils::IsContentInsertionPoint(aContainer)) {
|
||||
HTMLContentElement* content = HTMLContentElement::FromContent(aContainer);
|
||||
if (content->MatchedNodes().IsEmpty()) {
|
||||
aChild->DestInsertionPoints().AppendElement(aContainer);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If parent's root is a shadow root, and parent is a slot whose assigned
|
||||
// nodes is the empty list, then run signal a slot change for parent.
|
||||
HTMLSlotElement* slot = HTMLSlotElement::FromContentOrNull(aContainer);
|
||||
if (slot && slot->GetContainingShadow() == this &&
|
||||
slot->AssignedNodes().IsEmpty()) {
|
||||
slot->EnqueueSlotChangeEvent();
|
||||
DistributeSingleNode(aChild);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,32 +689,25 @@ ShadowRoot::ContentRemoved(nsIDocument* aDocument,
|
||||
int32_t aIndexInContainer,
|
||||
nsIContent* aPreviousSibling)
|
||||
{
|
||||
// Check to ensure that the content is in the same anonymous tree
|
||||
// as the container because anonymous content may report its container
|
||||
// as the host but it may not be in the host's child list.
|
||||
if (!nsContentUtils::IsInSameAnonymousTree(aContainer, aChild)) {
|
||||
if (mInsertionPointChanged) {
|
||||
DistributeAllNodes();
|
||||
mInsertionPointChanged = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!aChild->IsSlotable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aContainer && aContainer == GetHost()) {
|
||||
nsAutoString slotName;
|
||||
aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
|
||||
if (const HTMLSlotElement* slot = UnassignSlotFor(aChild, slotName)) {
|
||||
slot->EnqueueSlotChangeEvent();
|
||||
// Clear destination insertion points for removed
|
||||
// fallback content.
|
||||
if (nsContentUtils::IsContentInsertionPoint(aContainer)) {
|
||||
HTMLContentElement* content = HTMLContentElement::FromContent(aContainer);
|
||||
if (content->MatchedNodes().IsEmpty()) {
|
||||
aChild->DestInsertionPoints().Clear();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If parent's root is a shadow root, and parent is a slot whose assigned
|
||||
// nodes is the empty list, then run signal a slot change for parent.
|
||||
HTMLSlotElement* slot = HTMLSlotElement::FromContentOrNull(aContainer);
|
||||
if (slot && slot->GetContainingShadow() == this &&
|
||||
slot->AssignedNodes().IsEmpty()) {
|
||||
slot->EnqueueSlotChangeEvent();
|
||||
// Watch for node that is removed from the pool because
|
||||
// it may need to be removed from an insertion point.
|
||||
if (IsPooledNode(aChild, aContainer, mPoolHost)) {
|
||||
RemoveDistributedNode(aChild);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,3 +717,49 @@ ShadowRoot::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
|
||||
*aResult = nullptr;
|
||||
return NS_ERROR_DOM_DATA_CLONE_ERR;
|
||||
}
|
||||
|
||||
void
|
||||
ShadowRoot::DestroyContent()
|
||||
{
|
||||
if (mOlderShadow) {
|
||||
mOlderShadow->DestroyContent();
|
||||
}
|
||||
DocumentFragment::DestroyContent();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList, StyleSheetList,
|
||||
mShadowRoot)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList)
|
||||
NS_INTERFACE_MAP_END_INHERITING(StyleSheetList)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
|
||||
NS_IMPL_RELEASE_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
|
||||
|
||||
ShadowRootStyleSheetList::ShadowRootStyleSheetList(ShadowRoot* aShadowRoot)
|
||||
: mShadowRoot(aShadowRoot)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ShadowRootStyleSheetList);
|
||||
}
|
||||
|
||||
ShadowRootStyleSheetList::~ShadowRootStyleSheetList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ShadowRootStyleSheetList);
|
||||
}
|
||||
|
||||
StyleSheet*
|
||||
ShadowRootStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
|
||||
{
|
||||
aFound = aIndex < mShadowRoot->mProtoBinding->SheetCount();
|
||||
if (!aFound) {
|
||||
return nullptr;
|
||||
}
|
||||
return mShadowRoot->mProtoBinding->StyleSheetAt(aIndex);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ShadowRootStyleSheetList::Length()
|
||||
{
|
||||
return mShadowRoot->mProtoBinding->SheetCount();
|
||||
}
|
||||
|
||||
+115
-70
@@ -8,30 +8,30 @@
|
||||
#define mozilla_dom_shadowroot_h__
|
||||
|
||||
#include "mozilla/dom/DocumentFragment.h"
|
||||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "nsIdentifierMapEntry.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsXBLBinding.h"
|
||||
#include "nsDocument.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIContent;
|
||||
class nsXBLPrototypeBinding;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class EventChainPreVisitor;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class Element;
|
||||
class HTMLContentElement;
|
||||
class HTMLShadowElement;
|
||||
class ShadowRootStyleSheetList;
|
||||
|
||||
class ShadowRoot final : public DocumentFragment,
|
||||
public DocumentOrShadowRoot,
|
||||
public nsStubMutationObserver
|
||||
{
|
||||
friend class ShadowRootStyleSheetList;
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot,
|
||||
DocumentFragment)
|
||||
@@ -42,30 +42,46 @@ public:
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
ShadowRoot(Element* aElement, bool aClosed,
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
ShadowRoot(nsIContent* aContent, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
nsXBLPrototypeBinding* aProtoBinding);
|
||||
|
||||
// Shadow DOM v1
|
||||
Element* Host();
|
||||
ShadowRootMode Mode() const
|
||||
{
|
||||
return mMode;
|
||||
}
|
||||
bool IsClosed() const
|
||||
{
|
||||
return mMode == ShadowRootMode::Closed;
|
||||
}
|
||||
|
||||
// [deprecated] Shadow DOM v0
|
||||
void AddToIdTable(Element* aElement, nsIAtom* aId);
|
||||
void RemoveFromIdTable(Element* aElement, nsIAtom* aId);
|
||||
void InsertSheet(StyleSheet* aSheet, nsIContent* aLinkingContent);
|
||||
void RemoveSheet(StyleSheet* aSheet);
|
||||
bool ApplyAuthorStyles();
|
||||
void SetApplyAuthorStyles(bool aApplyAuthorStyles);
|
||||
StyleSheetList* StyleSheets()
|
||||
{
|
||||
return &DocumentOrShadowRoot::EnsureDOMStyleSheets();
|
||||
}
|
||||
StyleSheetList* StyleSheets();
|
||||
HTMLShadowElement* GetShadowElement() { return mShadowElement; }
|
||||
|
||||
/**
|
||||
* Sets the current shadow insertion point where the older
|
||||
* ShadowRoot will be projected.
|
||||
*/
|
||||
void SetShadowElement(HTMLShadowElement* aShadowElement);
|
||||
|
||||
/**
|
||||
* Change the node that populates the distribution pool with
|
||||
* its children. This is distinct from the ShadowRoot host described
|
||||
* in the specifications. The ShadowRoot host is the element
|
||||
* which created this ShadowRoot and does not change. The pool host
|
||||
* is the same as the ShadowRoot host if this is the youngest
|
||||
* ShadowRoot. If this is an older ShadowRoot, the pool host is
|
||||
* the <shadow> element in the younger ShadowRoot (if it exists).
|
||||
*/
|
||||
void ChangePoolHost(nsIContent* aNewHost);
|
||||
|
||||
/**
|
||||
* Distributes a single explicit child of the pool host to the content
|
||||
* insertion points in this ShadowRoot.
|
||||
*/
|
||||
void DistributeSingleNode(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Removes a single explicit child of the pool host from the content
|
||||
* insertion points in this ShadowRoot.
|
||||
*/
|
||||
void RemoveDistributedNode(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Distributes all the explicit children of the pool host to the content
|
||||
@@ -73,57 +89,43 @@ public:
|
||||
*/
|
||||
void DistributeAllNodes();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Try to reassign an element to a slot and returns whether the assignment
|
||||
* changed.
|
||||
*/
|
||||
bool MaybeReassignElement(Element* aElement, const nsAttrValue* aOldValue);
|
||||
|
||||
/**
|
||||
* Try to assign aContent to a slot in the shadow tree, returns the assigned
|
||||
* slot if found.
|
||||
*/
|
||||
const HTMLSlotElement* AssignSlotFor(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Unassign aContent from the assigned slot in the shadow tree, returns the
|
||||
* assigned slot if found.
|
||||
*
|
||||
* Note: slot attribute of aContent may have changed already, so pass slot
|
||||
* name explicity here.
|
||||
*/
|
||||
const HTMLSlotElement* UnassignSlotFor(nsIContent* aContent,
|
||||
const nsAString& aSlotName);
|
||||
|
||||
/**
|
||||
* Called when we redistribute content after insertion points have changed.
|
||||
*/
|
||||
void DistributionChanged();
|
||||
|
||||
bool IsPooledNode(nsIContent* aChild) const;
|
||||
|
||||
public:
|
||||
void AddSlot(HTMLSlotElement* aSlot);
|
||||
void RemoveSlot(HTMLSlotElement* aSlot);
|
||||
void AddInsertionPoint(HTMLContentElement* aInsertionPoint);
|
||||
void RemoveInsertionPoint(HTMLContentElement* aInsertionPoint);
|
||||
|
||||
void SetYoungerShadow(ShadowRoot* aYoungerShadow);
|
||||
ShadowRoot* GetYoungerShadowRoot() { return mYoungerShadow; }
|
||||
void SetInsertionPointChanged() { mInsertionPointChanged = true; }
|
||||
|
||||
void SetAssociatedBinding(nsXBLBinding* aBinding) { mAssociatedBinding = aBinding; }
|
||||
|
||||
nsISupports* GetParentObject() const { return mPoolHost; }
|
||||
|
||||
nsIContent* GetPoolHost() { return mPoolHost; }
|
||||
nsTArray<HTMLShadowElement*>& ShadowDescendants() { return mShadowDescendants; }
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
static bool IsPooledNode(nsIContent* aChild, nsIContent* aContainer,
|
||||
nsIContent* aHost);
|
||||
static ShadowRoot* FromNode(nsINode* aNode);
|
||||
static bool IsShadowInsertionPoint(nsIContent* aContent);
|
||||
|
||||
void AddToIdTable(Element* aElement, nsIAtom* aId);
|
||||
void RemoveFromIdTable(Element* aElement, nsIAtom* aId);
|
||||
static void RemoveDestInsertionPoint(nsIContent* aInsertionPoint,
|
||||
nsTArray<nsIContent*>& aDestInsertionPoints);
|
||||
|
||||
// WebIDL methods.
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementById;
|
||||
|
||||
Element* GetActiveElement();
|
||||
Element* GetElementById(const nsAString& aElementId);
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagName(const nsAString& aNamespaceURI);
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName);
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByClassName(const nsAString& aClasses);
|
||||
void GetInnerHTML(nsAString& aInnerHTML);
|
||||
void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
|
||||
Element* Host();
|
||||
ShadowRoot* GetOlderShadowRoot() { return mOlderShadow; }
|
||||
void StyleSheetChanged();
|
||||
|
||||
bool IsComposedDocParticipant() { return mIsComposedDocParticipant; }
|
||||
@@ -132,18 +134,26 @@ public:
|
||||
mIsComposedDocParticipant = aIsComposedDocParticipant;
|
||||
}
|
||||
|
||||
nsresult GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||
|
||||
virtual void DestroyContent() override;
|
||||
protected:
|
||||
virtual ~ShadowRoot();
|
||||
|
||||
ShadowRootMode mMode;
|
||||
// The pool host is the parent of the nodes that will be distributed
|
||||
// into the insertion points in this ShadowRoot. See |ChangeShadowRoot|.
|
||||
nsCOMPtr<nsIContent> mPoolHost;
|
||||
|
||||
// Map from name of slot to an array of all slots in the shadow DOM with with
|
||||
// the given name. The slots are stored as a weak pointer because the elements
|
||||
// are in the shadow tree and should be kept alive by its parent.
|
||||
nsClassHashtable<nsStringHashKey, nsTArray<mozilla::dom::HTMLSlotElement*>> mSlotMap;
|
||||
// An array of content insertion points that are a descendant of the ShadowRoot
|
||||
// sorted in tree order. Insertion points are responsible for notifying
|
||||
// the ShadowRoot when they are removed or added as a descendant. The insertion
|
||||
// points are kept alive by the parent node, thus weak references are held
|
||||
// by the array.
|
||||
nsTArray<HTMLContentElement*> mInsertionPoints;
|
||||
|
||||
// An array of the <shadow> elements that are descendant of the ShadowRoot
|
||||
// sorted in tree order. Only the first may be a shadow insertion point.
|
||||
nsTArray<HTMLShadowElement*> mShadowDescendants;
|
||||
|
||||
nsTHashtable<nsIdentifierMapEntry> mIdentifierMap;
|
||||
nsXBLPrototypeBinding* mProtoBinding;
|
||||
|
||||
// It is necessary to hold a reference to the associated nsXBLBinding
|
||||
@@ -151,6 +161,19 @@ protected:
|
||||
// owns |mProtoBinding|.
|
||||
RefPtr<nsXBLBinding> mAssociatedBinding;
|
||||
|
||||
RefPtr<ShadowRootStyleSheetList> mStyleSheetList;
|
||||
|
||||
// The current shadow insertion point of this ShadowRoot.
|
||||
HTMLShadowElement* mShadowElement;
|
||||
|
||||
// The ShadowRoot that was created by the host element before
|
||||
// this ShadowRoot was created.
|
||||
RefPtr<ShadowRoot> mOlderShadow;
|
||||
|
||||
// The ShadowRoot that was created by the host element after
|
||||
// this ShadowRoot was created.
|
||||
RefPtr<ShadowRoot> mYoungerShadow;
|
||||
|
||||
// A boolean that indicates that an insertion point was added or removed
|
||||
// from this ShadowRoot and that the nodes need to be redistributed into
|
||||
// the insertion points. After this flag is set, nodes will be distributed
|
||||
@@ -166,6 +189,28 @@ protected:
|
||||
nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const override;
|
||||
};
|
||||
|
||||
class ShadowRootStyleSheetList : public StyleSheetList
|
||||
{
|
||||
public:
|
||||
explicit ShadowRootStyleSheetList(ShadowRoot* aShadowRoot);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
|
||||
|
||||
virtual nsINode* GetParentObject() const override
|
||||
{
|
||||
return mShadowRoot;
|
||||
}
|
||||
|
||||
uint32_t Length() override;
|
||||
StyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) override;
|
||||
|
||||
protected:
|
||||
virtual ~ShadowRootStyleSheetList();
|
||||
|
||||
RefPtr<ShadowRoot> mShadowRoot;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include "mozilla/CSSStyleSheet.h"
|
||||
#include "mozilla/dom/StyleSheetListBinding.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@@ -18,8 +17,7 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(StyleSheetList)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(StyleSheetList)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMStyleSheetList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMStyleSheetList)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(StyleSheetList)
|
||||
@@ -45,24 +43,5 @@ StyleSheetList::SlowItem(uint32_t aIndex, nsIDOMStyleSheet** aItem)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
StyleSheetList::NodeWillBeDestroyed(const nsINode* aNode)
|
||||
{
|
||||
mDocumentOrShadowRoot = nullptr;
|
||||
}
|
||||
|
||||
StyleSheetList::StyleSheetList(DocumentOrShadowRoot& aScope)
|
||||
: mDocumentOrShadowRoot(&aScope)
|
||||
{
|
||||
mDocumentOrShadowRoot->AsNode().AddMutationObserver(this);
|
||||
}
|
||||
|
||||
StyleSheetList::~StyleSheetList()
|
||||
{
|
||||
if (mDocumentOrShadowRoot) {
|
||||
mDocumentOrShadowRoot->AsNode().RemoveMutationObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -7,10 +7,8 @@
|
||||
#ifndef mozilla_dom_StyleSheetList_h
|
||||
#define mozilla_dom_StyleSheetList_h
|
||||
|
||||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "nsIDOMStyleSheetList.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
|
||||
class nsINode;
|
||||
|
||||
@@ -19,54 +17,28 @@ class StyleSheet;
|
||||
|
||||
namespace dom {
|
||||
|
||||
class StyleSheetList final : public nsIDOMStyleSheetList
|
||||
, public nsWrapperCache
|
||||
, public nsStubDocumentObserver
|
||||
class StyleSheetList : public nsIDOMStyleSheetList
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(StyleSheetList, nsIDOMStyleSheetList)
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(StyleSheetList)
|
||||
NS_DECL_NSIDOMSTYLESHEETLIST
|
||||
|
||||
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
||||
|
||||
explicit StyleSheetList(DocumentOrShadowRoot& aScope);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override final;
|
||||
|
||||
nsINode* GetParentObject() const
|
||||
{
|
||||
return mDocumentOrShadowRoot ? &mDocumentOrShadowRoot->AsNode() : nullptr;
|
||||
}
|
||||
virtual nsINode* GetParentObject() const = 0;
|
||||
|
||||
uint32_t Length() const
|
||||
{
|
||||
return mDocumentOrShadowRoot ? mDocumentOrShadowRoot->SheetCount() : 0;
|
||||
}
|
||||
|
||||
StyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) const
|
||||
{
|
||||
if (!mDocumentOrShadowRoot) {
|
||||
aFound = false;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StyleSheet* sheet = mDocumentOrShadowRoot->SheetAt(aIndex);
|
||||
aFound = !!sheet;
|
||||
return sheet;
|
||||
}
|
||||
|
||||
StyleSheet* Item(uint32_t aIndex) const
|
||||
virtual uint32_t Length() = 0;
|
||||
virtual StyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) = 0;
|
||||
StyleSheet* Item(uint32_t aIndex)
|
||||
{
|
||||
bool dummy = false;
|
||||
return IndexedGetter(aIndex, dummy);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ~StyleSheetList();
|
||||
|
||||
DocumentOrShadowRoot* mDocumentOrShadowRoot; // Weak, cleared on "NodeWillBeDestroyed".
|
||||
virtual ~StyleSheetList() {}
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<!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,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var o1 = document.documentElement;
|
||||
var o2 = document.createElement("frame");
|
||||
document.documentElement.appendChild(o2);
|
||||
var o3 = o2.contentWindow;
|
||||
o1.parentNode.removeChild(o1);
|
||||
o3.customElements;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<script>
|
||||
try { o1 = document.createElement('textarea') } catch(e) { }
|
||||
try { o2 = document.createElement('div') } catch(e) { }
|
||||
try { o3 = document.createElement('map') } catch(e) { }
|
||||
try { document.documentElement.appendChild(o2) } catch(e) { }
|
||||
try { o2.appendChild(o1) } catch(e) { }
|
||||
try { document.documentElement.getClientRects() } catch(e) { }
|
||||
try { o4 = o2.attachShadow({ mode: "open" }); } catch(e) { }
|
||||
try { o1.appendChild(o3) } catch(e) { }
|
||||
try { o5 = o3.parentElement } catch(e) { }
|
||||
try { o3.outerHTML = "\n" } catch(e) { }
|
||||
try { o4.prepend("", o5, "") } catch(e) { }
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
@@ -1,6 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<!-- Testing slot element with "dom.webcomponents.enabled" set to false -->
|
||||
<slot><div></div></slot>
|
||||
</html>
|
||||
@@ -0,0 +1,24 @@
|
||||
<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>
|
||||
@@ -0,0 +1,28 @@
|
||||
<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>
|
||||
@@ -193,7 +193,7 @@ load 930250.html
|
||||
load 942979.html
|
||||
load 973401.html
|
||||
load 978646.html
|
||||
pref(dom.webcomponents.enabled,true) load 1024428-1.html # bug 1340009
|
||||
pref(dom.webcomponents.enabled,true) load 1024428-1.html
|
||||
load 1026714.html
|
||||
pref(dom.webcomponents.enabled,true) load 1027461-1.html
|
||||
pref(dom.webcomponents.enabled,true) load 1029710.html
|
||||
@@ -209,6 +209,3 @@ load 1230422.html
|
||||
load 1251361.html
|
||||
load 1304437.html
|
||||
pref(clipboard.autocopy,true) load 1385272-1.html
|
||||
pref(dom.webcomponents.enabled,true) load 1341693.html
|
||||
pref(dom.webcomponents.enabled,true) load 1419799.html
|
||||
pref(dom.webcomponents.enabled,false) load 1422931.html
|
||||
@@ -86,7 +86,6 @@ EXPORTS += [
|
||||
'nsIContentInlines.h',
|
||||
'nsIContentIterator.h',
|
||||
'nsIContentSerializer.h',
|
||||
'nsIdentifierMapEntry.h',
|
||||
'nsIDocument.h',
|
||||
'nsIDocumentInlines.h',
|
||||
'nsIDocumentObserver.h',
|
||||
@@ -164,7 +163,6 @@ EXPORTS.mozilla.dom += [
|
||||
'DirectionalityUtils.h',
|
||||
'DocGroup.h',
|
||||
'DocumentFragment.h',
|
||||
'DocumentOrShadowRoot.h',
|
||||
'DocumentType.h',
|
||||
'DOMCursor.h',
|
||||
'DOMError.h',
|
||||
@@ -243,7 +241,6 @@ SOURCES += [
|
||||
'DirectionalityUtils.cpp',
|
||||
'DocGroup.cpp',
|
||||
'DocumentFragment.cpp',
|
||||
'DocumentOrShadowRoot.cpp',
|
||||
'DocumentType.cpp',
|
||||
'DOMCursor.cpp',
|
||||
'DOMError.cpp',
|
||||
|
||||
@@ -382,15 +382,12 @@ nsAttrAndChildArray::AttrAt(uint32_t aPos) const
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
|
||||
bool* aHadValue)
|
||||
nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue)
|
||||
{
|
||||
*aHadValue = false;
|
||||
uint32_t i, slotCount = AttrSlotCount();
|
||||
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
|
||||
if (ATTRS(mImpl)[i].mName.Equals(aLocalName)) {
|
||||
ATTRS(mImpl)[i].mValue.SwapValueWith(aValue);
|
||||
*aHadValue = true;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@@ -410,22 +407,21 @@ nsAttrAndChildArray::SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAttrAndChildArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName,
|
||||
nsAttrValue& aValue, bool* aHadValue)
|
||||
nsAttrAndChildArray::SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue)
|
||||
{
|
||||
int32_t namespaceID = aName->NamespaceID();
|
||||
nsIAtom* localName = aName->NameAtom();
|
||||
if (namespaceID == kNameSpaceID_None) {
|
||||
return SetAndSwapAttr(localName, aValue, aHadValue);
|
||||
return SetAndSwapAttr(localName, aValue);
|
||||
}
|
||||
|
||||
*aHadValue = false;
|
||||
uint32_t i, slotCount = AttrSlotCount();
|
||||
for (i = 0; i < slotCount && AttrSlotIsTaken(i); ++i) {
|
||||
if (ATTRS(mImpl)[i].mName.Equals(localName, namespaceID)) {
|
||||
ATTRS(mImpl)[i].mName.SetTo(aName);
|
||||
ATTRS(mImpl)[i].mValue.Reset();
|
||||
ATTRS(mImpl)[i].mValue.SwapValueWith(aValue);
|
||||
*aHadValue = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
@@ -580,11 +576,10 @@ nsAttrAndChildArray::IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID) cons
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAttrAndChildArray::SetAndSwapMappedAttr(nsIAtom* aLocalName,
|
||||
nsAttrAndChildArray::SetAndTakeMappedAttr(nsIAtom* aLocalName,
|
||||
nsAttrValue& aValue,
|
||||
nsMappedAttributeElement* aContent,
|
||||
nsHTMLStyleSheet* aSheet,
|
||||
bool* aHadValue)
|
||||
nsHTMLStyleSheet* aSheet)
|
||||
{
|
||||
bool willAdd = true;
|
||||
if (mImpl && mImpl->mMappedAttrs) {
|
||||
@@ -594,7 +589,7 @@ nsAttrAndChildArray::SetAndSwapMappedAttr(nsIAtom* aLocalName,
|
||||
RefPtr<nsMappedAttributes> mapped =
|
||||
GetModifiableMapped(aContent, aSheet, willAdd);
|
||||
|
||||
mapped->SetAndSwapAttr(aLocalName, aValue, aHadValue);
|
||||
mapped->SetAndTakeAttr(aLocalName, aValue);
|
||||
|
||||
return MakeMappedUnique(mapped);
|
||||
}
|
||||
@@ -719,19 +714,10 @@ nsAttrAndChildArray::MappedAttrCount() const
|
||||
return mImpl && mImpl->mMappedAttrs ? (uint32_t)mImpl->mMappedAttrs->Count() : 0;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsAttrAndChildArray::ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument)
|
||||
{
|
||||
nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
|
||||
RefPtr<nsMappedAttributes> mapped = GetModifiableMapped(aContent, sheet, false, 0);
|
||||
return MakeMappedUnique(mapped);
|
||||
}
|
||||
|
||||
nsMappedAttributes*
|
||||
nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
|
||||
nsHTMLStyleSheet* aSheet,
|
||||
bool aWillAddAttr,
|
||||
int32_t aAttrCount)
|
||||
bool aWillAddAttr)
|
||||
{
|
||||
if (mImpl && mImpl->mMappedAttrs) {
|
||||
return mImpl->mMappedAttrs->Clone(aWillAddAttr);
|
||||
@@ -741,7 +727,7 @@ nsAttrAndChildArray::GetModifiableMapped(nsMappedAttributeElement* aContent,
|
||||
|
||||
nsMapRuleToAttributesFunc mapRuleFunc =
|
||||
aContent->GetAttributeMappingFunction();
|
||||
return new (aAttrCount) nsMappedAttributes(aSheet, mapRuleFunc);
|
||||
return new nsMappedAttributes(aSheet, mapRuleFunc);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
||||
@@ -91,13 +91,8 @@ public:
|
||||
nsCaseTreatment aCaseSensitive) const;
|
||||
const nsAttrValue* AttrAt(uint32_t aPos) const;
|
||||
// SetAndSwapAttr swaps the current attribute value with aValue.
|
||||
// If the attribute was unset, an empty value will be swapped into aValue
|
||||
// and aHadValue will be set to false. Otherwise, aHadValue will be set to
|
||||
// true.
|
||||
nsresult SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
|
||||
bool* aHadValue);
|
||||
nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue,
|
||||
bool* aHadValue);
|
||||
nsresult SetAndSwapAttr(nsIAtom* aLocalName, nsAttrValue& aValue);
|
||||
nsresult SetAndSwapAttr(mozilla::dom::NodeInfo* aName, nsAttrValue& aValue);
|
||||
|
||||
// Remove the attr at position aPos. The value of the attr is placed in
|
||||
// aValue; any value that was already in aValue is destroyed.
|
||||
@@ -115,14 +110,9 @@ public:
|
||||
const nsAttrName* GetExistingAttrNameFromQName(const nsAString& aName) const;
|
||||
int32_t IndexOfAttr(nsIAtom* aLocalName, int32_t aNamespaceID = kNameSpaceID_None) const;
|
||||
|
||||
// SetAndSwapMappedAttr swaps the current attribute value with aValue.
|
||||
// If the attribute was unset, an empty value will be swapped into aValue
|
||||
// and aHadValue will be set to false. Otherwise, aHadValue will be set to
|
||||
// true.
|
||||
nsresult SetAndSwapMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
|
||||
nsresult SetAndTakeMappedAttr(nsIAtom* aLocalName, nsAttrValue& aValue,
|
||||
nsMappedAttributeElement* aContent,
|
||||
nsHTMLStyleSheet* aSheet,
|
||||
bool* aHadValue);
|
||||
nsHTMLStyleSheet* aSheet);
|
||||
nsresult SetMappedAttrStyleSheet(nsHTMLStyleSheet* aSheet) {
|
||||
if (!mImpl || !mImpl->mMappedAttrs) {
|
||||
return NS_OK;
|
||||
@@ -145,9 +135,6 @@ public:
|
||||
return MappedAttrCount();
|
||||
}
|
||||
|
||||
// Force this to have mapped attributes, even if those attributes are empty.
|
||||
nsresult ForceMapped(nsMappedAttributeElement* aContent, nsIDocument* aDocument);
|
||||
|
||||
private:
|
||||
nsAttrAndChildArray(const nsAttrAndChildArray& aOther) = delete;
|
||||
nsAttrAndChildArray& operator=(const nsAttrAndChildArray& aOther) = delete;
|
||||
@@ -161,8 +148,7 @@ private:
|
||||
nsMappedAttributes*
|
||||
GetModifiableMapped(nsMappedAttributeElement* aContent,
|
||||
nsHTMLStyleSheet* aSheet,
|
||||
bool aWillAddAttr,
|
||||
int32_t aAttrCount = 1);
|
||||
bool aWillAddAttr);
|
||||
nsresult MakeMappedUnique(nsMappedAttributes* aAttributes);
|
||||
|
||||
uint32_t AttrSlotsSize() const
|
||||
|
||||
@@ -49,13 +49,20 @@ public:
|
||||
, mCheapString(nullptr)
|
||||
{ }
|
||||
|
||||
void ResetToAttrValue(const nsAttrValue& aValue)
|
||||
void TakeParsedValue(nsAttrValue& aValue)
|
||||
{
|
||||
mAttrValue = &aValue;
|
||||
mStoredAttrValue.SwapValueWith(aValue);
|
||||
mAttrValue = &mStoredAttrValue;
|
||||
mStringPtr = nullptr;
|
||||
// No need to touch mCheapString here. If we need to use it, we will reset
|
||||
// it to the rigthe value anyway.
|
||||
}
|
||||
/**
|
||||
* If TakeParsedValue has been called, returns the value that it set.
|
||||
*/
|
||||
nsAttrValue* GetStoredAttrValue()
|
||||
{
|
||||
return mAttrValue == &mStoredAttrValue ? &mStoredAttrValue : nullptr;
|
||||
}
|
||||
const nsAttrValue* GetAttrValue() { return mAttrValue; }
|
||||
|
||||
/**
|
||||
* Returns a reference to the string value of the contents of this object.
|
||||
@@ -78,24 +85,11 @@ public:
|
||||
return aOther.EqualsAsStrings(*mAttrValue);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the value stored is empty
|
||||
*/
|
||||
bool IsEmpty() const
|
||||
{
|
||||
if (mStringPtr) {
|
||||
return mStringPtr->IsEmpty();
|
||||
}
|
||||
if (mAttrValue) {
|
||||
return mAttrValue->IsEmptyString();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
const nsAttrValue* mAttrValue;
|
||||
mutable const nsAString* mStringPtr;
|
||||
mutable nsCheapString mCheapString;
|
||||
nsAttrValue mStoredAttrValue;
|
||||
};
|
||||
|
||||
#endif // nsAttrValueOrString_h___
|
||||
@@ -24,7 +24,6 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
class NodeInfo;
|
||||
struct CustomElementDefinition;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -42,8 +41,7 @@ nsresult
|
||||
NS_NewHTMLElement(mozilla::dom::Element** aResult,
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
|
||||
mozilla::dom::FromParser aFromParser,
|
||||
const nsAString* aIs = nullptr,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition = nullptr);
|
||||
const nsAString* aIs = nullptr);
|
||||
|
||||
// First argument should be nsHTMLTag, but that adds dependency to parser
|
||||
// for a bunch of files.
|
||||
|
||||
+164
-163
@@ -44,8 +44,9 @@
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/FileSystemSecurity.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/dom/HTMLSlotElement.h"
|
||||
#include "mozilla/dom/HTMLTemplateElement.h"
|
||||
#include "mozilla/dom/HTMLContentElement.h"
|
||||
#include "mozilla/dom/HTMLShadowElement.h"
|
||||
#include "mozilla/dom/ipc/BlobChild.h"
|
||||
#include "mozilla/dom/ipc/BlobParent.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
@@ -101,9 +102,7 @@
|
||||
#include "nsHostObjectProtocolHandler.h"
|
||||
#include "nsHtml5Module.h"
|
||||
#include "nsHtml5StringParser.h"
|
||||
#include "nsHTMLTags.h"
|
||||
#include "nsIAddonPolicyService.h"
|
||||
#include "nsIAnonymousContentCreator.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "nsICategoryManager.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
@@ -228,7 +227,6 @@ extern "C" int MOZ_XMLCheckQName(const char* ptr, const char* end,
|
||||
int ns_aware, const char** colon);
|
||||
|
||||
class imgLoader;
|
||||
class nsIAtom;
|
||||
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::ipc;
|
||||
@@ -260,6 +258,7 @@ nsIWordBreaker *nsContentUtils::sWordBreaker;
|
||||
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
|
||||
uint32_t nsContentUtils::sScriptBlockerCount = 0;
|
||||
uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
|
||||
uint32_t nsContentUtils::sMicroTaskLevel = 0;
|
||||
AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners = nullptr;
|
||||
uint32_t nsContentUtils::sRunnersCountAtFirstBlocker = 0;
|
||||
nsIInterfaceRequestor* nsContentUtils::sSameOriginChecker = nullptr;
|
||||
@@ -285,8 +284,6 @@ bool nsContentUtils::sIsResourceTimingEnabled = false;
|
||||
bool nsContentUtils::sIsPerformanceNavigationTimingEnabled = false;
|
||||
bool nsContentUtils::sIsUserTimingLoggingEnabled = false;
|
||||
bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
|
||||
bool nsContentUtils::sIsWebComponentsEnabled = false;
|
||||
bool nsContentUtils::sIsCustomElementsEnabled = false;
|
||||
bool nsContentUtils::sEncodeDecodeURLHash = false;
|
||||
bool nsContentUtils::sGettersDecodeURLHash = false;
|
||||
bool nsContentUtils::sPrivacyResistFingerprinting = false;
|
||||
@@ -501,8 +498,6 @@ nsContentUtils::Init()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsHTMLTags::AddRefTable();
|
||||
|
||||
sNameSpaceManager = nsNameSpaceManager::GetInstance();
|
||||
NS_ENSURE_TRUE(sNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
@@ -589,12 +584,6 @@ nsContentUtils::Init()
|
||||
Preferences::AddBoolVarCache(&sIsExperimentalAutocompleteEnabled,
|
||||
"dom.forms.autocomplete.experimental", false);
|
||||
|
||||
Preferences::AddBoolVarCache(&sIsWebComponentsEnabled,
|
||||
"dom.webcomponents.enabled", false);
|
||||
|
||||
Preferences::AddBoolVarCache(&sIsCustomElementsEnabled,
|
||||
"dom.webcomponents.enabled", false);
|
||||
|
||||
Preferences::AddBoolVarCache(&sEncodeDecodeURLHash,
|
||||
"dom.url.encode_decode_hash", false);
|
||||
|
||||
@@ -1929,8 +1918,6 @@ nsContentUtils::Shutdown()
|
||||
{
|
||||
sInitialized = false;
|
||||
|
||||
nsHTMLTags::ReleaseTable();
|
||||
|
||||
NS_IF_RELEASE(sContentPolicyService);
|
||||
sTriedToGetContentPolicy = false;
|
||||
uint32_t i;
|
||||
@@ -2395,9 +2382,6 @@ nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
||||
bool* aDisconnected)
|
||||
{
|
||||
if (aParent1 == aParent2) {
|
||||
// XXX This is odd. aOffset1 and/or aOffset2 may be -1, e.g., it's result
|
||||
// of nsINode::IndexOf(), but this compares such invalid offset with
|
||||
// valid offset.
|
||||
return aOffset1 < aOffset2 ? -1 :
|
||||
aOffset1 > aOffset2 ? 1 :
|
||||
0;
|
||||
@@ -2448,14 +2432,10 @@ nsContentUtils::ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
||||
|
||||
if (!pos1) {
|
||||
nsINode* child2 = parents2.ElementAt(--pos2);
|
||||
// XXX aOffset1 may be -1 as mentioned above. So, why does this return
|
||||
// it's *before* of the valid DOM point?
|
||||
return aOffset1 <= parent->IndexOf(child2) ? -1 : 1;
|
||||
}
|
||||
|
||||
nsINode* child1 = parents1.ElementAt(--pos1);
|
||||
// XXX aOffset2 may be -1 as mentioned above. So, why does this return it's
|
||||
// *after* of the valid DOM point?
|
||||
return parent->IndexOf(child1) < aOffset2 ? -1 : 1;
|
||||
}
|
||||
|
||||
@@ -3658,14 +3638,6 @@ nsContentUtils::ReportToConsole(uint32_t aErrorFlags,
|
||||
aLineNumber, aColumnNumber);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::ReportEmptyGetElementByIdArg(const nsIDocument* aDoc)
|
||||
{
|
||||
ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM"), aDoc,
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"EmptyGetElementByIdParam");
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsContentUtils::ReportToConsoleNonLocalized(const nsAString& aErrorText,
|
||||
@@ -4963,7 +4935,17 @@ nsContentUtils::IsInSameAnonymousTree(const nsINode* aNode,
|
||||
return aContent->GetBindingParent() == nullptr;
|
||||
}
|
||||
|
||||
return aNode->AsContent()->GetBindingParent() == aContent->GetBindingParent();
|
||||
const nsIContent* nodeAsContent = static_cast<const nsIContent*>(aNode);
|
||||
|
||||
// For nodes in a shadow tree, it is insufficient to simply compare
|
||||
// the binding parent because a node may host multiple ShadowRoots,
|
||||
// thus nodes in different shadow tree may have the same binding parent.
|
||||
if (aNode->IsInShadowTree()) {
|
||||
return nodeAsContent->GetContainingShadow() ==
|
||||
aContent->GetContainingShadow();
|
||||
}
|
||||
|
||||
return nodeAsContent->GetBindingParent() == aContent->GetBindingParent();
|
||||
}
|
||||
|
||||
class AnonymousContentDestroyer : public Runnable {
|
||||
@@ -5312,6 +5294,51 @@ nsContentUtils::RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable)
|
||||
CycleCollectedJSContext::Get()->RunInMetastableState(Move(aRunnable));
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::EnterMicroTask()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
++sMicroTaskLevel;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::LeaveMicroTask()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (--sMicroTaskLevel == 0) {
|
||||
PerformMainThreadMicroTaskCheckpoint();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsInMicroTask()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return sMicroTaskLevel != 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
nsContentUtils::MicroTaskLevel()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
return sMicroTaskLevel;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::SetMicroTaskLevel(uint32_t aLevel)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sMicroTaskLevel = aLevel;
|
||||
}
|
||||
|
||||
void
|
||||
nsContentUtils::PerformMainThreadMicroTaskCheckpoint()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsDOMMutationObserver::HandleMutations();
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for nsContentUtils::ProcessViewportInfo.
|
||||
*
|
||||
@@ -7025,11 +7052,25 @@ nsContentUtils::GetHTMLEditor(nsPresContext* aPresContext)
|
||||
return editor;
|
||||
}
|
||||
|
||||
bool
|
||||
nsContentUtils::IsContentInsertionPoint(nsIContent* aContent)
|
||||
{
|
||||
// Check if the content is a XBL insertion point.
|
||||
if (aContent->IsActiveChildrenElement()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if the content is a web components content insertion point.
|
||||
HTMLContentElement* contentElement =
|
||||
HTMLContentElement::FromContent(aContent);
|
||||
return contentElement && contentElement->IsInsertionPoint();
|
||||
}
|
||||
|
||||
// static
|
||||
bool
|
||||
nsContentUtils::HasDistributedChildren(nsIContent* aContent)
|
||||
{
|
||||
if (!aContent || !nsDocument::IsWebComponentsEnabled(aContent)) {
|
||||
if (!aContent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7039,11 +7080,26 @@ nsContentUtils::HasDistributedChildren(nsIContent* aContent)
|
||||
return true;
|
||||
}
|
||||
|
||||
HTMLSlotElement* slotEl = HTMLSlotElement::FromContent(aContent);
|
||||
if (slotEl && slotEl->GetContainingShadow()) {
|
||||
// Children of a slot are rendered if the slot does not have any assigned
|
||||
// nodes (fallback content).
|
||||
return slotEl->AssignedNodes().IsEmpty();
|
||||
ShadowRoot* shadow = ShadowRoot::FromNode(aContent);
|
||||
if (shadow) {
|
||||
// Children of a shadow root are distributed to
|
||||
// the shadow insertion point of the younger shadow root.
|
||||
return shadow->GetYoungerShadowRoot();
|
||||
}
|
||||
|
||||
HTMLShadowElement* shadowEl = HTMLShadowElement::FromContent(aContent);
|
||||
if (shadowEl && shadowEl->IsInsertionPoint()) {
|
||||
// Children of a shadow insertion points are distributed
|
||||
// to the insertion points in the older shadow root.
|
||||
return shadowEl->GetOlderShadowRoot();
|
||||
}
|
||||
|
||||
HTMLContentElement* contentEl = HTMLContentElement::FromContent(aContent);
|
||||
if (contentEl && contentEl->IsInsertionPoint()) {
|
||||
// Children of a content insertion point are distributed to the
|
||||
// content insertion point if the content insertion point does
|
||||
// not match any nodes (fallback content).
|
||||
return contentEl->MatchedNodes().IsEmpty();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -9512,34 +9568,11 @@ nsContentUtils::HttpsStateIsModern(nsIDocument* aDocument)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::TryToUpgradeElement(Element* aElement)
|
||||
{
|
||||
NodeInfo* nodeInfo = aElement->NodeInfo();
|
||||
RefPtr<nsIAtom> typeAtom =
|
||||
aElement->GetCustomElementData()->GetCustomElementType();
|
||||
|
||||
MOZ_ASSERT(nodeInfo->NameAtom()->Equals(nodeInfo->LocalName()));
|
||||
CustomElementDefinition* definition =
|
||||
nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
|
||||
nodeInfo->NameAtom(),
|
||||
nodeInfo->NamespaceID(),
|
||||
typeAtom);
|
||||
if (definition) {
|
||||
nsContentUtils::EnqueueUpgradeReaction(aElement, definition);
|
||||
} else {
|
||||
// Add an unresolved custom element that is a candidate for
|
||||
// upgrade when a custom element is connected to the document.
|
||||
// We will make sure it's shadow-including tree order in bug 1326028.
|
||||
nsContentUtils::RegisterUnresolvedElement(aElement, typeAtom);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ CustomElementDefinition*
|
||||
nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
|
||||
nsIAtom* aNameAtom,
|
||||
const nsAString& aLocalName,
|
||||
uint32_t aNameSpaceID,
|
||||
nsIAtom* aTypeAtom)
|
||||
const nsAString* aIs)
|
||||
{
|
||||
MOZ_ASSERT(aDoc);
|
||||
|
||||
@@ -9561,16 +9594,30 @@ nsContentUtils::LookupCustomElementDefinition(nsIDocument* aDoc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return registry->LookupCustomElementDefinition(aNameAtom, aTypeAtom);
|
||||
return registry->LookupCustomElementDefinition(aLocalName, aIs);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
|
||||
nsContentUtils::SetupCustomElement(Element* aElement,
|
||||
const nsAString* aTypeExtension)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
|
||||
nsIDocument* doc = aElement->OwnerDoc();
|
||||
nsPIDOMWindowInner* window(doc->GetInnerWindow());
|
||||
nsCOMPtr<nsIDocument> doc = aElement->OwnerDoc();
|
||||
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
||||
// To support imported document.
|
||||
doc = doc->MasterDocument();
|
||||
|
||||
if (aElement->GetNameSpaceID() != kNameSpaceID_XHTML ||
|
||||
!doc->GetDocShell()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window(doc->GetInnerWindow());
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
@@ -9580,80 +9627,65 @@ nsContentUtils::RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName)
|
||||
return;
|
||||
}
|
||||
|
||||
registry->RegisterUnresolvedElement(aElement, aTypeName);
|
||||
return registry->SetupCustomElement(aElement, aTypeExtension);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::UnregisterUnresolvedElement(Element* aElement)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
|
||||
RefPtr<nsIAtom> typeAtom =
|
||||
aElement->GetCustomElementData()->GetCustomElementType();
|
||||
nsIDocument* doc = aElement->OwnerDoc();
|
||||
nsPIDOMWindowInner* window(doc->GetInnerWindow());
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
|
||||
registry->UnregisterUnresolvedElement(aElement, typeAtom);
|
||||
}
|
||||
|
||||
/* static */ CustomElementDefinition*
|
||||
nsContentUtils::GetElementDefinitionIfObservingAttr(Element* aCustomElement,
|
||||
nsIAtom* aExtensionType,
|
||||
nsIAtom* aAttrName)
|
||||
{
|
||||
CustomElementDefinition* definition =
|
||||
aCustomElement->GetCustomElementDefinition();
|
||||
|
||||
// Custom element not defined yet or attribute is not in the observed
|
||||
// attribute list.
|
||||
if (!definition || !definition->IsInObservedAttributeList(aAttrName)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return definition;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::EnqueueUpgradeReaction(Element* aElement,
|
||||
CustomElementDefinition* aDefinition)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
|
||||
nsIDocument* doc = aElement->OwnerDoc();
|
||||
|
||||
// No DocGroup means no custom element reactions stack.
|
||||
if (!doc->GetDocGroup()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomElementReactionsStack* stack =
|
||||
doc->GetDocGroup()->CustomElementReactionsStack();
|
||||
stack->EnqueueUpgradeReaction(aElement, aDefinition);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc,
|
||||
nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
LifecycleCallbackArgs* aArgs,
|
||||
LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs,
|
||||
CustomElementDefinition* aDefinition)
|
||||
{
|
||||
// No DocGroup means no custom element reactions stack.
|
||||
if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
|
||||
MOZ_ASSERT(aDoc);
|
||||
|
||||
// To support imported document.
|
||||
nsCOMPtr<nsIDocument> doc = aDoc->MasterDocument();
|
||||
|
||||
if (!doc->GetDocShell()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
|
||||
aAdoptedCallbackArgs,
|
||||
aDefinition);
|
||||
nsCOMPtr<nsPIDOMWindowInner> window(doc->GetInnerWindow());
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
|
||||
registry->EnqueueLifecycleCallback(aType, aCustomElement, aArgs, aDefinition);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::GetCustomPrototype(nsIDocument* aDoc,
|
||||
int32_t aNamespaceID,
|
||||
nsIAtom* aAtom,
|
||||
JS::MutableHandle<JSObject*> aPrototype)
|
||||
{
|
||||
MOZ_ASSERT(aDoc);
|
||||
|
||||
// To support imported document.
|
||||
nsCOMPtr<nsIDocument> doc = aDoc->MasterDocument();
|
||||
|
||||
if (aNamespaceID != kNameSpaceID_XHTML ||
|
||||
!doc->GetDocShell()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window(doc->GetInnerWindow());
|
||||
if (!window) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<CustomElementRegistry> registry(window->CustomElements());
|
||||
if (!registry) {
|
||||
return;
|
||||
}
|
||||
|
||||
return registry->GetCustomPrototype(aAtom, aPrototype);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
@@ -9789,24 +9821,6 @@ nsContentUtils::AttemptLargeAllocationLoad(nsIHttpChannel* aChannel)
|
||||
return reloadSucceeded;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsContentUtils::AppendDocumentLevelNativeAnonymousContentTo(
|
||||
nsIDocument* aDocument,
|
||||
nsTArray<nsIContent*>& aElements)
|
||||
{
|
||||
MOZ_ASSERT(aDocument);
|
||||
|
||||
// XXXheycam This probably needs to find the nsCanvasFrame's NAC too.
|
||||
if (nsIPresShell* presShell = aDocument->GetShell()) {
|
||||
if (nsIFrame* scrollFrame = presShell->GetRootScrollFrame()) {
|
||||
nsIAnonymousContentCreator* creator = do_QueryFrame(scrollFrame);
|
||||
MOZ_ASSERT(creator,
|
||||
"scroll frame should always implement nsIAnonymousContentCreator");
|
||||
creator->AppendAnonymousContentTo(aElements, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsContentUtils::IsLocalRefURL(const nsString& aString)
|
||||
{
|
||||
@@ -9821,17 +9835,4 @@ nsContentUtils::IsLocalRefURL(const nsString& aString)
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ Element*
|
||||
nsContentUtils::GetClosestNonNativeAnonymousAncestor(Element* aElement)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
MOZ_ASSERT(aElement->IsNativeAnonymous());
|
||||
|
||||
Element* e = aElement;
|
||||
while (e && e->IsNativeAnonymous()) {
|
||||
e = e->GetParentElement();
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
+49
-55
@@ -126,7 +126,6 @@ class EventTarget;
|
||||
class IPCDataTransfer;
|
||||
class IPCDataTransferItem;
|
||||
struct LifecycleCallbackArgs;
|
||||
struct LifecycleAdoptedCallbackArgs;
|
||||
class NodeInfo;
|
||||
class nsIContentChild;
|
||||
class nsIContentParent;
|
||||
@@ -339,13 +338,6 @@ public:
|
||||
* NOTE! If the two nodes aren't in the same connected subtree,
|
||||
* the result is 1, and the optional aDisconnected parameter
|
||||
* is set to true.
|
||||
*
|
||||
* XXX aOffset1 and aOffset2 should be uint32_t since valid offset value is
|
||||
* between 0 - UINT32_MAX. However, these methods work even with
|
||||
* negative offset values! E.g., when aOffset1 is -1 and aOffset is 0,
|
||||
* these methods return -1. Some root callers depend on this behavior.
|
||||
* On the other hand, nsINode can have ATTRCHILD_ARRAY_MAX_CHILD_COUN
|
||||
* (0x3FFFFF) at most. Therefore, they can be int32_t for now.
|
||||
*/
|
||||
static int32_t ComparePoints(nsINode* aParent1, int32_t aOffset1,
|
||||
nsINode* aParent2, int32_t aOffset2,
|
||||
@@ -589,7 +581,7 @@ public:
|
||||
|
||||
/**
|
||||
* Returns true if |aName| is a valid name to be registered via
|
||||
* customElements.define.
|
||||
* document.registerElement.
|
||||
*/
|
||||
static bool IsCustomElementName(nsIAtom* aName);
|
||||
|
||||
@@ -941,8 +933,6 @@ public:
|
||||
uint32_t aLineNumber = 0,
|
||||
uint32_t aColumnNumber = 0);
|
||||
|
||||
static void ReportEmptyGetElementByIdArg(const nsIDocument* aDoc);
|
||||
|
||||
static void LogMessageToConsole(const char* aMsg);
|
||||
|
||||
/**
|
||||
@@ -1751,6 +1741,17 @@ public:
|
||||
*/
|
||||
static void RunInMetastableState(already_AddRefed<nsIRunnable> aRunnable);
|
||||
|
||||
// Call EnterMicroTask when you're entering JS execution.
|
||||
// Usually the best way to do this is to use nsAutoMicroTask.
|
||||
static void EnterMicroTask();
|
||||
static void LeaveMicroTask();
|
||||
|
||||
static bool IsInMicroTask();
|
||||
static uint32_t MicroTaskLevel();
|
||||
static void SetMicroTaskLevel(uint32_t aLevel);
|
||||
|
||||
static void PerformMainThreadMicroTaskCheckpoint();
|
||||
|
||||
/* Process viewport META data. This gives us information for the scale
|
||||
* and zoom of a page on mobile devices. We stick the information in
|
||||
* the document header and use it later on after rendering.
|
||||
@@ -2416,6 +2417,18 @@ public:
|
||||
*/
|
||||
static mozilla::LogModule* DOMDumpLog();
|
||||
|
||||
/**
|
||||
* Returns whether a content is an insertion point for XBL
|
||||
* bindings or web components ShadowRoot. In web components,
|
||||
* this corresponds to a <content> element that participates
|
||||
* in node distribution. In XBL this corresponds to an
|
||||
* <xbl:children> element in anonymous content.
|
||||
*
|
||||
* @param aContent The content to test for being an insertion point.
|
||||
*/
|
||||
static bool IsContentInsertionPoint(nsIContent* aContent);
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the children of the provided content are
|
||||
* nodes that are distributed to Shadow DOM insertion points.
|
||||
@@ -2699,50 +2712,31 @@ public:
|
||||
*/
|
||||
static bool HttpsStateIsModern(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Try to upgrade an element.
|
||||
* https://html.spec.whatwg.org/multipage/custom-elements.html#concept-try-upgrade
|
||||
*/
|
||||
static void TryToUpgradeElement(Element* aElement);
|
||||
|
||||
/**
|
||||
* Looking up a custom element definition.
|
||||
* https://html.spec.whatwg.org/#look-up-a-custom-element-definition
|
||||
*/
|
||||
static mozilla::dom::CustomElementDefinition*
|
||||
LookupCustomElementDefinition(nsIDocument* aDoc,
|
||||
nsIAtom* aNameAtom,
|
||||
const nsAString& aLocalName,
|
||||
uint32_t aNameSpaceID,
|
||||
nsIAtom* aTypeAtom);
|
||||
const nsAString* aIs = nullptr);
|
||||
|
||||
static void RegisterUnresolvedElement(Element* aElement, nsIAtom* aTypeName);
|
||||
static void UnregisterUnresolvedElement(Element* aElement);
|
||||
static void SetupCustomElement(Element* aElement,
|
||||
const nsAString* aTypeExtension = nullptr);
|
||||
|
||||
static mozilla::dom::CustomElementDefinition*
|
||||
GetElementDefinitionIfObservingAttr(Element* aCustomElement,
|
||||
nsIAtom* aExtensionType,
|
||||
nsIAtom* aAttrName);
|
||||
|
||||
static void EnqueueUpgradeReaction(Element* aElement,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition);
|
||||
|
||||
static void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
|
||||
static void EnqueueLifecycleCallback(nsIDocument* aDoc,
|
||||
nsIDocument::ElementCallbackType aType,
|
||||
Element* aCustomElement,
|
||||
mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr,
|
||||
mozilla::dom::LifecycleAdoptedCallbackArgs* aAdoptedCallbackArgs = nullptr,
|
||||
mozilla::dom::CustomElementDefinition* aDefinition = nullptr);
|
||||
|
||||
static bool AttemptLargeAllocationLoad(nsIHttpChannel* aChannel);
|
||||
static void GetCustomPrototype(nsIDocument* aDoc,
|
||||
int32_t aNamespaceID,
|
||||
nsIAtom* aAtom,
|
||||
JS::MutableHandle<JSObject*> prototype);
|
||||
|
||||
/**
|
||||
* Appends all "document level" native anonymous content subtree roots for
|
||||
* aDocument to aElements. Document level NAC subtrees are those created
|
||||
* by ancestor frames of the document element's primary frame, such as
|
||||
* the scrollbar elements created by the root scroll frame.
|
||||
*/
|
||||
static void AppendDocumentLevelNativeAnonymousContentTo(
|
||||
nsIDocument* aDocument,
|
||||
nsTArray<nsIContent*>& aElements);
|
||||
static bool AttemptLargeAllocationLoad(nsIHttpChannel* aChannel);
|
||||
|
||||
/**
|
||||
* Detect whether a string is a (CSS) local-url.
|
||||
@@ -2751,18 +2745,6 @@ public:
|
||||
static bool
|
||||
IsLocalRefURL(const nsString& aString);
|
||||
|
||||
static bool
|
||||
IsWebComponentsEnabled() { return sIsWebComponentsEnabled; }
|
||||
|
||||
/**
|
||||
* Walks up the tree from aElement until it finds an element that is
|
||||
* not native anonymous content. aElement must be NAC itself.
|
||||
*/
|
||||
static Element* GetClosestNonNativeAnonymousAncestor(Element* aElement);
|
||||
|
||||
static bool
|
||||
IsCustomElementsEnabled() { return sIsCustomElementsEnabled; }
|
||||
|
||||
private:
|
||||
static bool InitializeEventTable();
|
||||
|
||||
@@ -2849,6 +2831,7 @@ private:
|
||||
static bool sInitialized;
|
||||
static uint32_t sScriptBlockerCount;
|
||||
static uint32_t sDOMNodeRemovedSuppressCount;
|
||||
static uint32_t sMicroTaskLevel;
|
||||
// Not an nsCOMArray because removing elements from those is slower
|
||||
static AutoTArray<nsCOMPtr<nsIRunnable>, 8>* sBlockedScriptRunners;
|
||||
static uint32_t sRunnersCountAtFirstBlocker;
|
||||
@@ -2869,8 +2852,6 @@ private:
|
||||
static bool sIsUserTimingLoggingEnabled;
|
||||
static bool sIsFrameTimingPrefEnabled;
|
||||
static bool sIsExperimentalAutocompleteEnabled;
|
||||
static bool sIsWebComponentsEnabled;
|
||||
static bool sIsCustomElementsEnabled;
|
||||
static bool sEncodeDecodeURLHash;
|
||||
static bool sGettersDecodeURLHash;
|
||||
static bool sPrivacyResistFingerprinting;
|
||||
@@ -2926,6 +2907,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS nsAutoMicroTask
|
||||
{
|
||||
public:
|
||||
nsAutoMicroTask()
|
||||
{
|
||||
nsContentUtils::EnterMicroTask();
|
||||
}
|
||||
~nsAutoMicroTask()
|
||||
{
|
||||
nsContentUtils::LeaveMicroTask();
|
||||
}
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
||||
@@ -524,9 +524,3 @@ nsDOMAttributeMap::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return NamedNodeMapBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
DocGroup*
|
||||
nsDOMAttributeMap::GetDocGroup() const
|
||||
{
|
||||
return mContent ? mContent->OwnerDoc()->GetDocGroup() : nullptr;
|
||||
}
|
||||
@@ -22,11 +22,6 @@
|
||||
|
||||
class nsIAtom;
|
||||
class nsIDocument;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class DocGroup;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Structure used as a key for caching Attrs in nsDOMAttributeMap's mAttributeCache.
|
||||
@@ -92,7 +87,6 @@ class nsDOMAttributeMap final : public nsIDOMMozNamedAttrMap
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::Attr Attr;
|
||||
typedef mozilla::dom::DocGroup DocGroup;
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::ErrorResult ErrorResult;
|
||||
|
||||
@@ -141,7 +135,6 @@ public:
|
||||
return mContent;
|
||||
}
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
DocGroup* GetDocGroup() const;
|
||||
|
||||
// WebIDL
|
||||
Attr* GetNamedItem(const nsAString& aAttrName);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "mozilla/dom/Animation.h"
|
||||
#include "mozilla/dom/KeyframeEffectReadOnly.h"
|
||||
#include "mozilla/dom/DocGroup.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
@@ -37,6 +36,8 @@ using namespace mozilla::dom;
|
||||
AutoTArray<RefPtr<nsDOMMutationObserver>, 4>*
|
||||
nsDOMMutationObserver::sScheduledMutationObservers = nullptr;
|
||||
|
||||
nsDOMMutationObserver* nsDOMMutationObserver::sCurrentObserver = nullptr;
|
||||
|
||||
uint32_t nsDOMMutationObserver::sMutationLevel = 0;
|
||||
uint64_t nsDOMMutationObserver::sCount = 0;
|
||||
|
||||
@@ -600,54 +601,10 @@ nsDOMMutationObserver::ScheduleForRun()
|
||||
RescheduleForRun();
|
||||
}
|
||||
|
||||
class MutationObserverMicroTask final : public MicroTaskRunnable
|
||||
{
|
||||
public:
|
||||
virtual void Run(AutoSlowOperation& aAso) override
|
||||
{
|
||||
nsDOMMutationObserver::HandleMutations(aAso);
|
||||
}
|
||||
|
||||
virtual bool Suppressed() override
|
||||
{
|
||||
return nsDOMMutationObserver::AllScheduledMutationObserversAreSuppressed();
|
||||
}
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
nsDOMMutationObserver::QueueMutationObserverMicroTask()
|
||||
{
|
||||
CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
|
||||
if (!ccjs) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<MutationObserverMicroTask> momt =
|
||||
new MutationObserverMicroTask();
|
||||
ccjs->DispatchMicroTaskRunnable(momt.forget());
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMMutationObserver::HandleMutations(mozilla::AutoSlowOperation& aAso)
|
||||
{
|
||||
if (sScheduledMutationObservers ||
|
||||
mozilla::dom::DocGroup::sPendingDocGroups) {
|
||||
HandleMutationsInternal(aAso);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMMutationObserver::RescheduleForRun()
|
||||
{
|
||||
if (!sScheduledMutationObservers) {
|
||||
CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
|
||||
if (!ccjs) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<MutationObserverMicroTask> momt =
|
||||
new MutationObserverMicroTask();
|
||||
ccjs->DispatchMicroTaskRunnable(momt.forget());
|
||||
sScheduledMutationObservers = new AutoTArray<RefPtr<nsDOMMutationObserver>, 4>;
|
||||
}
|
||||
|
||||
@@ -909,47 +866,57 @@ nsDOMMutationObserver::HandleMutation()
|
||||
mCallback->Call(this, mutations, *this);
|
||||
}
|
||||
|
||||
void
|
||||
nsDOMMutationObserver::HandleMutationsInternal(AutoSlowOperation& aAso)
|
||||
class AsyncMutationHandler : public mozilla::Runnable
|
||||
{
|
||||
nsTArray<RefPtr<nsDOMMutationObserver> >* suppressedObservers = nullptr;
|
||||
public:
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
nsDOMMutationObserver::HandleMutations();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// Let signalList be a copy of unit of related similar-origin browsing
|
||||
// contexts' signal slot list.
|
||||
nsTArray<RefPtr<HTMLSlotElement>> signalList;
|
||||
if (DocGroup::sPendingDocGroups) {
|
||||
for (uint32_t i = 0; i < DocGroup::sPendingDocGroups->Length(); ++i) {
|
||||
DocGroup* docGroup = DocGroup::sPendingDocGroups->ElementAt(i);
|
||||
signalList.AppendElements(docGroup->SignalSlotList());
|
||||
|
||||
// Empty unit of related similar-origin browsing contexts' signal slot
|
||||
// list.
|
||||
docGroup->ClearSignalSlotList();
|
||||
}
|
||||
delete DocGroup::sPendingDocGroups;
|
||||
DocGroup::sPendingDocGroups = nullptr;
|
||||
void
|
||||
nsDOMMutationObserver::HandleMutationsInternal()
|
||||
{
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
nsContentUtils::AddScriptRunner(new AsyncMutationHandler());
|
||||
return;
|
||||
}
|
||||
static RefPtr<nsDOMMutationObserver> sCurrentObserver;
|
||||
if (sCurrentObserver && !sCurrentObserver->Suppressed()) {
|
||||
// In normal cases sScheduledMutationObservers will be handled
|
||||
// after previous mutations are handled. But in case some
|
||||
// callback calls a sync API, which spins the eventloop, we need to still
|
||||
// process other mutations happening during that sync call.
|
||||
// This does *not* catch all cases, but should work for stuff running
|
||||
// in separate tabs.
|
||||
return;
|
||||
}
|
||||
|
||||
if (sScheduledMutationObservers) {
|
||||
mozilla::AutoSlowOperation aso;
|
||||
|
||||
nsTArray<RefPtr<nsDOMMutationObserver> >* suppressedObservers = nullptr;
|
||||
|
||||
while (sScheduledMutationObservers) {
|
||||
AutoTArray<RefPtr<nsDOMMutationObserver>, 4>* observers =
|
||||
sScheduledMutationObservers;
|
||||
sScheduledMutationObservers = nullptr;
|
||||
for (uint32_t i = 0; i < observers->Length(); ++i) {
|
||||
RefPtr<nsDOMMutationObserver> currentObserver =
|
||||
static_cast<nsDOMMutationObserver*>((*observers)[i]);
|
||||
if (!currentObserver->Suppressed()) {
|
||||
currentObserver->HandleMutation();
|
||||
sCurrentObserver = static_cast<nsDOMMutationObserver*>((*observers)[i]);
|
||||
if (!sCurrentObserver->Suppressed()) {
|
||||
sCurrentObserver->HandleMutation();
|
||||
} else {
|
||||
if (!suppressedObservers) {
|
||||
suppressedObservers = new nsTArray<RefPtr<nsDOMMutationObserver> >;
|
||||
}
|
||||
if (!suppressedObservers->Contains(currentObserver)) {
|
||||
suppressedObservers->AppendElement(currentObserver);
|
||||
if (!suppressedObservers->Contains(sCurrentObserver)) {
|
||||
suppressedObservers->AppendElement(sCurrentObserver);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete observers;
|
||||
aAso.CheckForInterrupt();
|
||||
aso.CheckForInterrupt();
|
||||
}
|
||||
|
||||
if (suppressedObservers) {
|
||||
@@ -960,11 +927,7 @@ nsDOMMutationObserver::HandleMutationsInternal(AutoSlowOperation& aAso)
|
||||
delete suppressedObservers;
|
||||
suppressedObservers = nullptr;
|
||||
}
|
||||
|
||||
// Fire slotchange event for each slot in signalList.
|
||||
for (uint32_t i = 0; i < signalList.Length(); ++i) {
|
||||
signalList[i]->FireSlotChangeEvent();
|
||||
}
|
||||
sCurrentObserver = nullptr;
|
||||
}
|
||||
|
||||
nsDOMMutationRecord*
|
||||
|
||||
@@ -552,24 +552,11 @@ public:
|
||||
}
|
||||
|
||||
// static methods
|
||||
static void QueueMutationObserverMicroTask();
|
||||
|
||||
static void HandleMutations(mozilla::AutoSlowOperation& aAso);
|
||||
|
||||
static bool AllScheduledMutationObserversAreSuppressed()
|
||||
static void HandleMutations()
|
||||
{
|
||||
if (sScheduledMutationObservers) {
|
||||
uint32_t len = sScheduledMutationObservers->Length();
|
||||
if (len > 0) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
if (!(*sScheduledMutationObservers)[i]->Suppressed()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
HandleMutationsInternal();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void EnterMutationHandling();
|
||||
@@ -607,7 +594,7 @@ protected:
|
||||
return false;
|
||||
}
|
||||
|
||||
static void HandleMutationsInternal(mozilla::AutoSlowOperation& aAso);
|
||||
static void HandleMutationsInternal();
|
||||
|
||||
static void AddCurrentlyHandlingObserver(nsDOMMutationObserver* aObserver,
|
||||
uint32_t aMutationLevel);
|
||||
@@ -635,6 +622,7 @@ protected:
|
||||
|
||||
static uint64_t sCount;
|
||||
static AutoTArray<RefPtr<nsDOMMutationObserver>, 4>* sScheduledMutationObservers;
|
||||
static nsDOMMutationObserver* sCurrentObserver;
|
||||
|
||||
static uint32_t sMutationLevel;
|
||||
static AutoTArray<AutoTArray<RefPtr<nsDOMMutationObserver>, 4>, 4>*
|
||||
|
||||
@@ -366,12 +366,6 @@ nsDOMTokenList::Stringify(nsAString& aResult)
|
||||
mElement->GetAttr(kNameSpaceID_None, mAttrAtom, aResult);
|
||||
}
|
||||
|
||||
DocGroup*
|
||||
nsDOMTokenList::GetDocGroup() const
|
||||
{
|
||||
return mElement ? mElement->OwnerDoc()->GetDocGroup() : nullptr;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
nsDOMTokenList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
|
||||
@@ -22,9 +22,7 @@
|
||||
|
||||
namespace mozilla {
|
||||
class ErrorResult;
|
||||
namespace dom {
|
||||
class DocGroup;
|
||||
} // namespace dom
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
class nsAttrValue;
|
||||
@@ -37,7 +35,6 @@ class nsDOMTokenList : public nsISupports,
|
||||
{
|
||||
protected:
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::dom::DocGroup DocGroup;
|
||||
typedef nsWhitespaceTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
|
||||
WhitespaceTokenizer;
|
||||
|
||||
@@ -55,8 +52,6 @@ public:
|
||||
return mElement;
|
||||
}
|
||||
|
||||
DocGroup* GetDocGroup() const;
|
||||
|
||||
uint32_t Length();
|
||||
void Item(uint32_t aIndex, nsAString& aResult)
|
||||
{
|
||||
|
||||
@@ -3473,7 +3473,7 @@ nsDOMWindowUtils::AddSheet(nsIDOMStyleSheet *aSheet, uint32_t aSheetType)
|
||||
nsIDocument::additionalSheetType type = convertSheetType(aSheetType);
|
||||
RefPtr<CSSStyleSheet> sheet = do_QueryObject(aSheet);
|
||||
NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE);
|
||||
if (sheet->GetAssociatedDocument()) {
|
||||
if (sheet->GetOwningDocument()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
return doc->AddAdditionalStyleSheet(type, sheet);
|
||||
@@ -3658,11 +3658,11 @@ nsDOMWindowUtils::GetOMTAStyle(nsIDOMElement* aElement,
|
||||
|
||||
RefPtr<nsROCSSPrimitiveValue> cssValue = nullptr;
|
||||
nsIFrame* frame = element->GetPrimaryFrame();
|
||||
if (!aPseudoElement.IsEmpty()) {
|
||||
if (frame && !aPseudoElement.IsEmpty()) {
|
||||
if (aPseudoElement.EqualsLiteral("::before")) {
|
||||
frame = nsLayoutUtils::GetBeforeFrame(element);
|
||||
frame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
} else if (aPseudoElement.EqualsLiteral("::after")) {
|
||||
frame = nsLayoutUtils::GetAfterFrame(element);
|
||||
frame = nsLayoutUtils::GetAfterFrame(frame);
|
||||
} else {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
+494
-196
File diff suppressed because it is too large.
Load diff
+235
-15
@@ -19,7 +19,6 @@
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIdentifierMapEntry.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMDocumentXBL.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
@@ -131,6 +130,151 @@ public:
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Right now our identifier map entries contain information for 'name'
|
||||
* and 'id' mappings of a given string. This is so that
|
||||
* nsHTMLDocument::ResolveName only has to do one hash lookup instead
|
||||
* of two. It's not clear whether this still matters for performance.
|
||||
*
|
||||
* We also store the document.all result list here. This is mainly so that
|
||||
* when all elements with the given ID are removed and we remove
|
||||
* the ID's nsIdentifierMapEntry, the document.all result is released too.
|
||||
* Perhaps the document.all results should have their own hashtable
|
||||
* in nsHTMLDocument.
|
||||
*/
|
||||
class nsIdentifierMapEntry : public nsStringHashKey
|
||||
{
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
|
||||
|
||||
explicit nsIdentifierMapEntry(const nsAString& aKey) :
|
||||
nsStringHashKey(&aKey), mNameContentList(nullptr)
|
||||
{
|
||||
}
|
||||
explicit nsIdentifierMapEntry(const nsAString* aKey) :
|
||||
nsStringHashKey(aKey), mNameContentList(nullptr)
|
||||
{
|
||||
}
|
||||
nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) :
|
||||
nsStringHashKey(&aOther.GetKey())
|
||||
{
|
||||
NS_ERROR("Should never be called");
|
||||
}
|
||||
~nsIdentifierMapEntry();
|
||||
|
||||
void AddNameElement(nsINode* aDocument, Element* aElement);
|
||||
void RemoveNameElement(Element* aElement);
|
||||
bool IsEmpty();
|
||||
nsBaseContentList* GetNameContentList() {
|
||||
return mNameContentList;
|
||||
}
|
||||
bool HasNameElement() const {
|
||||
return mNameContentList && mNameContentList->Length() != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the element if we know the element associated with this
|
||||
* id. Otherwise returns null.
|
||||
*/
|
||||
Element* GetIdElement();
|
||||
/**
|
||||
* Returns the list of all elements associated with this id.
|
||||
*/
|
||||
const nsTArray<Element*>& GetIdElements() const {
|
||||
return mIdContentList;
|
||||
}
|
||||
/**
|
||||
* If this entry has a non-null image element set (using SetImageElement),
|
||||
* the image element will be returned, otherwise the same as GetIdElement().
|
||||
*/
|
||||
Element* GetImageIdElement();
|
||||
/**
|
||||
* Append all the elements with this id to aElements
|
||||
*/
|
||||
void AppendAllIdContent(nsCOMArray<nsIContent>* aElements);
|
||||
/**
|
||||
* This can fire ID change callbacks.
|
||||
* @return true if the content could be added, false if we failed due
|
||||
* to OOM.
|
||||
*/
|
||||
bool AddIdElement(Element* aElement);
|
||||
/**
|
||||
* This can fire ID change callbacks.
|
||||
*/
|
||||
void RemoveIdElement(Element* aElement);
|
||||
/**
|
||||
* Set the image element override for this ID. This will be returned by
|
||||
* GetIdElement(true) if non-null.
|
||||
*/
|
||||
void SetImageElement(Element* aElement);
|
||||
bool HasIdElementExposedAsHTMLDocumentProperty();
|
||||
|
||||
bool HasContentChangeCallback() { return mChangeCallbacks != nullptr; }
|
||||
void AddContentChangeCallback(nsIDocument::IDTargetObserver aCallback,
|
||||
void* aData, bool aForImage);
|
||||
void RemoveContentChangeCallback(nsIDocument::IDTargetObserver aCallback,
|
||||
void* aData, bool aForImage);
|
||||
|
||||
/**
|
||||
* Remove all elements and notify change listeners.
|
||||
*/
|
||||
void ClearAndNotify();
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback* aCallback);
|
||||
|
||||
struct ChangeCallback {
|
||||
nsIDocument::IDTargetObserver mCallback;
|
||||
void* mData;
|
||||
bool mForImage;
|
||||
};
|
||||
|
||||
struct ChangeCallbackEntry : public PLDHashEntryHdr {
|
||||
typedef const ChangeCallback KeyType;
|
||||
typedef const ChangeCallback* KeyTypePointer;
|
||||
|
||||
explicit ChangeCallbackEntry(const ChangeCallback* aKey) :
|
||||
mKey(*aKey) { }
|
||||
ChangeCallbackEntry(const ChangeCallbackEntry& toCopy) :
|
||||
mKey(toCopy.mKey) { }
|
||||
|
||||
KeyType GetKey() const { return mKey; }
|
||||
bool KeyEquals(KeyTypePointer aKey) const {
|
||||
return aKey->mCallback == mKey.mCallback &&
|
||||
aKey->mData == mKey.mData &&
|
||||
aKey->mForImage == mKey.mForImage;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
||||
{
|
||||
return mozilla::HashGeneric(aKey->mCallback, aKey->mData);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
ChangeCallback mKey;
|
||||
};
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
void FireChangeCallbacks(Element* aOldElement, Element* aNewElement,
|
||||
bool aImageOnly = false);
|
||||
|
||||
// empty if there are no elements with this ID.
|
||||
// The elements are stored as weak pointers.
|
||||
nsTArray<Element*> mIdContentList;
|
||||
RefPtr<nsBaseContentList> mNameContentList;
|
||||
nsAutoPtr<nsTHashtable<ChangeCallbackEntry> > mChangeCallbacks;
|
||||
RefPtr<Element> mImageElement;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsDocHeaderData
|
||||
{
|
||||
public:
|
||||
@@ -149,6 +293,36 @@ public:
|
||||
nsDocHeaderData* mNext;
|
||||
};
|
||||
|
||||
class nsDOMStyleSheetList : public mozilla::dom::StyleSheetList,
|
||||
public nsStubDocumentObserver
|
||||
{
|
||||
public:
|
||||
explicit nsDOMStyleSheetList(nsIDocument* aDocument);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
// nsIDocumentObserver
|
||||
NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETADDED
|
||||
NS_DECL_NSIDOCUMENTOBSERVER_STYLESHEETREMOVED
|
||||
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
||||
|
||||
virtual nsINode* GetParentObject() const override
|
||||
{
|
||||
return mDocument;
|
||||
}
|
||||
|
||||
uint32_t Length() override;
|
||||
mozilla::StyleSheet* IndexedGetter(uint32_t aIndex, bool& aFound) override;
|
||||
|
||||
protected:
|
||||
virtual ~nsDOMStyleSheetList();
|
||||
|
||||
int32_t mLength;
|
||||
nsIDocument* mDocument;
|
||||
};
|
||||
|
||||
class nsOnloadBlocker final : public nsIRequest
|
||||
{
|
||||
public:
|
||||
@@ -333,6 +507,7 @@ class nsDocument : public nsIDocument,
|
||||
|
||||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
using nsIDocument::GetElementsByTagName;
|
||||
typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
@@ -449,6 +624,14 @@ public:
|
||||
|
||||
virtual void EnsureOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet) override;
|
||||
|
||||
/**
|
||||
* Get the (document) style sheets owned by this document.
|
||||
* These are ordered, highest priority last
|
||||
*/
|
||||
virtual int32_t GetNumberOfStyleSheets() const override;
|
||||
virtual mozilla::StyleSheet* GetStyleSheetAt(int32_t aIndex) const override;
|
||||
virtual int32_t GetIndexOfStyleSheet(
|
||||
const mozilla::StyleSheet* aSheet) const override;
|
||||
virtual void AddStyleSheet(mozilla::StyleSheet* aSheet) override;
|
||||
virtual void RemoveStyleSheet(mozilla::StyleSheet* aSheet) override;
|
||||
|
||||
@@ -459,7 +642,7 @@ public:
|
||||
virtual void RemoveStyleSheetFromStyleSets(mozilla::StyleSheet* aSheet);
|
||||
|
||||
virtual void InsertStyleSheetAt(mozilla::StyleSheet* aSheet,
|
||||
size_t aIndex) override;
|
||||
int32_t aIndex) override;
|
||||
virtual void SetStyleSheetApplicableState(mozilla::StyleSheet* aSheet,
|
||||
bool aApplicable) override;
|
||||
|
||||
@@ -610,11 +793,7 @@ public:
|
||||
|
||||
virtual void NotifyLayerManagerRecreated() override;
|
||||
|
||||
// Check whether web components are enabled for the global of aObject.
|
||||
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
|
||||
// Check whether web components are enabled for the document this node belongs
|
||||
// to.
|
||||
static bool IsWebComponentsEnabled(const nsINode* aNode);
|
||||
|
||||
private:
|
||||
void AddOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet);
|
||||
nsRadioGroupStruct* GetRadioGroupInternal(const nsAString& aName) const;
|
||||
@@ -630,13 +809,8 @@ public:
|
||||
// nsIDOMDocumentXBL
|
||||
NS_DECL_NSIDOMDOCUMENTXBL
|
||||
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementById;
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName;
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagNameNS;
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementsByClassName;
|
||||
|
||||
// nsIDOMEventTarget
|
||||
virtual nsresult GetEventTargetParent(
|
||||
virtual nsresult PreHandleEvent(
|
||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||
virtual mozilla::EventListenerManager*
|
||||
GetOrCreateListenerManager() override;
|
||||
@@ -823,7 +997,10 @@ public:
|
||||
virtual void ResetScrolledToRefAlready() override;
|
||||
virtual void SetChangeScrollPosWhenScrollingToRef(bool aValue) override;
|
||||
|
||||
virtual Element* LookupImageElement(const nsAString& aElementId) override;
|
||||
virtual Element *GetElementById(const nsAString& aElementId) override;
|
||||
virtual const nsTArray<Element*>* GetAllElementsForId(const nsAString& aElementId) const override;
|
||||
|
||||
virtual Element *LookupImageElement(const nsAString& aElementId) override;
|
||||
virtual void MozSetImageElement(const nsAString& aImageElementId,
|
||||
Element* aElement) override;
|
||||
|
||||
@@ -952,7 +1129,12 @@ public:
|
||||
// WebIDL bits
|
||||
virtual mozilla::dom::DOMImplementation*
|
||||
GetImplementation(mozilla::ErrorResult& rv) override;
|
||||
|
||||
virtual void
|
||||
RegisterElement(JSContext* aCx, const nsAString& aName,
|
||||
const mozilla::dom::ElementRegistrationOptions& aOptions,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
mozilla::ErrorResult& rv) override;
|
||||
virtual mozilla::dom::StyleSheetList* StyleSheets() override;
|
||||
virtual void SetSelectedStyleSheetSet(const nsAString& aSheetSet) override;
|
||||
virtual void GetLastStyleSheetSet(nsString& aSheetSet) override;
|
||||
virtual mozilla::dom::DOMStringList* StyleSheetSets() override;
|
||||
@@ -1174,6 +1356,7 @@ protected:
|
||||
// EndLoad() has already happened.
|
||||
nsWeakPtr mWeakSink;
|
||||
|
||||
nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheets;
|
||||
nsTArray<RefPtr<mozilla::StyleSheet>> mOnDemandBuiltInUASheets;
|
||||
nsTArray<RefPtr<mozilla::StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
|
||||
|
||||
@@ -1202,11 +1385,48 @@ protected:
|
||||
// non-null when this document is in fullscreen mode.
|
||||
nsWeakPtr mFullscreenRoot;
|
||||
|
||||
private:
|
||||
static bool CustomElementConstructor(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
|
||||
|
||||
/**
|
||||
* Check if the passed custom element name, aOptions.mIs, is a registered
|
||||
* custom element type or not, then return the custom element name for future
|
||||
* usage.
|
||||
*
|
||||
* If there is no existing custom element definition for this name, throw a
|
||||
* NotFoundError.
|
||||
*/
|
||||
const nsString* CheckCustomElementName(
|
||||
const mozilla::dom::ElementCreationOptions& aOptions,
|
||||
const nsAString& aLocalName,
|
||||
uint32_t aNamespaceID,
|
||||
ErrorResult& rv);
|
||||
|
||||
public:
|
||||
virtual already_AddRefed<mozilla::dom::CustomElementRegistry>
|
||||
GetCustomElementRegistry() override;
|
||||
|
||||
// Check whether web components are enabled for the global of aObject.
|
||||
static bool IsWebComponentsEnabled(JSContext* aCx, JSObject* aObject);
|
||||
// Check whether web components are enabled for the global of the document
|
||||
// this nodeinfo comes from.
|
||||
static bool IsWebComponentsEnabled(mozilla::dom::NodeInfo* aNodeInfo);
|
||||
// Check whether web components are enabled for the given window.
|
||||
static bool IsWebComponentsEnabled(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
RefPtr<mozilla::EventListenerManager> mListenerManager;
|
||||
RefPtr<mozilla::dom::StyleSheetList> mDOMStyleSheets;
|
||||
RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
|
||||
RefPtr<nsScriptLoader> mScriptLoader;
|
||||
nsDocHeaderData* mHeaderData;
|
||||
/* mIdentifierMap works as follows for IDs:
|
||||
* 1) Attribute changes affect the table immediately (removing and adding
|
||||
* entries as needed).
|
||||
* 2) Removals from the DOM affect the table immediately
|
||||
* 3) Additions to the DOM always update existing entries for names, and add
|
||||
* new ones for IDs.
|
||||
*/
|
||||
nsTHashtable<nsIdentifierMapEntry> mIdentifierMap;
|
||||
|
||||
nsClassHashtable<nsStringHashKey, nsRadioGroupStruct> mRadioGroups;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIParserService.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
@@ -39,7 +40,6 @@
|
||||
#include "nsISelectionPrivate.h"
|
||||
#include "nsITransferable.h" // for kUnicodeMime
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsElementTable.h"
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
@@ -1588,13 +1588,10 @@ nsHTMLCopyEncoder::IncludeInContext(nsINode *aNode)
|
||||
nsresult
|
||||
nsHTMLCopyEncoder::PromoteRange(nsIDOMRange *inRange)
|
||||
{
|
||||
RefPtr<nsRange> range = static_cast<nsRange*>(inRange);
|
||||
if (!range) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (!inRange) return NS_ERROR_NULL_POINTER;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMNode> startNode, endNode, common;
|
||||
uint32_t startOffset, endOffset;
|
||||
int32_t startOffset, endOffset;
|
||||
|
||||
rv = inRange->GetCommonAncestorContainer(getter_AddRefs(common));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@@ -1612,11 +1609,9 @@ nsHTMLCopyEncoder::PromoteRange(nsIDOMRange *inRange)
|
||||
int32_t opStartOffset, opEndOffset;
|
||||
|
||||
// examine range endpoints.
|
||||
rv = GetPromotedPoint(kStart, startNode, static_cast<int32_t>(startOffset),
|
||||
address_of(opStartNode), &opStartOffset, common);
|
||||
rv = GetPromotedPoint( kStart, startNode, startOffset, address_of(opStartNode), &opStartOffset, common);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = GetPromotedPoint(kEnd, endNode, static_cast<int32_t>(endOffset),
|
||||
address_of(opEndNode), &opEndOffset, common);
|
||||
rv = GetPromotedPoint( kEnd, endNode, endOffset, address_of(opEndNode), &opEndOffset, common);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// if both range endpoints are at the common ancestor, check for possible inclusion of ancestors
|
||||
@@ -1628,9 +1623,9 @@ nsHTMLCopyEncoder::PromoteRange(nsIDOMRange *inRange)
|
||||
}
|
||||
|
||||
// set the range to the new values
|
||||
rv = inRange->SetStart(opStartNode, static_cast<uint32_t>(opStartOffset));
|
||||
rv = inRange->SetStart(opStartNode, opStartOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = inRange->SetEnd(opEndNode, static_cast<uint32_t>(opEndOffset));
|
||||
rv = inRange->SetEnd(opEndNode, opEndOffset);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@@ -1741,6 +1736,9 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, int32_t
|
||||
rv = GetNodeLocation(node, address_of(parent), &offset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (offset == -1) return NS_OK; // we hit generated content; STOP
|
||||
nsIParserService *parserService = nsContentUtils::GetParserService();
|
||||
if (!parserService)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
while ((IsFirstNode(node)) && (!IsRoot(parent)) && (parent != common))
|
||||
{
|
||||
if (bResetPromotion)
|
||||
@@ -1748,8 +1746,11 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, int32_t
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(parent);
|
||||
if (content && content->IsHTMLElement())
|
||||
{
|
||||
if (nsHTMLElement::IsBlock(nsHTMLTags::AtomTagToId(
|
||||
content->NodeInfo()->NameAtom()))) {
|
||||
bool isBlock = false;
|
||||
parserService->IsBlock(parserService->HTMLAtomTagToId(
|
||||
content->NodeInfo()->NameAtom()), isBlock);
|
||||
if (isBlock)
|
||||
{
|
||||
bResetPromotion = false;
|
||||
}
|
||||
}
|
||||
@@ -1818,6 +1819,9 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, int32_t
|
||||
rv = GetNodeLocation(node, address_of(parent), &offset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (offset == -1) return NS_OK; // we hit generated content; STOP
|
||||
nsIParserService *parserService = nsContentUtils::GetParserService();
|
||||
if (!parserService)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
while ((IsLastNode(node)) && (!IsRoot(parent)) && (parent != common))
|
||||
{
|
||||
if (bResetPromotion)
|
||||
@@ -1825,8 +1829,11 @@ nsHTMLCopyEncoder::GetPromotedPoint(Endpoint aWhere, nsIDOMNode *aNode, int32_t
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(parent);
|
||||
if (content && content->IsHTMLElement())
|
||||
{
|
||||
if (nsHTMLElement::IsBlock(nsHTMLTags::AtomTagToId(
|
||||
content->NodeInfo()->NameAtom()))) {
|
||||
bool isBlock = false;
|
||||
parserService->IsBlock(parserService->HTMLAtomTagToId(
|
||||
content->NodeInfo()->NameAtom()), isBlock);
|
||||
if (isBlock)
|
||||
{
|
||||
bResetPromotion = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,11 +813,10 @@ nsFocusManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent)
|
||||
if (!window)
|
||||
return NS_OK;
|
||||
|
||||
// if the content is currently focused in the window, or is an
|
||||
// shadow-including inclusive ancestor of the currently focused element,
|
||||
// reset the focus within that window.
|
||||
// if the content is currently focused in the window, or is an ancestor
|
||||
// of the currently focused element, reset the focus within that window.
|
||||
nsIContent* content = window->GetFocusedNode();
|
||||
if (content && nsContentUtils::ContentIsHostIncludingDescendantOf(content, aContent)) {
|
||||
if (content && nsContentUtils::ContentIsDescendantOf(content, aContent)) {
|
||||
bool shouldShowFocusRing = window->ShouldShowFocusRing();
|
||||
window->SetFocusedNode(nullptr);
|
||||
|
||||
@@ -2458,7 +2457,7 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
|
||||
nsCOMPtr<nsIDOMNode> startNode, endNode;
|
||||
bool isCollapsed = false;
|
||||
nsCOMPtr<nsIContent> startContent, endContent;
|
||||
uint32_t startOffset = 0;
|
||||
int32_t startOffset = 0;
|
||||
if (domSelection) {
|
||||
domSelection->GetIsCollapsed(&isCollapsed);
|
||||
nsCOMPtr<nsIDOMRange> domRange;
|
||||
@@ -2472,6 +2471,7 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
|
||||
|
||||
startContent = do_QueryInterface(startNode);
|
||||
if (startContent && startContent->IsElement()) {
|
||||
NS_ASSERTION(startOffset >= 0, "Start offset cannot be negative");
|
||||
childContent = startContent->GetChildAt(startOffset);
|
||||
if (childContent) {
|
||||
startContent = childContent;
|
||||
@@ -2480,8 +2480,9 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
|
||||
|
||||
endContent = do_QueryInterface(endNode);
|
||||
if (endContent && endContent->IsElement()) {
|
||||
uint32_t endOffset = 0;
|
||||
int32_t endOffset = 0;
|
||||
domRange->GetEndOffset(&endOffset);
|
||||
NS_ASSERTION(endOffset >= 0, "End offset cannot be negative");
|
||||
childContent = endContent->GetChildAt(endOffset);
|
||||
if (childContent) {
|
||||
endContent = childContent;
|
||||
@@ -2509,7 +2510,7 @@ nsFocusManager::GetSelectionLocation(nsIDocument* aDocument,
|
||||
bool isFormControl =
|
||||
startContent->IsNodeOfType(nsINode::eHTML_FORM_CONTROL);
|
||||
|
||||
if (nodeValue.Length() == startOffset && !isFormControl &&
|
||||
if (nodeValue.Length() == (uint32_t)startOffset && !isFormControl &&
|
||||
startContent != aDocument->GetRootElement()) {
|
||||
// Yes, indeed we were at the end of the last node
|
||||
nsCOMPtr<nsIFrameEnumerator> frameTraversal;
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsMappedAttributes.h"
|
||||
#include "nsView.h"
|
||||
#include "GroupedSHistory.h"
|
||||
#include "PartialSHistory.h"
|
||||
@@ -937,8 +936,6 @@ nsFrameLoader::MarginsChanged(uint32_t aMarginWidth,
|
||||
RefPtr<nsPresContext> presContext;
|
||||
mDocShell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext)
|
||||
// rebuild, because now the same nsMappedAttributes* will produce
|
||||
// a different style
|
||||
presContext->RebuildAllStyleData(nsChangeHint(0), eRestyle_Subtree);
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
|
||||
virtual EventStates IntrinsicState() const override;
|
||||
|
||||
virtual nsresult GetEventTargetParent(EventChainPreVisitor& aVisitor) override
|
||||
virtual nsresult PreHandleEvent(EventChainPreVisitor& aVisitor) override
|
||||
{
|
||||
MOZ_ASSERT(IsInNativeAnonymousSubtree());
|
||||
if (aVisitor.mEvent->mMessage == eLoad ||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
// Don't propagate the events to the parent.
|
||||
return NS_OK;
|
||||
}
|
||||
return nsXMLElement::GetEventTargetParent(aVisitor);
|
||||
return nsXMLElement::PreHandleEvent(aVisitor);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/HTMLSlotElement.h"
|
||||
#include "mozilla/dom/ShadowRoot.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
@@ -737,18 +736,21 @@ nsGenericDOMDataNode::SetShadowRoot(ShadowRoot* aShadowRoot)
|
||||
{
|
||||
}
|
||||
|
||||
HTMLSlotElement*
|
||||
nsGenericDOMDataNode::GetAssignedSlot() const
|
||||
{
|
||||
nsDataSlots *slots = GetExistingDataSlots();
|
||||
return slots ? slots->mAssignedSlot.get() : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericDOMDataNode::SetAssignedSlot(HTMLSlotElement* aSlot)
|
||||
nsTArray<nsIContent*>&
|
||||
nsGenericDOMDataNode::DestInsertionPoints()
|
||||
{
|
||||
nsDataSlots *slots = DataSlots();
|
||||
slots->mAssignedSlot = aSlot;
|
||||
return slots->mDestInsertionPoints;
|
||||
}
|
||||
|
||||
nsTArray<nsIContent*>*
|
||||
nsGenericDOMDataNode::GetExistingDestInsertionPoints() const
|
||||
{
|
||||
nsDataSlots *slots = GetExistingDataSlots();
|
||||
if (slots) {
|
||||
return &slots->mDestInsertionPoints;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsXBLBinding *
|
||||
@@ -791,6 +793,17 @@ nsGenericDOMDataNode::SetXBLInsertionParent(nsIContent* aContent)
|
||||
}
|
||||
}
|
||||
|
||||
CustomElementData *
|
||||
nsGenericDOMDataNode::GetCustomElementData() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsGenericDOMDataNode::SetCustomElementData(CustomElementData* aData)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
nsGenericDOMDataNode::IsNodeOfType(uint32_t aFlags) const
|
||||
{
|
||||
@@ -841,9 +854,6 @@ nsGenericDOMDataNode::nsDataSlots::Traverse(nsCycleCollectionTraversalCallback &
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
|
||||
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAssignedSlot");
|
||||
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mAssignedSlot.get()));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -851,7 +861,6 @@ nsGenericDOMDataNode::nsDataSlots::Unlink()
|
||||
{
|
||||
mXBLInsertionParent = nullptr;
|
||||
mContainingShadow = nullptr;
|
||||
mAssignedSlot = nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
class nsIDocument;
|
||||
class nsIDOMText;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class HTMLSlotElement;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#define DATA_NODE_FLAG_BIT(n_) NODE_FLAG_BIT(NODE_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
|
||||
// Data node specific flags
|
||||
@@ -160,14 +154,17 @@ public:
|
||||
virtual void SetXBLBinding(nsXBLBinding* aBinding,
|
||||
nsBindingManager* aOldBindingManager = nullptr) override;
|
||||
virtual mozilla::dom::ShadowRoot *GetContainingShadow() const override;
|
||||
virtual nsTArray<nsIContent*> &DestInsertionPoints() override;
|
||||
virtual nsTArray<nsIContent*> *GetExistingDestInsertionPoints() const override;
|
||||
virtual void SetShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot) override;
|
||||
virtual mozilla::dom::HTMLSlotElement* GetAssignedSlot() const override;
|
||||
virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) override;
|
||||
virtual nsIContent *GetXBLInsertionParent() const override;
|
||||
virtual void SetXBLInsertionParent(nsIContent* aContent) override;
|
||||
virtual bool IsNodeOfType(uint32_t aFlags) const override;
|
||||
virtual bool IsLink(nsIURI** aURI) const override;
|
||||
|
||||
virtual mozilla::dom::CustomElementData* GetCustomElementData() const override;
|
||||
virtual void SetCustomElementData(mozilla::dom::CustomElementData* aData) override;
|
||||
|
||||
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const;
|
||||
virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
|
||||
@@ -267,9 +264,9 @@ protected:
|
||||
RefPtr<mozilla::dom::ShadowRoot> mContainingShadow;
|
||||
|
||||
/**
|
||||
* @see nsIContent::GetAssignedSlot
|
||||
* @see nsIContent::GetDestInsertionPoints
|
||||
*/
|
||||
RefPtr<mozilla::dom::HTMLSlotElement> mAssignedSlot;
|
||||
nsTArray<nsIContent*> mDestInsertionPoints;
|
||||
};
|
||||
|
||||
// Override from nsINode
|
||||
|
||||
@@ -580,6 +580,7 @@ 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")
|
||||
@@ -909,9 +910,7 @@ 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")
|
||||
@@ -1561,11 +1560,11 @@ GK_ATOM(saturate, "saturate")
|
||||
GK_ATOM(saturation, "saturation")
|
||||
GK_ATOM(set, "set")
|
||||
GK_ATOM(seed, "seed")
|
||||
GK_ATOM(shadow, "shadow")
|
||||
GK_ATOM(shape_rendering, "shape-rendering")
|
||||
GK_ATOM(skewX, "skewX")
|
||||
GK_ATOM(skewY, "skewY")
|
||||
GK_ATOM(slope, "slope")
|
||||
GK_ATOM(slot, "slot")
|
||||
GK_ATOM(softLight, "soft-light")
|
||||
GK_ATOM(spacing, "spacing")
|
||||
GK_ATOM(spacingAndGlyphs, "spacingAndGlyphs")
|
||||
@@ -2145,14 +2144,12 @@ GK_ATOM(ongamepaddisconnected, "ongamepaddisconnected")
|
||||
#endif
|
||||
|
||||
// Content property names
|
||||
GK_ATOM(afterPseudoProperty, "afterPseudoProperty") // nsXMLElement*
|
||||
GK_ATOM(animationsProperty, "AnimationsProperty") // FrameAnimations*
|
||||
GK_ATOM(animationsOfBeforeProperty, "AnimationsOfBeforeProperty") // FrameAnimations*
|
||||
GK_ATOM(animationsOfAfterProperty, "AnimationsOfAfterProperty") // FrameAnimations*
|
||||
GK_ATOM(animationEffectsProperty, "AnimationEffectsProperty") // EffectSet*
|
||||
GK_ATOM(animationEffectsForBeforeProperty, "AnimationsEffectsForBeforeProperty") // EffectSet*
|
||||
GK_ATOM(animationEffectsForAfterProperty, "AnimationsEffectsForAfterProperty") // EffectSet*
|
||||
GK_ATOM(beforePseudoProperty, "beforePseudoProperty") // nsXMLElement*
|
||||
GK_ATOM(cssPseudoElementBeforeProperty, "CSSPseudoElementBeforeProperty") // CSSPseudoElement*
|
||||
GK_ATOM(cssPseudoElementAfterProperty, "CSSPseudoElementAfterProperty") // CSSPseudoElement*
|
||||
GK_ATOM(transitionsProperty, "TransitionsProperty") // FrameTransitions*
|
||||
@@ -2165,7 +2162,6 @@ GK_ATOM(lockedStyleStates, "lockedStyleStates")
|
||||
GK_ATOM(apzCallbackTransform, "apzCallbackTransform")
|
||||
GK_ATOM(restylableAnonymousNode, "restylableAnonymousNode")
|
||||
GK_ATOM(paintRequestTime, "PaintRequestTime")
|
||||
GK_ATOM(pseudoProperty, "PseudoProperty") // CSSPseudoElementType
|
||||
|
||||
// Languages for lang-specific transforms
|
||||
GK_ATOM(Japanese, "ja")
|
||||
|
||||
@@ -3577,10 +3577,9 @@ nsGlobalWindow::WillHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGlobalWindow::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
nsGlobalWindow::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
NS_PRECONDITION(IsInnerWindow(),
|
||||
"GetEventTargetParent is used on outer window!?");
|
||||
NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
|
||||
EventMessage msg = aVisitor.mEvent->mMessage;
|
||||
|
||||
aVisitor.mCanHandle = true;
|
||||
@@ -3608,7 +3607,7 @@ nsGlobalWindow::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
aVisitor.SetParentTarget(GetParentTarget(), true);
|
||||
aVisitor.mParentTarget = GetParentTarget();
|
||||
|
||||
// Handle 'active' event.
|
||||
if (!mIdleObservers.IsEmpty() &&
|
||||
@@ -3813,7 +3812,7 @@ nsGlobalWindow::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||
} else if (aVisitor.mEvent->mMessage == eLoad &&
|
||||
aVisitor.mEvent->IsTrusted()) {
|
||||
// This is page load event since load events don't propagate to |window|.
|
||||
// @see nsDocument::GetEventTargetParent.
|
||||
// @see nsDocument::PreHandleEvent.
|
||||
mIsDocumentLoaded = true;
|
||||
|
||||
nsCOMPtr<Element> element = GetOuterWindow()->GetFrameElementInternal();
|
||||
@@ -4242,9 +4241,8 @@ CustomElementRegistry*
|
||||
nsGlobalWindow::CustomElements()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(IsInnerWindow());
|
||||
|
||||
if (!mCustomElements) {
|
||||
mCustomElements = new CustomElementRegistry(AsInner());
|
||||
mCustomElements = CustomElementRegistry::Create(AsInner());
|
||||
}
|
||||
|
||||
return mCustomElements;
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsElementTable.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
@@ -348,13 +347,20 @@ nsHTMLContentSerializer::AppendElementEnd(Element* aElement,
|
||||
}
|
||||
|
||||
if (ns == kNameSpaceID_XHTML) {
|
||||
bool isContainer =
|
||||
nsHTMLElement::IsContainer(nsHTMLTags::CaseSensitiveAtomTagToId(name));
|
||||
if (!isContainer) {
|
||||
// Keep this in sync with the cleanup at the end of this method.
|
||||
MOZ_ASSERT(name != nsGkAtoms::body);
|
||||
MaybeLeaveFromPreContent(content);
|
||||
return NS_OK;
|
||||
nsIParserService* parserService = nsContentUtils::GetParserService();
|
||||
|
||||
if (parserService) {
|
||||
bool isContainer;
|
||||
|
||||
parserService->
|
||||
IsContainer(parserService->HTMLCaseSensitiveAtomTagToId(name),
|
||||
isContainer);
|
||||
if (!isContainer) {
|
||||
// Keep this in sync with the cleanup at the end of this method.
|
||||
MOZ_ASSERT(name != nsGkAtoms::body);
|
||||
MaybeLeaveFromPreContent(content);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+32
-61
@@ -26,7 +26,7 @@ namespace mozilla {
|
||||
class EventChainPreVisitor;
|
||||
namespace dom {
|
||||
class ShadowRoot;
|
||||
class HTMLSlotElement;
|
||||
struct CustomElementData;
|
||||
} // namespace dom
|
||||
namespace widget {
|
||||
struct IMEState;
|
||||
@@ -145,14 +145,7 @@ public:
|
||||
* Skip native anonymous content created for placeholder of HTML input,
|
||||
* used in conjunction with eAllChildren or eAllButXBL.
|
||||
*/
|
||||
eSkipPlaceholderContent = 2,
|
||||
|
||||
/**
|
||||
* Skip native anonymous content created by ancestor frames of the root
|
||||
* element's primary frame, such as scrollbar elements created by the root
|
||||
* scroll frame.
|
||||
*/
|
||||
eSkipDocumentLevelNativeAnonymousContent = 4,
|
||||
eSkipPlaceholderContent = 2
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -194,7 +187,7 @@ public:
|
||||
void SetIsNativeAnonymousRoot()
|
||||
{
|
||||
SetFlags(NODE_IS_ANONYMOUS_ROOT | NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE |
|
||||
NODE_IS_NATIVE_ANONYMOUS_ROOT | NODE_IS_NATIVE_ANONYMOUS);
|
||||
NODE_IS_NATIVE_ANONYMOUS_ROOT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -697,35 +690,18 @@ public:
|
||||
virtual mozilla::dom::ShadowRoot *GetContainingShadow() const = 0;
|
||||
|
||||
/**
|
||||
* Gets the shadow host if this content is in a shadow tree. That is, the host
|
||||
* of |GetContainingShadow|, if its not null.
|
||||
*
|
||||
* @return The shadow host, if this is in shadow tree, or null.
|
||||
* Gets an array of destination insertion points where this content
|
||||
* is distributed by web component distribution algorithms.
|
||||
* The array is created if it does not already exist.
|
||||
*/
|
||||
nsIContent* GetContainingShadowHost() const;
|
||||
virtual nsTArray<nsIContent*> &DestInsertionPoints() = 0;
|
||||
|
||||
/**
|
||||
* Gets the assigned slot associated with this content.
|
||||
*
|
||||
* @return The assigned slot element or null.
|
||||
* Same as DestInsertionPoints except that this method will return
|
||||
* null if the array of destination insertion points does not already
|
||||
* exist.
|
||||
*/
|
||||
virtual mozilla::dom::HTMLSlotElement* GetAssignedSlot() const = 0;
|
||||
|
||||
/**
|
||||
* Sets the assigned slot associated with this content.
|
||||
*
|
||||
* @param aSlot The assigned slot.
|
||||
*/
|
||||
virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) = 0;
|
||||
|
||||
/**
|
||||
* Gets the assigned slot associated with this content based on parent's
|
||||
* shadow root mode. Returns null if parent's shadow root is "closed".
|
||||
* https://dom.spec.whatwg.org/#dom-slotable-assignedslot
|
||||
*
|
||||
* @return The assigned slot element or null.
|
||||
*/
|
||||
mozilla::dom::HTMLSlotElement* GetAssignedSlotByMode() const;
|
||||
virtual nsTArray<nsIContent*> *GetExistingDestInsertionPoints() const = 0;
|
||||
|
||||
/**
|
||||
* Gets the insertion parent element of the XBL binding.
|
||||
@@ -748,9 +724,26 @@ public:
|
||||
*/
|
||||
inline nsIContent *GetFlattenedTreeParent() const;
|
||||
|
||||
// Helper method, which we leave public so that it's accessible from nsINode.
|
||||
enum FlattenedParentType { eNotForStyle, eForStyle };
|
||||
nsINode* GetFlattenedTreeParentNodeInternal(FlattenedParentType aType) const;
|
||||
/**
|
||||
* Helper method, which we leave public so that it's accessible from nsINode.
|
||||
*/
|
||||
nsINode *GetFlattenedTreeParentNodeInternal() const;
|
||||
|
||||
/**
|
||||
* Gets the custom element data used by web components custom element.
|
||||
* Custom element data is created at the first attempt to enqueue a callback.
|
||||
*
|
||||
* @return The custom element data or null if none.
|
||||
*/
|
||||
virtual mozilla::dom::CustomElementData *GetCustomElementData() const = 0;
|
||||
|
||||
/**
|
||||
* Sets the custom element data, ownership of the
|
||||
* callback data is taken by this content.
|
||||
*
|
||||
* @param aCallbackData The custom element data.
|
||||
*/
|
||||
virtual void SetCustomElementData(mozilla::dom::CustomElementData* aData) = 0;
|
||||
|
||||
/**
|
||||
* API to check if this is a link that's traversed in response to user input
|
||||
@@ -968,18 +961,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if this element is native-anonymous scrollbar content.
|
||||
bool IsNativeScrollbarContent() const {
|
||||
return IsNativeAnonymous() &&
|
||||
IsAnyOfXULElements(nsGkAtoms::scrollbar,
|
||||
nsGkAtoms::resizer,
|
||||
nsGkAtoms::scrollcorner);
|
||||
}
|
||||
|
||||
// Overloaded from nsINode
|
||||
virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
|
||||
|
||||
virtual nsresult GetEventTargetParent(
|
||||
virtual nsresult PreHandleEvent(
|
||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||
|
||||
virtual bool IsPurple() = 0;
|
||||
@@ -993,12 +978,6 @@ protected:
|
||||
*/
|
||||
nsIAtom* DoGetID() const;
|
||||
|
||||
/**
|
||||
* Returns the assigned slot, if it exists, or the direct parent, if it's a
|
||||
* fallback content of a slot.
|
||||
*/
|
||||
nsINode* GetFlattenedTreeParentForMaybeAssignedNode() const;
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
@@ -1052,15 +1031,7 @@ inline nsIContent* nsINode::AsContent()
|
||||
{ \
|
||||
return aContent->_check ? static_cast<_class*>(aContent) : nullptr; \
|
||||
} \
|
||||
static const _class* FromContent(const nsIContent* aContent) \
|
||||
{ \
|
||||
return aContent->_check ? static_cast<const _class*>(aContent) : nullptr; \
|
||||
} \
|
||||
static _class* FromContentOrNull(nsIContent* aContent) \
|
||||
{ \
|
||||
return aContent ? FromContent(aContent) : nullptr; \
|
||||
} \
|
||||
static const _class* FromContentOrNull(const nsIContent* aContent) \
|
||||
{ \
|
||||
return aContent ? FromContent(aContent) : nullptr; \
|
||||
}
|
||||
|
||||
@@ -33,15 +33,14 @@ inline mozilla::dom::ShadowRoot* nsIContent::GetShadowRoot() const
|
||||
return AsElement()->FastGetShadowRoot();
|
||||
}
|
||||
|
||||
template<nsIContent::FlattenedParentType Type>
|
||||
static inline nsINode*
|
||||
GetFlattenedTreeParentNode(const nsINode* aNode)
|
||||
inline nsINode* nsINode::GetFlattenedTreeParentNode() const
|
||||
{
|
||||
nsINode* parent = aNode->GetParentNode();
|
||||
nsINode* parent = GetParentNode();
|
||||
|
||||
// Try to short-circuit past the complicated and not-exactly-fast logic for
|
||||
// computing the flattened parent.
|
||||
//
|
||||
// There are four cases where we need might something other than parentNode:
|
||||
// There are three cases where we need might something other than parentNode:
|
||||
// (1) The node is an explicit child of an XBL-bound element, re-bound
|
||||
// to an XBL insertion point.
|
||||
// (2) The node is a top-level element in a shadow tree, whose flattened
|
||||
@@ -49,29 +48,16 @@ GetFlattenedTreeParentNode(const nsINode* aNode)
|
||||
// is the shadow root).
|
||||
// (3) The node is an explicit child of an element with a shadow root,
|
||||
// re-bound to an insertion point.
|
||||
// (4) We want the flattened parent for style, and the node is the root
|
||||
// of a native anonymous content subtree parented to the document's
|
||||
// root element.
|
||||
bool needSlowCall = aNode->HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
|
||||
aNode->IsInShadowTree() ||
|
||||
(parent &&
|
||||
parent->IsContent() &&
|
||||
parent->AsContent()->GetShadowRoot()) ||
|
||||
(Type == nsIContent::eForStyle &&
|
||||
aNode->IsContent() &&
|
||||
aNode->AsContent()->IsRootOfNativeAnonymousSubtree() &&
|
||||
aNode->OwnerDoc()->GetRootElement() == parent);
|
||||
bool needSlowCall = HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) ||
|
||||
IsInShadowTree() ||
|
||||
(parent && parent->IsContent() &&
|
||||
parent->AsContent()->GetShadowRoot());
|
||||
if (MOZ_UNLIKELY(needSlowCall)) {
|
||||
MOZ_ASSERT(aNode->IsContent());
|
||||
return aNode->AsContent()->GetFlattenedTreeParentNodeInternal(Type);
|
||||
MOZ_ASSERT(IsContent());
|
||||
return AsContent()->GetFlattenedTreeParentNodeInternal();
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
inline nsINode*
|
||||
nsINode::GetFlattenedTreeParentNode() const
|
||||
{
|
||||
return ::GetFlattenedTreeParentNode<nsIContent::eNotForStyle>(this);
|
||||
return parent;
|
||||
}
|
||||
|
||||
inline nsIContent*
|
||||
@@ -81,16 +67,5 @@ nsIContent::GetFlattenedTreeParent() const
|
||||
return (parent && parent->IsContent()) ? parent->AsContent() : nullptr;
|
||||
}
|
||||
|
||||
inline nsINode*
|
||||
nsINode::GetFlattenedTreeParentNodeForStyle() const
|
||||
{
|
||||
return ::GetFlattenedTreeParentNode<nsIContent::eForStyle>(this);
|
||||
}
|
||||
|
||||
inline bool
|
||||
nsINode::NodeOrAncestorHasDirAuto() const
|
||||
{
|
||||
return AncestorHasDirAuto() || (IsElement() && AsElement()->HasDirAuto());
|
||||
}
|
||||
|
||||
#endif // nsIContentInlines_h
|
||||
+69
-73
@@ -34,7 +34,6 @@
|
||||
#include "prclist.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/dom/DocumentOrShadowRoot.h"
|
||||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/StyleBackendType.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
@@ -62,7 +61,6 @@ class nsFrameLoader;
|
||||
class nsHTMLCSSStyleSheet;
|
||||
class nsHTMLDocument;
|
||||
class nsHTMLStyleSheet;
|
||||
class nsGenericHTMLElement;
|
||||
class nsIAtom;
|
||||
class nsIBFCacheEntry;
|
||||
class nsIChannel;
|
||||
@@ -134,6 +132,7 @@ class DOMIntersectionObserver;
|
||||
class DOMStringList;
|
||||
class Element;
|
||||
struct ElementCreationOptions;
|
||||
struct ElementRegistrationOptions;
|
||||
class Event;
|
||||
class EventTarget;
|
||||
class FontFaceSet;
|
||||
@@ -197,8 +196,7 @@ class nsContentList;
|
||||
|
||||
// Document interface. This is implemented by all document objects in
|
||||
// Gecko.
|
||||
class nsIDocument : public nsINode,
|
||||
public mozilla::dom::DocumentOrShadowRoot
|
||||
class nsIDocument : public nsINode
|
||||
{
|
||||
typedef mozilla::dom::GlobalObject GlobalObject;
|
||||
|
||||
@@ -499,7 +497,7 @@ public:
|
||||
* to remove it.
|
||||
*/
|
||||
typedef bool (* IDTargetObserver)(Element* aOldElement,
|
||||
Element* aNewelement, void* aData);
|
||||
Element* aNewelement, void* aData);
|
||||
|
||||
/**
|
||||
* Add an IDTargetObserver for a specific ID. The IDTargetObserver
|
||||
@@ -1038,11 +1036,6 @@ public:
|
||||
Element* GetHeadElement() {
|
||||
return GetHtmlChildElement(nsGkAtoms::head);
|
||||
}
|
||||
// Get the "body" in the sense of document.body: The first <body> or
|
||||
// <frameset> that's a child of a root <html>
|
||||
nsGenericHTMLElement* GetBody();
|
||||
// Set the "body" in the sense of document.body.
|
||||
void SetBody(nsGenericHTMLElement* aBody, mozilla::ErrorResult& rv);
|
||||
|
||||
/**
|
||||
* Accessors to the collection of stylesheets owned by this document.
|
||||
@@ -1071,19 +1064,40 @@ public:
|
||||
*/
|
||||
virtual void EnsureOnDemandBuiltInUASheet(mozilla::StyleSheet* aSheet) = 0;
|
||||
|
||||
mozilla::dom::StyleSheetList* StyleSheets()
|
||||
{
|
||||
return &DocumentOrShadowRoot::EnsureDOMStyleSheets();
|
||||
}
|
||||
/**
|
||||
* Get the number of (document) stylesheets
|
||||
*
|
||||
* @return the number of stylesheets
|
||||
* @throws no exceptions
|
||||
*/
|
||||
virtual int32_t GetNumberOfStyleSheets() const = 0;
|
||||
|
||||
/**
|
||||
* Get a particular stylesheet
|
||||
* @param aIndex the index the stylesheet lives at. This is zero-based
|
||||
* @return the stylesheet at aIndex. Null if aIndex is out of range.
|
||||
* @throws no exceptions
|
||||
*/
|
||||
virtual mozilla::StyleSheet* GetStyleSheetAt(int32_t aIndex) const = 0;
|
||||
|
||||
/**
|
||||
* Insert a sheet at a particular spot in the stylesheet list (zero-based)
|
||||
* @param aSheet the sheet to insert
|
||||
* @param aIndex the index to insert at.
|
||||
* @param aIndex the index to insert at. This index will be
|
||||
* adjusted for the "special" sheets.
|
||||
* @throws no exceptions
|
||||
*/
|
||||
virtual void InsertStyleSheetAt(mozilla::StyleSheet* aSheet,
|
||||
size_t aIndex) = 0;
|
||||
int32_t aIndex) = 0;
|
||||
|
||||
/**
|
||||
* Get the index of a particular stylesheet. This will _always_
|
||||
* consider the "special" sheets as part of the sheet list.
|
||||
* @param aSheet the sheet to get the index of
|
||||
* @return aIndex the index of the sheet in the full list
|
||||
*/
|
||||
virtual int32_t GetIndexOfStyleSheet(
|
||||
const mozilla::StyleSheet* aSheet) const = 0;
|
||||
|
||||
/**
|
||||
* Replace the stylesheets in aOldSheets with the stylesheets in
|
||||
@@ -1134,13 +1148,11 @@ public:
|
||||
* sheets for this document, returns the index that aSheet should
|
||||
* be inserted at to maintain document ordering.
|
||||
*
|
||||
* Type T has to cast to StyleSheet*.
|
||||
*
|
||||
* Defined in nsIDocumentInlines.h.
|
||||
*/
|
||||
template<typename T>
|
||||
size_t FindDocStyleSheetInsertionPoint(const nsTArray<T>& aDocSheets,
|
||||
const mozilla::StyleSheet& aSheet);
|
||||
size_t FindDocStyleSheetInsertionPoint(const nsTArray<RefPtr<T>>& aDocSheets,
|
||||
T* aSheet);
|
||||
|
||||
/**
|
||||
* Get this document's CSSLoader. This is guaranteed to not return null.
|
||||
@@ -2357,10 +2369,19 @@ public:
|
||||
virtual void ResetScrolledToRefAlready() = 0;
|
||||
virtual void SetChangeScrollPosWhenScrollingToRef(bool aValue) = 0;
|
||||
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementById;
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagName;
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementsByTagNameNS;
|
||||
using mozilla::dom::DocumentOrShadowRoot::GetElementsByClassName;
|
||||
/**
|
||||
* This method is similar to GetElementById() from nsIDOMDocument but it
|
||||
* returns a mozilla::dom::Element instead of a nsIDOMElement.
|
||||
* It prevents converting nsIDOMElement to mozilla::dom::Element which is
|
||||
* already converted from mozilla::dom::Element.
|
||||
*/
|
||||
virtual Element* GetElementById(const nsAString& aElementId) = 0;
|
||||
|
||||
/**
|
||||
* This method returns _all_ the elements in this document which
|
||||
* have id aElementId, if there are any. Otherwise it returns null.
|
||||
*/
|
||||
virtual const nsTArray<Element*>* GetAllElementsForId(const nsAString& aElementId) const = 0;
|
||||
|
||||
/**
|
||||
* Lookup an image element using its associated ID, which is usually provided
|
||||
@@ -2552,14 +2573,34 @@ public:
|
||||
}
|
||||
|
||||
enum ElementCallbackType {
|
||||
eConnected,
|
||||
eDisconnected,
|
||||
eAdopted,
|
||||
eCreated,
|
||||
eAttached,
|
||||
eDetached,
|
||||
eAttributeChanged
|
||||
};
|
||||
|
||||
nsIDocument* GetTopLevelContentDocument();
|
||||
|
||||
virtual void
|
||||
RegisterElement(JSContext* aCx, const nsAString& aName,
|
||||
const mozilla::dom::ElementRegistrationOptions& aOptions,
|
||||
JS::MutableHandle<JSObject*> aRetval,
|
||||
mozilla::ErrorResult& rv) = 0;
|
||||
virtual already_AddRefed<mozilla::dom::CustomElementRegistry>
|
||||
GetCustomElementRegistry() = 0;
|
||||
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagName(const nsAString& aTagName)
|
||||
{
|
||||
return NS_GetContentList(this, kNameSpaceID_Unknown, aTagName);
|
||||
}
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
||||
const nsAString& aLocalName,
|
||||
mozilla::ErrorResult& aResult);
|
||||
already_AddRefed<nsContentList>
|
||||
GetElementsByClassName(const nsAString& aClasses);
|
||||
// GetElementById defined above
|
||||
virtual already_AddRefed<Element>
|
||||
CreateElement(const nsAString& aTagName,
|
||||
const mozilla::dom::ElementCreationOptionsOrString& aOptions,
|
||||
@@ -2659,6 +2700,7 @@ public:
|
||||
return mVisibilityState;
|
||||
}
|
||||
#endif
|
||||
virtual mozilla::dom::StyleSheetList* StyleSheets() = 0;
|
||||
void GetSelectedStyleSheetSet(nsAString& aSheetSet);
|
||||
virtual void SetSelectedStyleSheetSet(const nsAString& aSheetSet) = 0;
|
||||
virtual void GetLastStyleSheetSet(nsString& aSheetSet) = 0;
|
||||
@@ -2830,27 +2872,6 @@ public:
|
||||
virtual void ScheduleIntersectionObserverNotification() = 0;
|
||||
virtual void NotifyIntersectionObservers() = 0;
|
||||
|
||||
bool ShouldThrowOnDynamicMarkupInsertion()
|
||||
{
|
||||
return mThrowOnDynamicMarkupInsertionCounter;
|
||||
}
|
||||
|
||||
void IncrementThrowOnDynamicMarkupInsertionCounter()
|
||||
{
|
||||
++mThrowOnDynamicMarkupInsertionCounter;
|
||||
}
|
||||
|
||||
void DecrementThrowOnDynamicMarkupInsertionCounter()
|
||||
{
|
||||
MOZ_ASSERT(mThrowOnDynamicMarkupInsertionCounter);
|
||||
--mThrowOnDynamicMarkupInsertionCounter;
|
||||
}
|
||||
|
||||
bool IsWebComponentsEnabled() const
|
||||
{
|
||||
return mIsWebComponentsEnabled;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||
{
|
||||
@@ -2994,9 +3015,6 @@ protected:
|
||||
// container for per-context fonts (downloadable, SVG, etc.)
|
||||
RefPtr<mozilla::dom::FontFaceSet> mFontFaceSet;
|
||||
|
||||
// True if dom.webcomponents.enabled pref is set when document is created.
|
||||
bool mIsWebComponentsEnabled : 1;
|
||||
|
||||
// Compatibility mode
|
||||
nsCompatibility mCompatMode;
|
||||
|
||||
@@ -3301,11 +3319,6 @@ protected:
|
||||
|
||||
uint32_t mBlockDOMContentLoaded;
|
||||
|
||||
// Used in conjunction with the create-an-element-for-the-token algorithm to
|
||||
// prevent custom element constructors from being able to use document.open(),
|
||||
// document.close(), and document.write() when they are invoked by the parser.
|
||||
uint32_t mThrowOnDynamicMarkupInsertionCounter;
|
||||
|
||||
// Our live MediaQueryLists
|
||||
PRCList mDOMMediaQueryLists;
|
||||
|
||||
@@ -3379,23 +3392,6 @@ private:
|
||||
uint32_t mMicroTaskLevel;
|
||||
};
|
||||
|
||||
class MOZ_RAII AutoSetThrowOnDynamicMarkupInsertionCounter final {
|
||||
public:
|
||||
explicit AutoSetThrowOnDynamicMarkupInsertionCounter(
|
||||
nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
{
|
||||
mDocument->IncrementThrowOnDynamicMarkupInsertionCounter();
|
||||
}
|
||||
|
||||
~AutoSetThrowOnDynamicMarkupInsertionCounter() {
|
||||
mDocument->DecrementThrowOnDynamicMarkupInsertionCounter();
|
||||
}
|
||||
|
||||
private:
|
||||
nsIDocument* mDocument;
|
||||
};
|
||||
|
||||
// XXX These belong somewhere else
|
||||
nsresult
|
||||
NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
|
||||
|
||||
@@ -19,23 +19,24 @@ nsIDocument::GetBodyElement()
|
||||
template<typename T>
|
||||
size_t
|
||||
nsIDocument::FindDocStyleSheetInsertionPoint(
|
||||
const nsTArray<T>& aDocSheets,
|
||||
const mozilla::StyleSheet& aSheet)
|
||||
const nsTArray<RefPtr<T>>& aDocSheets,
|
||||
T* aSheet)
|
||||
{
|
||||
nsStyleSheetService* sheetService = nsStyleSheetService::GetInstance();
|
||||
|
||||
// lowest index first
|
||||
int32_t newDocIndex = IndexOfSheet(aSheet);
|
||||
int32_t newDocIndex = GetIndexOfStyleSheet(aSheet);
|
||||
|
||||
size_t count = aDocSheets.Length();
|
||||
size_t index = 0;
|
||||
for (; index < count; index++) {
|
||||
auto* sheet = static_cast<mozilla::StyleSheet*>(aDocSheets[index]);
|
||||
MOZ_ASSERT(sheet);
|
||||
int32_t sheetDocIndex = IndexOfSheet(*sheet);
|
||||
int32_t count = aDocSheets.Length();
|
||||
int32_t index;
|
||||
for (index = 0; index < count; index++) {
|
||||
T* sheet = aDocSheets[index];
|
||||
int32_t sheetDocIndex = GetIndexOfStyleSheet(sheet);
|
||||
if (sheetDocIndex > newDocIndex)
|
||||
break;
|
||||
|
||||
mozilla::StyleSheet* sheetHandle = sheet;
|
||||
|
||||
// If the sheet is not owned by the document it can be an author
|
||||
// sheet registered at nsStyleSheetService or an additional author
|
||||
// sheet on the document, which means the new
|
||||
@@ -43,11 +44,11 @@ nsIDocument::FindDocStyleSheetInsertionPoint(
|
||||
if (sheetDocIndex < 0) {
|
||||
if (sheetService) {
|
||||
auto& authorSheets = *sheetService->AuthorStyleSheets();
|
||||
if (authorSheets.IndexOf(sheet) != authorSheets.NoIndex) {
|
||||
if (authorSheets.IndexOf(sheetHandle) != authorSheets.NoIndex) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sheet == GetFirstAdditionalAuthorSheet()) {
|
||||
if (sheetHandle == GetFirstAdditionalAuthorSheet()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ interface nsIImageLoadingContent : imgINotificationObserver
|
||||
* the image was blocked. This status always refers to the
|
||||
* CURRENT_REQUEST load.
|
||||
*/
|
||||
[infallible] readonly attribute short imageBlockingStatus;
|
||||
readonly attribute short imageBlockingStatus;
|
||||
|
||||
/**
|
||||
* Used to register an image decoder observer. Typically, this will
|
||||
|
||||
+2
-32
@@ -107,7 +107,6 @@
|
||||
#include "GeometryUtils.h"
|
||||
#include "nsIAnimationObserver.h"
|
||||
#include "nsChildContentList.h"
|
||||
#include "mozilla/dom/NodeBinding.h"
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "mozilla/dom/AccessibleNode.h"
|
||||
@@ -251,30 +250,6 @@ 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
|
||||
{
|
||||
@@ -1268,7 +1243,7 @@ nsINode::RemoveEventListener(const nsAString& aType,
|
||||
NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsINode)
|
||||
|
||||
nsresult
|
||||
nsINode::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
nsINode::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
// This is only here so that we can use the NS_DECL_NSIDOMTARGET macro
|
||||
NS_ABORT();
|
||||
@@ -1540,6 +1515,7 @@ nsINode::SetExplicitBaseURI(nsIURI* aURI)
|
||||
{
|
||||
nsresult rv = SetProperty(nsGkAtoms::baseURIProperty, aURI, ReleaseURI);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
SetHasExplicitBaseURI();
|
||||
NS_ADDREF(aURI);
|
||||
}
|
||||
return rv;
|
||||
@@ -3157,9 +3133,3 @@ nsINode::IsStyledByServo() const
|
||||
return OwnerDoc()->IsStyledByServo();
|
||||
}
|
||||
#endif
|
||||
|
||||
DocGroup*
|
||||
nsINode::GetDocGroup() const
|
||||
{
|
||||
return OwnerDoc()->GetDocGroup();
|
||||
}
|
||||
+36
-72
@@ -72,7 +72,6 @@ inline bool IsSpaceCharacter(char aChar) {
|
||||
class AccessibleNode;
|
||||
struct BoxQuadOptions;
|
||||
struct ConvertCoordinateOptions;
|
||||
class DocGroup;
|
||||
class DOMPoint;
|
||||
class DOMQuad;
|
||||
class DOMRectReadOnly;
|
||||
@@ -84,7 +83,6 @@ template<typename> class Sequence;
|
||||
class Text;
|
||||
class TextOrElementOrDocument;
|
||||
struct DOMPointInit;
|
||||
struct GetRootNodeOptions;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -128,28 +126,9 @@ enum {
|
||||
|
||||
NODE_IS_EDITABLE = NODE_FLAG_BIT(7),
|
||||
|
||||
// This node was created by layout as native anonymous content. This
|
||||
// generally corresponds to things created by nsIAnonymousContentCreator,
|
||||
// though there are exceptions (svg:use content does not have this flag
|
||||
// set, and any non-nsIAnonymousContentCreator callers of
|
||||
// SetIsNativeAnonymousRoot also get this flag).
|
||||
//
|
||||
// One very important aspect here is that this node is not transitive over
|
||||
// the subtree (if you want that, use NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE).
|
||||
// If Gecko code somewhere attaches children to a node with this bit set,
|
||||
// the children will not have the bit themselves unless the calling code sets
|
||||
// it explicitly. This means that XBL content bound to NAC doesn't get this
|
||||
// bit, nor do nodes inserted by editor.
|
||||
//
|
||||
// For now, this bit exists primarily to control style inheritance behavior,
|
||||
// since the nodes for which we set it are often used to implement pseudo-
|
||||
// elements, which need to inherit style from a script-visible element.
|
||||
//
|
||||
// A more general principle for this bit might be this: If the node is entirely
|
||||
// a detail of layout, is not script-observable in any way, and other engines
|
||||
// might accomplish the same task with a nodeless layout frame, then the node
|
||||
// should have this bit set.
|
||||
NODE_IS_NATIVE_ANONYMOUS = NODE_FLAG_BIT(8),
|
||||
// For all Element nodes, NODE_MAY_HAVE_CLASS is guaranteed to be set if the
|
||||
// node in fact has a class, but may be set even if it doesn't.
|
||||
NODE_MAY_HAVE_CLASS = NODE_FLAG_BIT(8),
|
||||
|
||||
// Whether the node participates in a shadow tree.
|
||||
NODE_IS_IN_SHADOW_TREE = NODE_FLAG_BIT(9),
|
||||
@@ -301,7 +280,6 @@ class nsINode : public mozilla::dom::EventTarget
|
||||
public:
|
||||
typedef mozilla::dom::BoxQuadOptions BoxQuadOptions;
|
||||
typedef mozilla::dom::ConvertCoordinateOptions ConvertCoordinateOptions;
|
||||
typedef mozilla::dom::DocGroup DocGroup;
|
||||
typedef mozilla::dom::DOMPoint DOMPoint;
|
||||
typedef mozilla::dom::DOMPointInit DOMPointInit;
|
||||
typedef mozilla::dom::DOMQuad DOMQuad;
|
||||
@@ -411,12 +389,6 @@ public:
|
||||
*/
|
||||
virtual bool IsNodeOfType(uint32_t aFlags) const = 0;
|
||||
|
||||
bool
|
||||
IsSlotable() const
|
||||
{
|
||||
return IsElement() || IsNodeOfType(eTEXT);
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
/**
|
||||
@@ -616,11 +588,6 @@ public:
|
||||
return mNodeInfo->NamespaceID() == aNamespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DocGroup of the "node document" of this node.
|
||||
*/
|
||||
DocGroup* GetDocGroup() const;
|
||||
|
||||
/**
|
||||
* Print a debugger friendly descriptor of this element. This will describe
|
||||
* the position of this element in the document.
|
||||
@@ -953,14 +920,6 @@ public:
|
||||
*/
|
||||
inline nsINode* GetFlattenedTreeParentNode() const;
|
||||
|
||||
/**
|
||||
* Like GetFlattenedTreeParentNode, but returns null for any native
|
||||
* anonymous content that was generated for ancestor frames of the
|
||||
* root element's primary frame, such as scrollbar elements created
|
||||
* by the root scroll frame.
|
||||
*/
|
||||
inline nsINode* GetFlattenedTreeParentNodeForStyle() const;
|
||||
|
||||
/**
|
||||
* Get the parent nsINode for this node if it is an Element.
|
||||
* @return the parent node
|
||||
@@ -983,11 +942,10 @@ public:
|
||||
*/
|
||||
nsINode* SubtreeRoot() const;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
nsINode* RootNode() const
|
||||
{
|
||||
return SubtreeRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* See nsIDOMEventTarget
|
||||
@@ -1245,15 +1203,6 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if |this| is native anonymous (i.e. created by
|
||||
* nsIAnonymousContentCreator);
|
||||
*/
|
||||
bool IsNativeAnonymous() const
|
||||
{
|
||||
return HasFlag(NODE_IS_NATIVE_ANONYMOUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if |this| or any of its ancestors is native anonymous.
|
||||
*/
|
||||
@@ -1386,11 +1335,10 @@ public:
|
||||
|
||||
protected:
|
||||
nsIURI* GetExplicitBaseURI() const {
|
||||
if (!HasProperties()) {
|
||||
return nullptr;
|
||||
if (HasExplicitBaseURI()) {
|
||||
return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
|
||||
}
|
||||
|
||||
return static_cast<nsIURI*>(GetProperty(nsGkAtoms::baseURIProperty));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1593,8 +1541,6 @@ private:
|
||||
// cases lie for nsXMLElement, such as when the node has been moved between
|
||||
// documents with different id mappings.
|
||||
ElementHasID,
|
||||
// Set if the element might have a class.
|
||||
ElementMayHaveClass,
|
||||
// Set if the element might have inline style.
|
||||
ElementMayHaveStyle,
|
||||
// Set if the element has a name attribute set.
|
||||
@@ -1613,6 +1559,8 @@ private:
|
||||
// Maybe set if the node is a root of a subtree
|
||||
// which needs to be kept in the purple buffer.
|
||||
NodeIsPurpleRoot,
|
||||
// Set if the node has an explicit base URI stored
|
||||
NodeHasExplicitBaseURI,
|
||||
// Set if the element has some style states locked
|
||||
ElementHasLockedStyleStates,
|
||||
// Set if element has pointer locked
|
||||
@@ -1623,11 +1571,10 @@ private:
|
||||
NodeIsContent,
|
||||
// Set if the node has animations or transitions
|
||||
ElementHasAnimations,
|
||||
// Set if node has a dir attribute with a valid value (ltr, rtl, or auto).
|
||||
// Note that we cannot compute this from the dir attribute event state
|
||||
// flags, because we can't use those to distinguish
|
||||
// <bdi dir="some-invalid-value"> and <bdi dir="auto">.
|
||||
// Set if node has a dir attribute with a valid value (ltr, rtl, or auto)
|
||||
NodeHasValidDirAttribute,
|
||||
// Set if node has a dir attribute with a fixed value (ltr or rtl, NOT auto)
|
||||
NodeHasFixedDir,
|
||||
// Set if the node has dir=auto and has a property pointing to the text
|
||||
// node that determines its direction
|
||||
NodeHasDirAutoSet,
|
||||
@@ -1635,6 +1582,8 @@ private:
|
||||
// and has a TextNodeDirectionalityMap property listing the elements whose
|
||||
// direction it determines.
|
||||
NodeHasTextNodeDirectionalityMap,
|
||||
// Set if the node has dir=auto.
|
||||
NodeHasDirAuto,
|
||||
// Set if a node in the node's parent chain has dir=auto.
|
||||
NodeAncestorHasDirAuto,
|
||||
// Set if the element is in the scope of a scoped style sheet; this flag is
|
||||
@@ -1688,8 +1637,6 @@ public:
|
||||
{ SetBoolFlag(NodeHasRenderingObservers, aValue); }
|
||||
bool IsContent() const { return GetBoolFlag(NodeIsContent); }
|
||||
bool HasID() const { return GetBoolFlag(ElementHasID); }
|
||||
bool MayHaveClass() const { return GetBoolFlag(ElementMayHaveClass); }
|
||||
void SetMayHaveClass() { SetBoolFlag(ElementMayHaveClass); }
|
||||
bool MayHaveStyle() const { return GetBoolFlag(ElementMayHaveStyle); }
|
||||
bool HasName() const { return GetBoolFlag(ElementHasName); }
|
||||
bool MayHaveContentEditableAttr() const
|
||||
@@ -1729,6 +1676,17 @@ public:
|
||||
void SetHasValidDir() { SetBoolFlag(NodeHasValidDirAttribute); }
|
||||
void ClearHasValidDir() { ClearBoolFlag(NodeHasValidDirAttribute); }
|
||||
bool HasValidDir() const { return GetBoolFlag(NodeHasValidDirAttribute); }
|
||||
void SetHasFixedDir() {
|
||||
MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
|
||||
"SetHasFixedDir on text node");
|
||||
SetBoolFlag(NodeHasFixedDir);
|
||||
}
|
||||
void ClearHasFixedDir() {
|
||||
MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
|
||||
"ClearHasFixedDir on text node");
|
||||
ClearBoolFlag(NodeHasFixedDir);
|
||||
}
|
||||
bool HasFixedDir() const { return GetBoolFlag(NodeHasFixedDir); }
|
||||
void SetHasDirAutoSet() {
|
||||
MOZ_ASSERT(NodeType() != nsIDOMNode::TEXT_NODE,
|
||||
"SetHasDirAutoSet on text node");
|
||||
@@ -1757,12 +1715,16 @@ public:
|
||||
return GetBoolFlag(NodeHasTextNodeDirectionalityMap);
|
||||
}
|
||||
|
||||
void SetHasDirAuto() { SetBoolFlag(NodeHasDirAuto); }
|
||||
void ClearHasDirAuto() { ClearBoolFlag(NodeHasDirAuto); }
|
||||
bool HasDirAuto() const { return GetBoolFlag(NodeHasDirAuto); }
|
||||
|
||||
void SetAncestorHasDirAuto() { SetBoolFlag(NodeAncestorHasDirAuto); }
|
||||
void ClearAncestorHasDirAuto() { ClearBoolFlag(NodeAncestorHasDirAuto); }
|
||||
bool AncestorHasDirAuto() const { return GetBoolFlag(NodeAncestorHasDirAuto); }
|
||||
|
||||
// Implemented in nsIContentInlines.h.
|
||||
inline bool NodeOrAncestorHasDirAuto() const;
|
||||
bool NodeOrAncestorHasDirAuto() const
|
||||
{ return HasDirAuto() || AncestorHasDirAuto(); }
|
||||
|
||||
void SetIsElementInStyleScope(bool aValue) {
|
||||
MOZ_ASSERT(IsElement(), "SetIsInStyleScope on a non-Element node");
|
||||
@@ -1804,6 +1766,8 @@ protected:
|
||||
void ClearHasName() { ClearBoolFlag(ElementHasName); }
|
||||
void SetMayHaveContentEditableAttr()
|
||||
{ SetBoolFlag(ElementMayHaveContentEditableAttr); }
|
||||
bool HasExplicitBaseURI() const { return GetBoolFlag(NodeHasExplicitBaseURI); }
|
||||
void SetHasExplicitBaseURI() { SetBoolFlag(NodeHasExplicitBaseURI); }
|
||||
void SetHasLockedStyleStates() { SetBoolFlag(ElementHasLockedStyleStates); }
|
||||
void ClearHasLockedStyleStates() { ClearBoolFlag(ElementHasLockedStyleStates); }
|
||||
bool HasLockedStyleStates() const
|
||||
|
||||
@@ -1,236 +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/. */
|
||||
|
||||
/*
|
||||
* Base class for all our document implementations.
|
||||
*/
|
||||
|
||||
#ifndef nsIdentifierMapEntry_h
|
||||
#define nsIdentifierMapEntry_h
|
||||
|
||||
#include "PLDHashTable.h"
|
||||
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/net/ReferrerPolicy.h"
|
||||
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIAtom.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsContentList;
|
||||
class nsBaseContentList;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Right now our identifier map entries contain information for 'name'
|
||||
* and 'id' mappings of a given string. This is so that
|
||||
* nsHTMLDocument::ResolveName only has to do one hash lookup instead
|
||||
* of two. It's not clear whether this still matters for performance.
|
||||
*
|
||||
* We also store the document.all result list here. This is mainly so that
|
||||
* when all elements with the given ID are removed and we remove
|
||||
* the ID's nsIdentifierMapEntry, the document.all result is released too.
|
||||
* Perhaps the document.all results should have their own hashtable
|
||||
* in nsHTMLDocument.
|
||||
*/
|
||||
class nsIdentifierMapEntry : public PLDHashEntryHdr
|
||||
{
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::net::ReferrerPolicy ReferrerPolicy;
|
||||
|
||||
/**
|
||||
* @see nsIDocument::IDTargetObserver, this is just here to avoid include
|
||||
* hell.
|
||||
*/
|
||||
typedef bool (* IDTargetObserver)(Element* aOldElement,
|
||||
Element* aNewelement, void* aData);
|
||||
|
||||
public:
|
||||
struct AtomOrString
|
||||
{
|
||||
MOZ_IMPLICIT AtomOrString(nsIAtom* aAtom) : mAtom(aAtom) {}
|
||||
MOZ_IMPLICIT AtomOrString(const nsAString& aString) : mString(aString) {}
|
||||
AtomOrString(const AtomOrString& aOther)
|
||||
: mAtom(aOther.mAtom)
|
||||
, mString(aOther.mString)
|
||||
{
|
||||
}
|
||||
|
||||
AtomOrString(AtomOrString&& aOther)
|
||||
: mAtom(aOther.mAtom.forget())
|
||||
, mString(aOther.mString)
|
||||
{
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAtom> mAtom;
|
||||
const nsString mString;
|
||||
};
|
||||
|
||||
typedef const AtomOrString& KeyType;
|
||||
typedef const AtomOrString* KeyTypePointer;
|
||||
|
||||
explicit nsIdentifierMapEntry(const AtomOrString& aKey);
|
||||
explicit nsIdentifierMapEntry(const AtomOrString* aKey);
|
||||
nsIdentifierMapEntry(nsIdentifierMapEntry&& aOther);
|
||||
~nsIdentifierMapEntry();
|
||||
|
||||
KeyType GetKey() const { return mKey; }
|
||||
|
||||
nsString GetKeyAsString() const
|
||||
{
|
||||
if (mKey.mAtom) {
|
||||
return nsAtomString(mKey.mAtom);
|
||||
}
|
||||
|
||||
return mKey.mString;
|
||||
}
|
||||
|
||||
bool KeyEquals(const KeyTypePointer aOtherKey) const
|
||||
{
|
||||
if (mKey.mAtom) {
|
||||
if (aOtherKey->mAtom) {
|
||||
return mKey.mAtom == aOtherKey->mAtom;
|
||||
}
|
||||
|
||||
return mKey.mAtom->Equals(aOtherKey->mString);
|
||||
}
|
||||
|
||||
if (aOtherKey->mAtom) {
|
||||
return aOtherKey->mAtom->Equals(mKey.mString);
|
||||
}
|
||||
|
||||
return mKey.mString.Equals(aOtherKey->mString);
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
|
||||
|
||||
static PLDHashNumber HashKey(const KeyTypePointer aKey)
|
||||
{
|
||||
return aKey->mAtom ?
|
||||
aKey->mAtom->hash() : mozilla::HashString(aKey->mString);
|
||||
}
|
||||
|
||||
enum { ALLOW_MEMMOVE = false };
|
||||
|
||||
void AddNameElement(nsINode* aDocument, Element* aElement);
|
||||
void RemoveNameElement(Element* aElement);
|
||||
bool IsEmpty();
|
||||
nsBaseContentList* GetNameContentList() {
|
||||
return mNameContentList;
|
||||
}
|
||||
bool HasNameElement() const;
|
||||
|
||||
/**
|
||||
* Returns the element if we know the element associated with this
|
||||
* id. Otherwise returns null.
|
||||
*/
|
||||
Element* GetIdElement();
|
||||
/**
|
||||
* Returns the list of all elements associated with this id.
|
||||
*/
|
||||
const nsTArray<Element*>& GetIdElements() const {
|
||||
return mIdContentList;
|
||||
}
|
||||
/**
|
||||
* If this entry has a non-null image element set (using SetImageElement),
|
||||
* the image element will be returned, otherwise the same as GetIdElement().
|
||||
*/
|
||||
Element* GetImageIdElement();
|
||||
/**
|
||||
* Append all the elements with this id to aElements
|
||||
*/
|
||||
void AppendAllIdContent(nsCOMArray<nsIContent>* aElements);
|
||||
/**
|
||||
* This can fire ID change callbacks.
|
||||
* @return true if the content could be added, false if we failed due
|
||||
* to OOM.
|
||||
*/
|
||||
bool AddIdElement(Element* aElement);
|
||||
/**
|
||||
* This can fire ID change callbacks.
|
||||
*/
|
||||
void RemoveIdElement(Element* aElement);
|
||||
/**
|
||||
* Set the image element override for this ID. This will be returned by
|
||||
* GetIdElement(true) if non-null.
|
||||
*/
|
||||
void SetImageElement(Element* aElement);
|
||||
bool HasIdElementExposedAsHTMLDocumentProperty();
|
||||
|
||||
bool HasContentChangeCallback() { return mChangeCallbacks != nullptr; }
|
||||
void AddContentChangeCallback(IDTargetObserver aCallback,
|
||||
void* aData, bool aForImage);
|
||||
void RemoveContentChangeCallback(IDTargetObserver aCallback,
|
||||
void* aData, bool aForImage);
|
||||
|
||||
/**
|
||||
* Remove all elements and notify change listeners.
|
||||
*/
|
||||
void ClearAndNotify();
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback* aCallback);
|
||||
|
||||
struct ChangeCallback {
|
||||
IDTargetObserver mCallback;
|
||||
void* mData;
|
||||
bool mForImage;
|
||||
};
|
||||
|
||||
struct ChangeCallbackEntry : public PLDHashEntryHdr {
|
||||
typedef const ChangeCallback KeyType;
|
||||
typedef const ChangeCallback* KeyTypePointer;
|
||||
|
||||
explicit ChangeCallbackEntry(const ChangeCallback* aKey) :
|
||||
mKey(*aKey) { }
|
||||
ChangeCallbackEntry(const ChangeCallbackEntry& toCopy) :
|
||||
mKey(toCopy.mKey) { }
|
||||
|
||||
KeyType GetKey() const { return mKey; }
|
||||
bool KeyEquals(KeyTypePointer aKey) const {
|
||||
return aKey->mCallback == mKey.mCallback &&
|
||||
aKey->mData == mKey.mData &&
|
||||
aKey->mForImage == mKey.mForImage;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType& aKey) { return &aKey; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
||||
{
|
||||
return mozilla::HashGeneric(aKey->mCallback, aKey->mData);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
ChangeCallback mKey;
|
||||
};
|
||||
|
||||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
|
||||
private:
|
||||
nsIdentifierMapEntry(const nsIdentifierMapEntry& aOther) = delete;
|
||||
nsIdentifierMapEntry& operator=(const nsIdentifierMapEntry& aOther) = delete;
|
||||
|
||||
void FireChangeCallbacks(Element* aOldElement, Element* aNewElement,
|
||||
bool aImageOnly = false);
|
||||
|
||||
AtomOrString mKey;
|
||||
// empty if there are no elements with this ID.
|
||||
// The elements are stored as weak pointers.
|
||||
AutoTArray<Element*, 1> mIdContentList;
|
||||
RefPtr<nsBaseContentList> mNameContentList;
|
||||
nsAutoPtr<nsTHashtable<ChangeCallbackEntry> > mChangeCallbacks;
|
||||
RefPtr<Element> mImageElement;
|
||||
};
|
||||
|
||||
#endif // #ifndef nsIdentifierMapEntry_h
|
||||
@@ -97,7 +97,7 @@ nsInProcessTabChildGlobal::nsInProcessTabChildGlobal(nsIDocShell* aShell,
|
||||
mozilla::HoldJSObjects(this);
|
||||
|
||||
// If owner corresponds to an <iframe mozbrowser> or <iframe mozapp>, we'll
|
||||
// GetEventTargetParent implementation.
|
||||
// have to tweak our PreHandleEvent implementation.
|
||||
nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwner);
|
||||
if (browserFrame) {
|
||||
mIsBrowserOrAppFrame = browserFrame->GetReallyIsBrowserOrApp();
|
||||
@@ -251,7 +251,7 @@ nsInProcessTabChildGlobal::GetOwnerContent()
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
nsInProcessTabChildGlobal::PreHandleEvent(EventChainPreVisitor& aVisitor)
|
||||
{
|
||||
aVisitor.mForceContentDispatch = true;
|
||||
aVisitor.mCanHandle = true;
|
||||
@@ -270,7 +270,7 @@ nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
#endif
|
||||
|
||||
if (mPreventEventsEscaping) {
|
||||
aVisitor.SetParentTarget(nullptr, false);
|
||||
aVisitor.mParentTarget = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -278,13 +278,11 @@ nsInProcessTabChildGlobal::GetEventTargetParent(EventChainPreVisitor& aVisitor)
|
||||
(!mOwner || !nsContentUtils::IsInChromeDocshell(mOwner->OwnerDoc()))) {
|
||||
if (mOwner) {
|
||||
if (nsPIDOMWindowInner* innerWindow = mOwner->OwnerDoc()->GetInnerWindow()) {
|
||||
// 'this' is already a "chrome handler", so we consider window's
|
||||
// parent target to be part of that same part of the event path.
|
||||
aVisitor.SetParentTarget(innerWindow->GetParentTarget(), false);
|
||||
aVisitor.mParentTarget = innerWindow->GetParentTarget();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
aVisitor.SetParentTarget(mOwner, false);
|
||||
aVisitor.mParentTarget = mOwner;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
JS::Handle<JSObject *> aCpows,
|
||||
nsIPrincipal* aPrincipal) override;
|
||||
|
||||
virtual nsresult GetEventTargetParent(
|
||||
virtual nsresult PreHandleEvent(
|
||||
mozilla::EventChainPreVisitor& aVisitor) override;
|
||||
NS_IMETHOD AddEventListener(const nsAString& aType,
|
||||
nsIDOMEventListener* aListener,
|
||||
@@ -168,7 +168,7 @@ protected:
|
||||
|
||||
// Is this the message manager for an in-process <iframe mozbrowser> or
|
||||
// <iframe mozapp>? This affects where events get sent, so it affects
|
||||
// GetEventTargetParent.
|
||||
// PreHandleEvent.
|
||||
bool mIsBrowserOrAppFrame;
|
||||
bool mPreventEventsEscaping;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#include "xpcpublic.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsGlobalWindow.h"
|
||||
#include "mozilla/CycleCollectedJSContext.h"
|
||||
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/Date.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
@@ -160,8 +160,7 @@ nsJSUtils::EvaluateString(JSContext* aCx,
|
||||
aEvaluationGlobal);
|
||||
MOZ_ASSERT_IF(aOffThreadToken, aCompileOptions.noScriptRval);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(CycleCollectedJSContext::Get() &&
|
||||
CycleCollectedJSContext::Get()->MicroTaskLevel());
|
||||
MOZ_ASSERT(nsContentUtils::IsInMicroTask());
|
||||
|
||||
// Unfortunately, the JS engine actually compiles scripts with a return value
|
||||
// in a different, less efficient way. Furthermore, it can't JIT them in many
|
||||
@@ -295,8 +294,7 @@ nsJSUtils::CompileModule(JSContext* aCx,
|
||||
aEvaluationGlobal);
|
||||
MOZ_ASSERT(JS::CurrentGlobalOrNull(aCx) == aEvaluationGlobal);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(CycleCollectedJSContext::Get() &&
|
||||
CycleCollectedJSContext::Get()->MicroTaskLevel());
|
||||
MOZ_ASSERT(nsContentUtils::IsInMicroTask());
|
||||
|
||||
NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
|
||||
|
||||
@@ -333,8 +331,7 @@ nsJSUtils::ModuleEvaluation(JSContext* aCx, JS::Handle<JSObject*> aModule)
|
||||
|
||||
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(CycleCollectedJSContext::Get() &&
|
||||
CycleCollectedJSContext::Get()->MicroTaskLevel());
|
||||
MOZ_ASSERT(nsContentUtils::IsInMicroTask());
|
||||
|
||||
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
|
||||
|
||||
|
||||
@@ -15,19 +15,17 @@ nsMappedAttributeElement::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
|
||||
}
|
||||
|
||||
bool
|
||||
nsMappedAttributeElement::SetAndSwapMappedAttribute(nsIDocument* aDocument,
|
||||
nsIAtom* aName,
|
||||
nsAttrValue& aValue,
|
||||
bool* aValueWasSet,
|
||||
nsresult* aRetval)
|
||||
|
||||
nsMappedAttributeElement::SetMappedAttribute(nsIDocument* aDocument,
|
||||
nsIAtom* aName,
|
||||
nsAttrValue& aValue,
|
||||
nsresult* aRetval)
|
||||
{
|
||||
NS_PRECONDITION(aDocument == GetComposedDoc(), "Unexpected document");
|
||||
nsHTMLStyleSheet* sheet = aDocument ?
|
||||
aDocument->GetAttributeStyleSheet() : nullptr;
|
||||
|
||||
*aRetval = mAttrsAndChildren.SetAndSwapMappedAttr(aName, aValue,
|
||||
this, sheet, aValueWasSet);
|
||||
*aRetval = mAttrsAndChildren.SetAndTakeMappedAttr(aName, aValue,
|
||||
this, sheet);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,10 @@ public:
|
||||
nsRuleData* aRuleData);
|
||||
|
||||
NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
|
||||
virtual bool SetAndSwapMappedAttribute(nsIDocument* aDocument,
|
||||
nsIAtom* aName,
|
||||
nsAttrValue& aValue,
|
||||
bool* aValueWasSet,
|
||||
nsresult* aRetval) override;
|
||||
virtual bool SetMappedAttribute(nsIDocument* aDocument,
|
||||
nsIAtom* aName,
|
||||
nsAttrValue& aValue,
|
||||
nsresult* aRetval) override;
|
||||
};
|
||||
|
||||
#endif // NS_MAPPEDATTRIBUTEELEMENT_H_
|
||||
@@ -62,17 +62,11 @@ nsMappedAttributes::Clone(bool aWillAddAttr)
|
||||
|
||||
void* nsMappedAttributes::operator new(size_t aSize, uint32_t aAttrCount) CPP_THROW_NEW
|
||||
{
|
||||
size_t size = aSize + aAttrCount * sizeof(InternalAttr);
|
||||
NS_ASSERTION(aAttrCount > 0, "zero-attribute nsMappedAttributes requested");
|
||||
|
||||
// aSize will include the mAttrs buffer so subtract that.
|
||||
// We don't want to under-allocate, however, so do not subtract
|
||||
// if we have zero attributes. The zero attribute case only happens
|
||||
// for <body>'s mapped attributes
|
||||
if (aAttrCount != 0) {
|
||||
size -= sizeof(void*[1]);
|
||||
}
|
||||
|
||||
void* newAttrs = ::operator new(size);
|
||||
void* newAttrs = ::operator new(aSize - sizeof(void*[1]) +
|
||||
aAttrCount * sizeof(InternalAttr));
|
||||
|
||||
#ifdef DEBUG
|
||||
static_cast<nsMappedAttributes*>(newAttrs)->mBufferSize = aAttrCount;
|
||||
@@ -85,16 +79,15 @@ NS_IMPL_ISUPPORTS(nsMappedAttributes,
|
||||
nsIStyleRule)
|
||||
|
||||
void
|
||||
nsMappedAttributes::SetAndSwapAttr(nsIAtom* aAttrName, nsAttrValue& aValue,
|
||||
bool* aValueWasSet)
|
||||
nsMappedAttributes::SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue)
|
||||
{
|
||||
NS_PRECONDITION(aAttrName, "null name");
|
||||
*aValueWasSet = false;
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < mAttrCount && !Attrs()[i].mName.IsSmaller(aAttrName); ++i) {
|
||||
if (Attrs()[i].mName.Equals(aAttrName)) {
|
||||
Attrs()[i].mValue.Reset();
|
||||
Attrs()[i].mValue.SwapValueWith(aValue);
|
||||
*aValueWasSet = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@ public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
void SetAndSwapAttr(nsIAtom* aAttrName, nsAttrValue& aValue,
|
||||
bool* aValueWasSet);
|
||||
void SetAndTakeAttr(nsIAtom* aAttrName, nsAttrValue& aValue);
|
||||
const nsAttrValue* GetAttr(nsIAtom* aAttrName) const;
|
||||
const nsAttrValue* GetAttr(const nsAString& aAttrName) const;
|
||||
|
||||
|
||||
Loaded 100 of 1842 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user