Compare commits
143
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1db27e199 | ||
|
|
a5203631d8 | ||
|
|
e2fe23c90b | ||
|
|
fcc0241430 | ||
|
|
24657db629 | ||
|
|
4939447eb7 | ||
|
|
f07d60c09f | ||
|
|
d7a05ea9e5 | ||
|
|
10bf4a6d5b | ||
|
|
c3778db14d | ||
|
|
abcee4f85c | ||
|
|
67a7e4eabd | ||
|
|
c1ef954679 | ||
|
|
eac19e3356 | ||
|
|
a98d06380f | ||
|
|
1e8d07cac2 | ||
|
|
e7a0013f81 | ||
|
|
17b4d049f4 | ||
|
|
abf1d5a099 | ||
|
|
b7dac18c0e | ||
|
|
63a0006985 | ||
|
|
e50094ab02 | ||
|
|
d11196927a | ||
|
|
af6a8637f5 | ||
|
|
5a9f8ae723 | ||
|
|
9f5c27ba47 | ||
|
|
f624bd1375 | ||
|
|
312f0b3a76 | ||
|
|
04479387a2 | ||
|
|
b0c271c7f9 | ||
|
|
37efb98518 | ||
|
|
3272147d97 | ||
|
|
f2866a5420 | ||
|
|
b862145e9c | ||
|
|
e2e483ac47 | ||
|
|
892a2d9655 | ||
|
|
075fa01286 | ||
|
|
32e0d2ca23 | ||
|
|
791d5f8a43 | ||
|
|
ed1f54ab73 | ||
|
|
eb1315e093 | ||
|
|
fa9730a46c | ||
|
|
ba0518147f | ||
|
|
7564818c79 | ||
|
|
10866dd35c | ||
|
|
f43c37cabe | ||
|
|
157f218c8d | ||
|
|
d49fb8a691 | ||
|
|
71b988d1b4 | ||
|
|
ddc43bf9d7 | ||
|
|
5819a1a525 | ||
|
|
351974555b | ||
|
|
abaea77ccb | ||
|
|
4698b4b3ca | ||
|
|
798f0bd3ad | ||
|
|
427d325d0c | ||
|
|
9c515323ff | ||
|
|
c2b91aaf8c | ||
|
|
1da42403ec | ||
|
|
602fbdcb44 | ||
|
|
42f895f27f | ||
|
|
a6f632714f | ||
|
|
b28effe2ea | ||
|
|
afd6edd667 | ||
|
|
582a1ce72a | ||
|
|
71ac56ba40 | ||
|
|
ae184d09e6 | ||
|
|
868f0755ae | ||
|
|
5ca8fbd41c | ||
|
|
549c8b9283 | ||
|
|
77e8ba7eaf | ||
|
|
e854d58633 | ||
|
|
d58cb8e11b | ||
|
|
429a7bdb93 | ||
|
|
3f14e9ec5f | ||
|
|
aefb293793 | ||
|
|
c583315558 | ||
|
|
834ecdc59a | ||
|
|
798c2ed4f8 | ||
|
|
767b637c83 | ||
|
|
702ad218b0 | ||
|
|
b9af9c0c51 | ||
|
|
9d6e28d3d0 | ||
|
|
c735355ae1 | ||
|
|
10a10fd375 | ||
|
|
1012dbe9e5 | ||
|
|
9982c1f5cb | ||
|
|
fe912e94e4 | ||
|
|
770b1c9071 | ||
|
|
daf56131a7 | ||
|
|
d8686de401 | ||
|
|
c8a38346c8 | ||
|
|
70bafe4df5 | ||
|
|
498b1ab0c8 | ||
|
|
2f145b6eda | ||
|
|
06a092d08e | ||
|
|
d107016d37 | ||
|
|
63371593c0 | ||
|
|
ce1dc7e6c6 | ||
|
|
a4780ebaeb | ||
|
|
c384fa6e25 | ||
|
|
5e8e0d05a6 | ||
|
|
bf95a03189 | ||
|
|
c75e412f17 | ||
|
|
0bbe6ec105 | ||
|
|
48d31ea5eb | ||
|
|
3cf0843679 | ||
|
|
ff21776616 | ||
|
|
2f022ab1fa | ||
|
|
14e7f881be | ||
|
|
4f03fb2798 | ||
|
|
3dd316f739 | ||
|
|
972ab6d437 | ||
|
|
83ae5bd019 | ||
|
|
c237a54f23 | ||
|
|
8f72a673ca | ||
|
|
3266e0976f | ||
|
|
4433519ae8 | ||
|
|
d419fe2d52 | ||
|
|
c77c6de9ce | ||
|
|
2ed0607c74 | ||
|
|
922a72766c | ||
|
|
16d1313104 | ||
|
|
0387f52bd3 | ||
|
|
a1ca8ca9bd | ||
|
|
2ee2ca7dfb | ||
|
|
0d7b7b74c6 | ||
|
|
45db2388fe | ||
|
|
323288bc72 | ||
|
|
3323a8eda3 | ||
|
|
71293f0fe4 | ||
|
|
a91722be27 | ||
|
|
1ef64f9ea3 | ||
|
|
4a960879c8 | ||
|
|
4329ae3337 | ||
|
|
ad453f0b28 | ||
|
|
d332d4a60d | ||
|
|
ad5e9449d2 | ||
|
|
71848c23a4 | ||
|
|
1d321e689e | ||
|
|
b9b9d5bfb9 | ||
|
|
b92abc83c2 | ||
|
|
4950c982e0 |
No files matched your search
@@ -22,5 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Clobber for NSS update
|
||||
|
||||
Clobber for CSS flow-root implementation
|
||||
@@ -36,4 +36,4 @@ improvement patches upstream to its origin to mutually improve the platform and
|
||||
a future for XUL.
|
||||
|
||||
## Looking for Pale Moon and Basilisk?
|
||||
As of [`Issue #969`](https://github.com/MoonchildProductions/UXP/issues/969), release versions `28.9.0` and `2020.03.04` respectively, they have been split off into their own dedicated repositories located at [`MoonchildProductions/Pale-Moon`](https://github.com/MoonchildProductions/Pale-Moon) and [`MoonchildProductions/Basilisk`](https://github.com/MoonchildProductions/Basilisk).
|
||||
As of [`Issue #969`](https://repo.palemoon.org/MoonchildProductions/UXP/issues/969), release versions `28.9.0` and `2020.03.04` respectively, they have been split off into their own dedicated repositories located at [`MoonchildProductions/Pale-Moon`](https://repo.palemoon.org/MoonchildProductions/Pale-Moon) and [`MoonchildProductions/Basilisk`](https://repo.palemoon.org/MoonchildProductions/Basilisk).
|
||||
+1
-1
@@ -23,7 +23,7 @@ Generally not security vulnerabilities:
|
||||
## Reporting a Vulnerability
|
||||
|
||||
If you find an issue in UXP or the applications it builds on that could impact the security or safety of users please **do not**
|
||||
make an issue on GitHub about it. GitHub does not support restricted viewability for security sensitive bugs.
|
||||
make an issue on Gitea about it. Gitea does not support restricted viewability for security sensitive bugs.
|
||||
|
||||
If you want to report a security-sensitive issue then please go to the [forum](https://forum.palemoon.org) and report the issue
|
||||
via a **private message** to **Moonchild** (the founder and prime responsible for security issues).
|
||||
|
||||
@@ -347,16 +347,6 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
|
||||
eLandmark,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // marquee
|
||||
&nsGkAtoms::marquee,
|
||||
roles::ANIMATION,
|
||||
kUseMapRole,
|
||||
eNoValue,
|
||||
eNoAction,
|
||||
eOffLiveAttr,
|
||||
kGenericAccType,
|
||||
kNoReqStates
|
||||
},
|
||||
{ // math
|
||||
&nsGkAtoms::math,
|
||||
roles::FLAT_EQUATION,
|
||||
|
||||
@@ -732,8 +732,6 @@ using namespace mozilla::a11y;
|
||||
return @"AXDocument";
|
||||
if (roleAtom == nsGkAtoms::log_)
|
||||
return @"AXApplicationLog";
|
||||
if (roleAtom == nsGkAtoms::marquee)
|
||||
return @"AXApplicationMarquee";
|
||||
if (roleAtom == nsGkAtoms::math)
|
||||
return @"AXDocumentMath";
|
||||
if (roleAtom == nsGkAtoms::note_)
|
||||
@@ -869,7 +867,6 @@ static const RoleDescrMap sRoleDescrMap[] = {
|
||||
{ @"AXApplicationAlert", NS_LITERAL_STRING("alert") },
|
||||
{ @"AXApplicationAlertDialog", NS_LITERAL_STRING("alertDialog") },
|
||||
{ @"AXApplicationLog", NS_LITERAL_STRING("log") },
|
||||
{ @"AXApplicationMarquee", NS_LITERAL_STRING("marquee") },
|
||||
{ @"AXApplicationStatus", NS_LITERAL_STRING("status") },
|
||||
{ @"AXApplicationTimer", NS_LITERAL_STRING("timer") },
|
||||
{ @"AXContentSeparator", NS_LITERAL_STRING("separator") },
|
||||
|
||||
@@ -62,7 +62,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
testAbsentAttrs("live3", {"live" : ""});
|
||||
testAttrs("log", {"live" : "polite"}, true);
|
||||
testAttrs("logAssertive", {"live" : "assertive"}, true);
|
||||
testAttrs("marquee", {"live" : "off"}, true);
|
||||
testAttrs("status", {"live" : "polite"}, true);
|
||||
testAttrs("timer", {"live" : "off"}, true);
|
||||
testAbsentAttrs("tablist", {"live" : "polite"});
|
||||
@@ -72,7 +71,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
testAttrs("live2Child", {"container-live" : "polite"}, true);
|
||||
testAttrs("logChild", {"container-live" : "polite"}, true);
|
||||
testAttrs("logAssertiveChild", {"container-live" : "assertive"}, true);
|
||||
testAttrs("marqueeChild", {"container-live" : "off"}, true);
|
||||
testAttrs("statusChild", {"container-live" : "polite"}, true);
|
||||
testAttrs("timerChild", {"container-live" : "off"}, true);
|
||||
testAbsentAttrs("tablistChild", {"container-live" : "polite"});
|
||||
@@ -80,13 +78,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
// container-live-role object attribute
|
||||
testAttrs("log", {"container-live-role" : "log"}, true);
|
||||
testAttrs("logAssertive", {"container-live-role" : "log"}, true);
|
||||
testAttrs("marquee", {"container-live-role" : "marquee"}, true);
|
||||
testAttrs("status", {"container-live-role" : "status"}, true);
|
||||
testAttrs("timer", {"container-live-role" : "timer"}, true);
|
||||
testAttrs("logChild", {"container-live-role" : "log"}, true);
|
||||
testAttrs("logAssertive", {"container-live-role" : "log"}, true);
|
||||
testAttrs("logAssertiveChild", {"container-live-role" : "log"}, true);
|
||||
testAttrs("marqueeChild", {"container-live-role" : "marquee"}, true);
|
||||
testAttrs("statusChild", {"container-live-role" : "status"}, true);
|
||||
testAttrs("timerChild", {"container-live-role" : "timer"}, true);
|
||||
testAbsentAttrs("tablistChild", {"container-live-role" : "tablist"});
|
||||
@@ -230,11 +226,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=558036
|
||||
|
||||
<!-- back to aria -->
|
||||
<div id="live" aria-live="polite">excuse <div id="liveChild">me</div></div>
|
||||
<div id="live2" role="marquee" aria-live="polite">excuse <div id="live2Child">me</div></div>
|
||||
<div id="live3" role="region">excuse</div>
|
||||
<div id="log" role="log">excuse <div id="logChild">me</div></div>
|
||||
<div id="logAssertive" role="log" aria-live="assertive">excuse <div id="logAssertiveChild">me</div></div>
|
||||
<div id="marquee" role="marquee">excuse <div id="marqueeChild">me</div></div>
|
||||
<div id="status" role="status">excuse <div id="statusChild">me</div></div>
|
||||
<div id="tablist" role="tablist">tablist <div id="tablistChild">tab</div></div>
|
||||
<div id="timer" role="timer">excuse <div id="timerChild">me</div></div>
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
testRole("aria_listbox", ROLE_LISTBOX);
|
||||
testRole("aria_listitem", ROLE_LISTITEM);
|
||||
testRole("aria_log", ROLE_TEXT); // weak role
|
||||
testRole("aria_marquee", ROLE_ANIMATION);
|
||||
testRole("aria_math", ROLE_FLAT_EQUATION);
|
||||
testRole("aria_menu", ROLE_MENUPOPUP);
|
||||
testRole("aria_menubar", ROLE_MENUBAR);
|
||||
@@ -89,9 +88,6 @@
|
||||
testRole("log_table", ROLE_TABLE);
|
||||
testRole("timer_div", ROLE_SECTION);
|
||||
|
||||
// other roles that are forms of "live regions"
|
||||
testRole("marquee_h1", ROLE_ANIMATION);
|
||||
|
||||
// strong landmark
|
||||
testRole("application", ROLE_APPLICATION);
|
||||
testRole("form", ROLE_FORM);
|
||||
@@ -219,7 +215,6 @@
|
||||
<span id="aria_listbox" role="listbox"/>
|
||||
<span id="aria_listitem" role="listitem"/>
|
||||
<span id="aria_log" role="log"/>
|
||||
<span id="aria_marquee" role="marquee"/>
|
||||
<span id="aria_math" role="math"/>
|
||||
<span id="aria_menu" role="menu"/>
|
||||
<span id="aria_menubar" role="menubar"/>
|
||||
@@ -263,7 +258,6 @@
|
||||
<table role="log" id="log_table">
|
||||
<tr><td>Table based log</td></tr>
|
||||
</table>
|
||||
<h1 role="marquee" id="marquee_h1">marquee</h1>
|
||||
<div role="timer" id="timer_div">timer</div>
|
||||
|
||||
<!-- landmarks -->
|
||||
|
||||
@@ -310,6 +310,7 @@ def old_configure_options(*options):
|
||||
'--disable-browser-statusbar',
|
||||
'--disable-sync',
|
||||
'--disable-personas',
|
||||
'--enable-phoenix-extensions',
|
||||
|
||||
# Below are configure flags used by Basilisk
|
||||
'--disable-webextensions',
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
4.6.0
|
||||
4.7.0
|
||||
@@ -65,9 +65,13 @@ if CONFIG['MOZ_DEBUG']:
|
||||
|
||||
# Force using malloc_usable_size when building with jemalloc because _msize
|
||||
# causes assertions on Win64. See bug 719579.
|
||||
# This causes a known warning due to the way mozjemalloc is linked and the
|
||||
# malloc_usable_size function not being available at compile time on MSVC
|
||||
# so we suppress that particular warning (C4013)
|
||||
if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_MEMORY']:
|
||||
DEFINES['HAVE_MALLOC_USABLE_SIZE'] = True
|
||||
DEFINES['SQLITE_WITHOUT_MSIZE'] = True
|
||||
CFLAGS += ['-wd4013']
|
||||
|
||||
# Omit unused functions to save some library footprint.
|
||||
DEFINES['SQLITE_OMIT_DEPRECATED'] = True
|
||||
|
||||
+20958
-15503
File diff suppressed because it is too large.
Load diff
+1205
-888
File diff suppressed because it is too large.
Load diff
@@ -30,7 +30,7 @@ function* testTopLeft(inspector, view) {
|
||||
elementRulesNb: 4,
|
||||
firstLineRulesNb: 2,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 0,
|
||||
selectionRulesNb: 1,
|
||||
afterRulesNb: 1,
|
||||
beforeRulesNb: 2
|
||||
}
|
||||
@@ -167,7 +167,7 @@ function* testParagraph(inspector, view) {
|
||||
elementRulesNb: 3,
|
||||
firstLineRulesNb: 1,
|
||||
firstLetterRulesNb: 1,
|
||||
selectionRulesNb: 1,
|
||||
selectionRulesNb: 2,
|
||||
beforeRulesNb: 0,
|
||||
afterRulesNb: 0
|
||||
});
|
||||
@@ -217,7 +217,7 @@ function* assertPseudoElementRulesNumbers(selector, inspector, view, ruleNbs) {
|
||||
firstLetterRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":first-letter"),
|
||||
selectionRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":-moz-selection"),
|
||||
rule.pseudoElement === ":selection"),
|
||||
beforeRules: elementStyle.rules.filter(rule =>
|
||||
rule.pseudoElement === ":before"),
|
||||
afterRules: elementStyle.rules.filter(rule =>
|
||||
|
||||
@@ -2872,6 +2872,7 @@ exports.CSS_PROPERTIES = {
|
||||
"box-shadow",
|
||||
"box-sizing",
|
||||
"caption-side",
|
||||
"caret-color",
|
||||
"clear",
|
||||
"clip",
|
||||
"clip-path",
|
||||
@@ -5277,6 +5278,28 @@ exports.CSS_PROPERTIES = {
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"caret-color": {
|
||||
"isInherited": true,
|
||||
"subproperties": [
|
||||
"caret-color"
|
||||
],
|
||||
"supports": [
|
||||
2
|
||||
],
|
||||
"values": [
|
||||
"COLOR",
|
||||
"auto",
|
||||
"currentColor",
|
||||
"hsl",
|
||||
"hsla",
|
||||
"inherit",
|
||||
"initial",
|
||||
"rgb",
|
||||
"rgba",
|
||||
"transparent",
|
||||
"unset"
|
||||
]
|
||||
},
|
||||
"clear": {
|
||||
"isInherited": false,
|
||||
"subproperties": [
|
||||
@@ -7857,6 +7880,7 @@ exports.CSS_PROPERTIES = {
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"anywhere",
|
||||
"break-word",
|
||||
"inherit",
|
||||
"initial",
|
||||
@@ -9317,6 +9341,7 @@ exports.CSS_PROPERTIES = {
|
||||
],
|
||||
"supports": [],
|
||||
"values": [
|
||||
"anywhere",
|
||||
"break-word",
|
||||
"inherit",
|
||||
"initial",
|
||||
@@ -9373,6 +9398,7 @@ exports.PSEUDO_ELEMENTS = [
|
||||
":backdrop",
|
||||
":first-letter",
|
||||
":first-line",
|
||||
":selection",
|
||||
":-moz-selection",
|
||||
":-moz-focus-inner",
|
||||
":-moz-focus-outer",
|
||||
|
||||
@@ -93,15 +93,20 @@ With rare exception, it is advisable to use the following style for commit messa
|
||||
|
||||
This would directly apply to anyone making a pull request.
|
||||
|
||||
Single commits are where issues can be reasonably resolved in a single commit.
|
||||
- Single Commit: `Issue #xxx - Cited issue title or appropriate direct description of changes`
|
||||
- *`Issue #1083 - Deprecate FUEL extension helper javascript library`*
|
||||
- Multi-Part Commits: `Issue #xxx - Part Number: Appropriate direct description of changes`
|
||||
|
||||
Multi-part commits would be used for complex issues. However, an exception exists for multi-part commits where the issue is anticipated or ends up being long term such as "Stop using unified compilation of sources". In these instances the multi-part form is not required.
|
||||
- Multi-Part Form: `Issue #xxx - Part Number: Appropriate direct description of changes`
|
||||
- *`Issue #492 - Part 1: Remove files`*
|
||||
- *`Issue #492 - Part 2: Build system, Installer/Packaging`*
|
||||
- *`Issue #492 - Part 3: nsUpdateService.js, updater.cpp, nsUpdateDriver.cpp`*
|
||||
- *`Issue #492 - Part 4: Remove superfluous brackets in nsUpdateService.js and updater.cpp`*
|
||||
|
||||
An exception exists for multi-part commits where the issue is anticipated or ends up being long term such as "Stop using unified compilation of sources". In these instances the multi-part form is not required.
|
||||
Occasionally a resolved (and shipped) issue requires further changes to fix bugs. However, If follow-ups are complex enough to be multi-part it should be considered a new issue.
|
||||
- Follow-up Form: *`Issue #xxx - Follow-up: Appropriate direct description of changes`*
|
||||
- *`Issue #1643 - Follow-up: Make sure things aren't changed while iterating.`*
|
||||
|
||||
### Commits with no issue
|
||||
|
||||
|
||||
@@ -56,9 +56,16 @@ AbortSignal::Aborted() const
|
||||
void
|
||||
AbortSignal::Abort()
|
||||
{
|
||||
MOZ_ASSERT(!mAborted);
|
||||
// Re-entrancy guard
|
||||
if (mAborted) {
|
||||
return;
|
||||
}
|
||||
mAborted = true;
|
||||
|
||||
// We might be deleted as a result of aborting a follower, so ensure we
|
||||
// stay alive until all followers have been aborted.
|
||||
RefPtr<AbortSignal> pinThis = this;
|
||||
|
||||
// Let's inform the followers.
|
||||
for (uint32_t i = 0; i < mFollowers.Length(); ++i) {
|
||||
mFollowers[i]->Aborted();
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ EXPORTS.mozilla.dom += [
|
||||
'AbortSignal.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
SOURCES += [
|
||||
'AbortController.cpp',
|
||||
'AbortSignal.cpp',
|
||||
]
|
||||
|
||||
@@ -38,8 +38,6 @@ struct AnimationPerformanceWarning
|
||||
std::initializer_list<int32_t> aParams)
|
||||
: mType(aType)
|
||||
{
|
||||
// FIXME: Once std::initializer_list::size() become a constexpr function,
|
||||
// we should use static_assert here.
|
||||
MOZ_ASSERT(aParams.size() <= kMaxParamsForLocalization,
|
||||
"The length of parameters should be less than "
|
||||
"kMaxParamsForLocalization");
|
||||
@@ -49,11 +47,11 @@ struct AnimationPerformanceWarning
|
||||
// Maximum number of parameters passed to
|
||||
// nsContentUtils::FormatLocalizedString to localize warning messages.
|
||||
//
|
||||
// NOTE: This constexpr can't be forward declared, so if you want to use
|
||||
// NOTE: This can't be forward declared, so if you want to use
|
||||
// this variable, please include this header file directly.
|
||||
// This value is the same as the limit of nsStringBundle::FormatString.
|
||||
// See the implementation of nsStringBundle::FormatString.
|
||||
static constexpr uint8_t kMaxParamsForLocalization = 10;
|
||||
static const uint8_t kMaxParamsForLocalization = 10;
|
||||
|
||||
// Indicates why this property could not be animated on the compositor.
|
||||
Type mType;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "BatteryManager.h"
|
||||
#ifdef MOZ_GAMEPAD
|
||||
#include "mozilla/dom/GamepadServiceTest.h"
|
||||
#endif
|
||||
@@ -197,8 +196,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPermissions)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStorageManager)
|
||||
@@ -249,13 +246,6 @@ Navigator::Invalidate()
|
||||
mNotification = nullptr;
|
||||
}
|
||||
|
||||
if (mBatteryManager) {
|
||||
mBatteryManager->Shutdown();
|
||||
mBatteryManager = nullptr;
|
||||
}
|
||||
|
||||
mBatteryPromise = nullptr;
|
||||
|
||||
if (mPowerManager) {
|
||||
mPowerManager->Shutdown();
|
||||
mPowerManager = nullptr;
|
||||
@@ -1321,39 +1311,6 @@ Navigator::GetMozNotification(ErrorResult& aRv)
|
||||
return mNotification;
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
// Navigator::nsINavigatorBattery
|
||||
//*****************************************************************************
|
||||
|
||||
Promise*
|
||||
Navigator::GetBattery(ErrorResult& aRv)
|
||||
{
|
||||
if (mBatteryPromise) {
|
||||
return mBatteryPromise;
|
||||
}
|
||||
|
||||
if (!mWindow || !mWindow->GetDocShell()) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(mWindow);
|
||||
RefPtr<Promise> batteryPromise = Promise::Create(go, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
mBatteryPromise = batteryPromise;
|
||||
|
||||
if (!mBatteryManager) {
|
||||
mBatteryManager = new battery::BatteryManager(mWindow);
|
||||
mBatteryManager->Init();
|
||||
}
|
||||
|
||||
mBatteryPromise->MaybeResolve(mBatteryManager);
|
||||
|
||||
return mBatteryPromise;
|
||||
}
|
||||
|
||||
PowerManager*
|
||||
Navigator::GetMozPower(ErrorResult& aRv)
|
||||
{
|
||||
|
||||
@@ -51,10 +51,6 @@ namespace dom {
|
||||
|
||||
class Permissions;
|
||||
|
||||
namespace battery {
|
||||
class BatteryManager;
|
||||
} // namespace battery
|
||||
|
||||
class Promise;
|
||||
|
||||
class DesktopNotificationCenter;
|
||||
@@ -136,7 +132,6 @@ public:
|
||||
Permissions* GetPermissions(ErrorResult& aRv);
|
||||
// The XPCOM GetDoNotTrack is ok
|
||||
Geolocation* GetGeolocation(ErrorResult& aRv);
|
||||
Promise* GetBattery(ErrorResult& aRv);
|
||||
|
||||
static void AppName(nsAString& aAppName, bool aUsePrefOverriddenValue);
|
||||
|
||||
@@ -269,8 +264,6 @@ private:
|
||||
RefPtr<Permissions> mPermissions;
|
||||
RefPtr<Geolocation> mGeolocation;
|
||||
RefPtr<DesktopNotificationCenter> mNotification;
|
||||
RefPtr<battery::BatteryManager> mBatteryManager;
|
||||
RefPtr<Promise> mBatteryPromise;
|
||||
RefPtr<PowerManager> mPowerManager;
|
||||
RefPtr<network::Connection> mConnection;
|
||||
#ifdef MOZ_AUDIO_CHANNEL_MANAGER
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/ResizeObserver.h"
|
||||
|
||||
#include "mozilla/dom/DOMRect.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsSVGUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserver)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserver)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(ResizeObserver)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mObservationMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ResizeObserver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOwner)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mObservationMap)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
already_AddRefed<ResizeObserver>
|
||||
ResizeObserver::Constructor(const GlobalObject& aGlobal,
|
||||
ResizeObserverCallback& aCb,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||
do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> document = window->GetExtantDoc();
|
||||
|
||||
if (!document) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ResizeObserver> observer = new ResizeObserver(window.forget(), aCb);
|
||||
document->AddResizeObserver(observer);
|
||||
|
||||
return observer.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::Observe(Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!aTarget) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ResizeObservation> observation;
|
||||
|
||||
if (!mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
|
||||
observation = new ResizeObservation(this, aTarget);
|
||||
|
||||
mObservationMap.Put(aTarget, observation);
|
||||
mObservationList.insertBack(observation);
|
||||
|
||||
// Per the spec, we need to trigger notification in event loop that
|
||||
// contains ResizeObserver observe call even when resize/reflow does
|
||||
// not happen.
|
||||
aTarget->OwnerDoc()->ScheduleResizeObserversNotification();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::Unobserve(Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
if (!aTarget) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ResizeObservation> observation;
|
||||
|
||||
if (mObservationMap.Get(aTarget, getter_AddRefs(observation))) {
|
||||
mObservationMap.Remove(aTarget);
|
||||
|
||||
MOZ_ASSERT(!mObservationList.isEmpty(),
|
||||
"If ResizeObservation found for an element, observation list "
|
||||
"must be not empty.");
|
||||
|
||||
observation->remove();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::Disconnect()
|
||||
{
|
||||
mObservationMap.Clear();
|
||||
mObservationList.clear();
|
||||
mActiveTargets.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserver::GatherActiveObservations(uint32_t aDepth)
|
||||
{
|
||||
mActiveTargets.Clear();
|
||||
mHasSkippedTargets = false;
|
||||
|
||||
for (auto observation : mObservationList) {
|
||||
if (observation->IsActive()) {
|
||||
uint32_t targetDepth =
|
||||
nsContentUtils::GetNodeDepth(observation->Target());
|
||||
|
||||
if (targetDepth > aDepth) {
|
||||
mActiveTargets.AppendElement(observation);
|
||||
} else {
|
||||
mHasSkippedTargets = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserver::HasActiveObservations() const
|
||||
{
|
||||
return !mActiveTargets.IsEmpty();
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserver::HasSkippedObservations() const
|
||||
{
|
||||
return mHasSkippedTargets;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ResizeObserver::BroadcastActiveObservations()
|
||||
{
|
||||
uint32_t shallowestTargetDepth = UINT32_MAX;
|
||||
|
||||
if (HasActiveObservations()) {
|
||||
Sequence<OwningNonNull<ResizeObserverEntry>> entries;
|
||||
|
||||
for (auto observation : mActiveTargets) {
|
||||
RefPtr<ResizeObserverEntry> entry =
|
||||
new ResizeObserverEntry(this, observation->Target());
|
||||
|
||||
nsRect rect = observation->GetTargetRect();
|
||||
entry->SetContentRect(rect);
|
||||
|
||||
if (!entries.AppendElement(entry.forget(), fallible)) {
|
||||
// Out of memory.
|
||||
break;
|
||||
}
|
||||
|
||||
// Sync the broadcast size of observation so the next size inspection
|
||||
// will be based on the updated size from last delivered observations.
|
||||
observation->UpdateBroadcastSize(rect);
|
||||
|
||||
uint32_t targetDepth =
|
||||
nsContentUtils::GetNodeDepth(observation->Target());
|
||||
|
||||
if (targetDepth < shallowestTargetDepth) {
|
||||
shallowestTargetDepth = targetDepth;
|
||||
}
|
||||
}
|
||||
|
||||
mCallback->Call(this, entries, *this);
|
||||
mActiveTargets.Clear();
|
||||
mHasSkippedTargets = false;
|
||||
}
|
||||
|
||||
return shallowestTargetDepth;
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObserverEntry)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObserverEntry)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObserverEntry)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObserverEntry,
|
||||
mTarget, mContentRect,
|
||||
mOwner)
|
||||
|
||||
already_AddRefed<ResizeObserverEntry>
|
||||
ResizeObserverEntry::Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<ResizeObserverEntry> observerEntry =
|
||||
new ResizeObserverEntry(aGlobal.GetAsSupports(), aTarget);
|
||||
return observerEntry.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverEntry::SetContentRect(nsRect aRect)
|
||||
{
|
||||
RefPtr<DOMRect> contentRect = new DOMRect(mTarget);
|
||||
nsIFrame* frame = mTarget->GetPrimaryFrame();
|
||||
|
||||
if (frame) {
|
||||
nsMargin padding = frame->GetUsedPadding();
|
||||
|
||||
// Per the spec, we need to include padding in contentRect of
|
||||
// ResizeObserverEntry.
|
||||
aRect.x = padding.left;
|
||||
aRect.y = padding.top;
|
||||
}
|
||||
|
||||
contentRect->SetLayoutRect(aRect);
|
||||
mContentRect = contentRect.forget();
|
||||
}
|
||||
|
||||
ResizeObserverEntry::~ResizeObserverEntry()
|
||||
{
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ResizeObservation)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(ResizeObservation)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(ResizeObservation)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ResizeObservation,
|
||||
mTarget, mOwner)
|
||||
|
||||
already_AddRefed<ResizeObservation>
|
||||
ResizeObservation::Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<ResizeObservation> observation =
|
||||
new ResizeObservation(aGlobal.GetAsSupports(), aTarget);
|
||||
return observation.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObservation::IsActive() const
|
||||
{
|
||||
nsRect rect = GetTargetRect();
|
||||
return (rect.width != mBroadcastWidth || rect.height != mBroadcastHeight);
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObservation::UpdateBroadcastSize(nsRect aRect)
|
||||
{
|
||||
mBroadcastWidth = aRect.width;
|
||||
mBroadcastHeight = aRect.height;
|
||||
}
|
||||
|
||||
nsRect
|
||||
ResizeObservation::GetTargetRect() const
|
||||
{
|
||||
nsRect rect;
|
||||
nsIFrame* frame = mTarget->GetPrimaryFrame();
|
||||
|
||||
if (frame) {
|
||||
if (mTarget->IsSVGElement()) {
|
||||
gfxRect bbox = nsSVGUtils::GetBBox(frame);
|
||||
rect.width = NSFloatPixelsToAppUnits(bbox.width, AppUnitsPerCSSPixel());
|
||||
rect.height = NSFloatPixelsToAppUnits(bbox.height, AppUnitsPerCSSPixel());
|
||||
} else {
|
||||
// Per the spec, non-replaced inline Elements will always have an empty
|
||||
// content rect.
|
||||
if (frame->IsFrameOfType(nsIFrame::eReplaced) ||
|
||||
!frame->IsFrameOfType(nsIFrame::eLineParticipant)) {
|
||||
rect = frame->GetContentRectRelativeToSelf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
ResizeObservation::~ResizeObservation()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,254 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ResizeObserver_h
|
||||
#define mozilla_dom_ResizeObserver_h
|
||||
|
||||
#include "mozilla/dom/ResizeObserverBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
/**
|
||||
* ResizeObserver interfaces and algorithms are based on
|
||||
* https://wicg.github.io/ResizeObserver/#api
|
||||
*/
|
||||
class ResizeObserver final
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserver)
|
||||
|
||||
ResizeObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,
|
||||
ResizeObserverCallback& aCb)
|
||||
: mOwner(aOwner)
|
||||
, mCallback(&aCb)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner window");
|
||||
}
|
||||
|
||||
static already_AddRefed<ResizeObserver>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
ResizeObserverCallback& aCb,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return ResizeObserverBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
void Observe(Element* aTarget, ErrorResult& aRv);
|
||||
|
||||
void Unobserve(Element* aTarget, ErrorResult& aRv);
|
||||
|
||||
void Disconnect();
|
||||
|
||||
/*
|
||||
* Gather all observations which have an observed target with size changed
|
||||
* since last BroadcastActiveObservations() in this ResizeObserver.
|
||||
* An observation will be skipped if the depth of its observed target is less
|
||||
* or equal than aDepth. All gathered observations will be added to
|
||||
* mActiveTargets.
|
||||
*/
|
||||
void GatherActiveObservations(uint32_t aDepth);
|
||||
|
||||
/*
|
||||
* Returns whether this ResizeObserver has any active observations
|
||||
* since last GatherActiveObservations().
|
||||
*/
|
||||
bool HasActiveObservations() const;
|
||||
|
||||
/*
|
||||
* Returns whether this ResizeObserver has any skipped observations
|
||||
* since last GatherActiveObservations().
|
||||
*/
|
||||
bool HasSkippedObservations() const;
|
||||
|
||||
/*
|
||||
* Deliver the callback function in JavaScript for all active observations
|
||||
* and pass the sequence of ResizeObserverEntry so JavaScript can access them.
|
||||
* The broadcast size of observations will be updated and mActiveTargets will
|
||||
* be cleared. It also returns the shallowest depth of elements from active
|
||||
* observations or UINT32_MAX if there is no any active observations.
|
||||
*/
|
||||
uint32_t BroadcastActiveObservations();
|
||||
|
||||
protected:
|
||||
~ResizeObserver()
|
||||
{
|
||||
mObservationList.clear();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> mOwner;
|
||||
RefPtr<ResizeObserverCallback> mCallback;
|
||||
nsTArray<RefPtr<ResizeObservation>> mActiveTargets;
|
||||
bool mHasSkippedTargets;
|
||||
|
||||
// Combination of HashTable and LinkedList so we can iterate through
|
||||
// the elements of HashTable in order of insertion time.
|
||||
// Will be nice if we have our own data structure for this in the future.
|
||||
nsRefPtrHashtable<nsPtrHashKey<Element>, ResizeObservation> mObservationMap;
|
||||
LinkedList<ResizeObservation> mObservationList;
|
||||
};
|
||||
|
||||
/**
|
||||
* ResizeObserverEntry is the entry that contains the information for observed
|
||||
* elements. This object is the one that visible to JavaScript in callback
|
||||
* function that is fired by ResizeObserver.
|
||||
*/
|
||||
class ResizeObserverEntry final
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObserverEntry)
|
||||
|
||||
ResizeObserverEntry(nsISupports* aOwner, Element* aTarget)
|
||||
: mOwner(aOwner)
|
||||
, mTarget(aTarget)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner");
|
||||
MOZ_ASSERT(mTarget, "Need a non-null target element");
|
||||
}
|
||||
|
||||
static already_AddRefed<ResizeObserverEntry>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return ResizeObserverEntryBinding::Wrap(aCx, this,
|
||||
aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
Element* Target() const
|
||||
{
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the DOMRectReadOnly of target's content rect so it can be
|
||||
* accessed from JavaScript in callback function of ResizeObserver.
|
||||
*/
|
||||
DOMRectReadOnly* GetContentRect() const
|
||||
{
|
||||
return mContentRect;
|
||||
}
|
||||
|
||||
void SetContentRect(nsRect aRect);
|
||||
|
||||
protected:
|
||||
~ResizeObserverEntry();
|
||||
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsCOMPtr<Element> mTarget;
|
||||
RefPtr<DOMRectReadOnly> mContentRect;
|
||||
};
|
||||
|
||||
/**
|
||||
* We use ResizeObservation to store and sync the size information of one
|
||||
* observed element so we can decide whether an observation should be fired
|
||||
* or not.
|
||||
*/
|
||||
class ResizeObservation final
|
||||
: public nsISupports
|
||||
, public nsWrapperCache
|
||||
, public LinkedListElement<ResizeObservation>
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(ResizeObservation)
|
||||
|
||||
ResizeObservation(nsISupports* aOwner, Element* aTarget)
|
||||
: mOwner(aOwner)
|
||||
, mTarget(aTarget)
|
||||
, mBroadcastWidth(0)
|
||||
, mBroadcastHeight(0)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner");
|
||||
MOZ_ASSERT(mTarget, "Need a non-null target element");
|
||||
}
|
||||
|
||||
static already_AddRefed<ResizeObservation>
|
||||
Constructor(const GlobalObject& aGlobal,
|
||||
Element* aTarget,
|
||||
ErrorResult& aRv);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
return ResizeObservationBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
nsISupports* GetParentObject() const
|
||||
{
|
||||
return mOwner;
|
||||
}
|
||||
|
||||
Element* Target() const
|
||||
{
|
||||
return mTarget;
|
||||
}
|
||||
|
||||
nscoord BroadcastWidth() const
|
||||
{
|
||||
return mBroadcastWidth;
|
||||
}
|
||||
|
||||
nscoord BroadcastHeight() const
|
||||
{
|
||||
return mBroadcastHeight;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns whether the observed target element size differs from current
|
||||
* BroadcastWidth and BroadcastHeight
|
||||
*/
|
||||
bool IsActive() const;
|
||||
|
||||
/*
|
||||
* Update current BroadcastWidth and BroadcastHeight with size from aRect.
|
||||
*/
|
||||
void UpdateBroadcastSize(nsRect aRect);
|
||||
|
||||
/*
|
||||
* Returns the target's rect in the form of nsRect.
|
||||
* If the target is SVG, width and height are determined from bounding box.
|
||||
*/
|
||||
nsRect GetTargetRect() const;
|
||||
|
||||
protected:
|
||||
~ResizeObservation();
|
||||
|
||||
nsCOMPtr<nsISupports> mOwner;
|
||||
nsCOMPtr<Element> mTarget;
|
||||
|
||||
// Broadcast width and broadcast height are the latest recorded size
|
||||
// of observed target.
|
||||
nscoord mBroadcastWidth;
|
||||
nscoord mBroadcastHeight;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ResizeObserver_h
|
||||
|
||||
@@ -0,0 +1,252 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/ResizeObserverController.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ErrorEvent.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::WillRefresh(TimeStamp aTime)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mOwner, "RefreshObserver should have been de-registered on time, but isn't.");
|
||||
if (mOwner) {
|
||||
mOwner->Notify();
|
||||
}
|
||||
}
|
||||
|
||||
nsRefreshDriver*
|
||||
ResizeObserverNotificationHelper::GetRefreshDriver() const
|
||||
{
|
||||
nsIPresShell* presShell = mOwner->GetShell();
|
||||
if (MOZ_UNLIKELY(!presShell)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
if (MOZ_UNLIKELY(!presContext)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return presContext->RefreshDriver();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::Register()
|
||||
{
|
||||
if (mRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefreshDriver* refreshDriver = GetRefreshDriver();
|
||||
if (!refreshDriver) {
|
||||
// We maybe navigating away from this page or currently in an iframe with
|
||||
// display: none. Just abort the Register(), no need to do notification.
|
||||
return;
|
||||
}
|
||||
|
||||
refreshDriver->AddRefreshObserver(this, Flush_Display);
|
||||
mRegistered = true;
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::Unregister()
|
||||
{
|
||||
if (!mOwner) {
|
||||
// We've outlived our owner, so there's nothing registered anymore.
|
||||
mRegistered = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mRegistered) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefreshDriver* refreshDriver = GetRefreshDriver();
|
||||
MOZ_RELEASE_ASSERT(refreshDriver,
|
||||
"We should not leave a dangling reference to the observer around");
|
||||
|
||||
refreshDriver->RemoveRefreshObserver(this, Flush_Display);
|
||||
mRegistered = false;
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverNotificationHelper::Disconnect()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(!mRegistered, "How can we die when registered?");
|
||||
MOZ_RELEASE_ASSERT(!mOwner, "Forgot to clear weak pointer?");
|
||||
}
|
||||
|
||||
ResizeObserverNotificationHelper::~ResizeObserverNotificationHelper()
|
||||
{
|
||||
Unregister();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::Traverse(nsCycleCollectionTraversalCallback& aCb)
|
||||
{
|
||||
ImplCycleCollectionTraverse(aCb, mResizeObservers, "mResizeObservers");
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::Unlink()
|
||||
{
|
||||
mResizeObservers.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::AddResizeObserver(ResizeObserver* aObserver)
|
||||
{
|
||||
MOZ_ASSERT(aObserver, "AddResizeObserver() should never be called with "
|
||||
"a null parameter");
|
||||
mResizeObservers.AppendElement(aObserver);
|
||||
}
|
||||
|
||||
void ResizeObserverController::DetachFromDocument() {
|
||||
mResizeObserverNotificationHelper->Unregister();
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::Notify()
|
||||
{
|
||||
if (mResizeObservers.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Hold a strong reference to the document, because otherwise calling
|
||||
// all active observers on it might yank it out from under us.
|
||||
RefPtr<nsIDocument> document(mDocument);
|
||||
|
||||
uint32_t shallowestTargetDepth = 0;
|
||||
|
||||
GatherAllActiveObservations(shallowestTargetDepth);
|
||||
|
||||
while (HasAnyActiveObservations()) {
|
||||
DebugOnly<uint32_t> oldShallowestTargetDepth = shallowestTargetDepth;
|
||||
shallowestTargetDepth = BroadcastAllActiveObservations();
|
||||
NS_ASSERTION(oldShallowestTargetDepth < shallowestTargetDepth,
|
||||
"shallowestTargetDepth should be getting strictly deeper");
|
||||
|
||||
// Flush layout, so that any callback functions' style changes / resizes
|
||||
// get a chance to take effect.
|
||||
mDocument->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
// To avoid infinite resize loop, we only gather all active observations
|
||||
// that have the depth of observed target element more than current
|
||||
// shallowestTargetDepth.
|
||||
GatherAllActiveObservations(shallowestTargetDepth);
|
||||
}
|
||||
|
||||
mResizeObserverNotificationHelper->Unregister();
|
||||
|
||||
// Per spec, we deliver an error if the document has any skipped observations.
|
||||
if (HasAnySkippedObservations()) {
|
||||
RootedDictionary<ErrorEventInit> init(RootingCx());
|
||||
|
||||
init.mMessage.AssignLiteral("ResizeObserver loop completed with undelivered"
|
||||
" notifications.");
|
||||
init.mCancelable = true;
|
||||
init.mBubbles = true;
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window =
|
||||
document->GetWindow()->GetCurrentInnerWindow();
|
||||
|
||||
if (window) {
|
||||
nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(window);
|
||||
MOZ_ASSERT(sgo);
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(sgo->HandleScriptError(init, &status)))) {
|
||||
status = nsEventStatus_eIgnore;
|
||||
}
|
||||
} else {
|
||||
// We don't fire error events at any global for non-window JS on the main
|
||||
// thread.
|
||||
}
|
||||
|
||||
// We need to deliver pending notifications in next cycle.
|
||||
ScheduleNotification();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::GatherAllActiveObservations(uint32_t aDepth)
|
||||
{
|
||||
for (auto observer : mResizeObservers) {
|
||||
observer->GatherActiveObservations(aDepth);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ResizeObserverController::BroadcastAllActiveObservations()
|
||||
{
|
||||
uint32_t shallowestTargetDepth = UINT32_MAX;
|
||||
|
||||
// Use a copy of the observers as this invokes the callbacks of the observers
|
||||
// which could register/unregister observers at will.
|
||||
nsTArray<RefPtr<ResizeObserver>> tempObservers(mResizeObservers);
|
||||
|
||||
for (auto observer : tempObservers) {
|
||||
|
||||
uint32_t targetDepth = observer->BroadcastActiveObservations();
|
||||
|
||||
if (targetDepth < shallowestTargetDepth) {
|
||||
shallowestTargetDepth = targetDepth;
|
||||
}
|
||||
}
|
||||
|
||||
return shallowestTargetDepth;
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserverController::HasAnyActiveObservations() const
|
||||
{
|
||||
for (auto observer : mResizeObservers) {
|
||||
if (observer->HasActiveObservations()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ResizeObserverController::HasAnySkippedObservations() const
|
||||
{
|
||||
for (auto observer : mResizeObservers) {
|
||||
if (observer->HasSkippedObservations()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ResizeObserverController::ScheduleNotification()
|
||||
{
|
||||
mResizeObserverNotificationHelper->Register();
|
||||
}
|
||||
|
||||
nsIPresShell*
|
||||
ResizeObserverController::GetShell() const
|
||||
{
|
||||
return mDocument->GetShell();
|
||||
}
|
||||
|
||||
ResizeObserverController::~ResizeObserverController()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(
|
||||
!mResizeObserverNotificationHelper->IsRegistered(),
|
||||
"Nothing else should keep a reference to our notification helper when we go away");
|
||||
mResizeObserverNotificationHelper->DetachFromOwner();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,134 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ResizeObserverController_h
|
||||
#define mozilla_dom_ResizeObserverController_h
|
||||
|
||||
#include "mozilla/dom/ResizeObserver.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ResizeObserverController;
|
||||
|
||||
/*
|
||||
* ResizeObserverNotificationHelper will trigger ResizeObserver notifications
|
||||
* by registering with the Refresh Driver.
|
||||
*/
|
||||
class ResizeObserverNotificationHelper final : public nsARefreshObserver
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(ResizeObserverNotificationHelper, override)
|
||||
|
||||
explicit ResizeObserverNotificationHelper(ResizeObserverController* aOwner)
|
||||
: mOwner(aOwner)
|
||||
, mRegistered(false)
|
||||
{
|
||||
MOZ_ASSERT(mOwner, "Need a non-null owner");
|
||||
}
|
||||
|
||||
void WillRefresh(TimeStamp aTime) override;
|
||||
|
||||
nsRefreshDriver* GetRefreshDriver() const;
|
||||
|
||||
void Register();
|
||||
|
||||
void Unregister();
|
||||
|
||||
void Disconnect();
|
||||
|
||||
bool IsRegistered() const { return mRegistered; }
|
||||
|
||||
void DetachFromOwner() { mOwner = nullptr; }
|
||||
|
||||
protected:
|
||||
virtual ~ResizeObserverNotificationHelper();
|
||||
|
||||
ResizeObserverController* mOwner;
|
||||
bool mRegistered;
|
||||
};
|
||||
|
||||
/*
|
||||
* ResizeObserverController contains the list of ResizeObservers and controls
|
||||
* the flow of notification.
|
||||
*/
|
||||
class ResizeObserverController final
|
||||
{
|
||||
public:
|
||||
explicit ResizeObserverController(nsIDocument* aDocument)
|
||||
: mDocument(aDocument)
|
||||
, mIsNotificationActive(false)
|
||||
{
|
||||
MOZ_ASSERT(mDocument, "Need a non-null document");
|
||||
mResizeObserverNotificationHelper =
|
||||
new ResizeObserverNotificationHelper(this);
|
||||
}
|
||||
|
||||
// Methods for supporting cycle-collection
|
||||
void Traverse(nsCycleCollectionTraversalCallback& aCb);
|
||||
void Unlink();
|
||||
|
||||
void DetachFromDocument();
|
||||
void AddResizeObserver(ResizeObserver* aObserver);
|
||||
|
||||
/*
|
||||
* Schedule the notification via ResizeObserverNotificationHelper refresh
|
||||
* observer.
|
||||
*/
|
||||
void ScheduleNotification();
|
||||
|
||||
/*
|
||||
* Notify all ResizeObservers by gathering and broadcasting all active
|
||||
* observations.
|
||||
*/
|
||||
void Notify();
|
||||
|
||||
nsIPresShell* GetShell() const;
|
||||
|
||||
~ResizeObserverController();
|
||||
|
||||
private:
|
||||
/*
|
||||
* Calls GatherActiveObservations(aDepth) for all ResizeObservers in this
|
||||
* controller. All observations in each ResizeObserver with element's depth
|
||||
* more than aDepth will be gathered.
|
||||
*/
|
||||
void GatherAllActiveObservations(uint32_t aDepth);
|
||||
|
||||
/*
|
||||
* Calls BroadcastActiveObservations() for all ResizeObservers in this
|
||||
* controller. It also returns the shallowest depth of observed target
|
||||
* elements from all ResizeObserver or UINT32_MAX if there is no any
|
||||
* active obsevations at all.
|
||||
*/
|
||||
uint32_t BroadcastAllActiveObservations();
|
||||
|
||||
/*
|
||||
* Returns whether there is any ResizeObserver that has active observations.
|
||||
*/
|
||||
bool HasAnyActiveObservations() const;
|
||||
|
||||
/*
|
||||
* Returns whether there is any ResizeObserver that has skipped observations.
|
||||
*/
|
||||
bool HasAnySkippedObservations() const;
|
||||
|
||||
protected:
|
||||
// Raw pointer is OK because mDocument strongly owns us & hence must outlive
|
||||
// us.
|
||||
nsIDocument* const mDocument;
|
||||
|
||||
RefPtr<ResizeObserverNotificationHelper> mResizeObserverNotificationHelper;
|
||||
nsTArray<RefPtr<ResizeObserver>> mResizeObservers;
|
||||
bool mIsNotificationActive;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ResizeObserverController_h
|
||||
@@ -15,7 +15,7 @@ namespace dom {
|
||||
class WindowNamedPropertiesHandler : public BaseDOMProxyHandler
|
||||
{
|
||||
public:
|
||||
constexpr WindowNamedPropertiesHandler()
|
||||
WindowNamedPropertiesHandler()
|
||||
: BaseDOMProxyHandler(nullptr, /* hasPrototype = */ true)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script>
|
||||
|
||||
var frameRoot;
|
||||
|
||||
function boom()
|
||||
{
|
||||
var frameWin = f.contentWindow;
|
||||
frameRoot = frameWin.document.documentElement;
|
||||
frameWin.location.replace("data:text/html;charset=UTF-8,<body onload='parent.g();'>2");
|
||||
}
|
||||
|
||||
function g()
|
||||
{
|
||||
setTimeout(h, 0);
|
||||
}
|
||||
|
||||
function h()
|
||||
{
|
||||
var newDoc = document.implementation.createDocument('', '', null);
|
||||
newDoc.adoptNode(frameRoot);
|
||||
}
|
||||
|
||||
</script>
|
||||
<body onload="boom();">
|
||||
|
||||
<iframe id="f" src="data:text/html;charset=UTF-8,<marquee>1"></iframe>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
|
||||
<head>
|
||||
<script>
|
||||
|
||||
function boom()
|
||||
{
|
||||
var marquee = document.getElementById("marquee");
|
||||
var span = document.getElementById("span");
|
||||
marquee.appendChild(span);
|
||||
marquee.removeChild(span);
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body onload="setTimeout(boom, 30);">
|
||||
|
||||
<marquee id="marquee" />
|
||||
|
||||
<span id="span"><div>Foo</div><textarea/></span>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,28 +0,0 @@
|
||||
<html class="reftest-wait">
|
||||
<head>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
var i = 0;
|
||||
function mmf()
|
||||
{
|
||||
if (++i == 2) {
|
||||
document.body.innerHTML = "<marquee>";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}
|
||||
}
|
||||
|
||||
function init()
|
||||
{
|
||||
document.documentElement.offsetHeight;
|
||||
for (var j = 0; j < 2; ++j) {
|
||||
var iframe = document.createElementNS("http://www.w3.org/1999/xhtml", "iframe");
|
||||
iframe.addEventListener("load", mmf, false);
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="setTimeout(init, 0);"></body>
|
||||
</html>
|
||||
+4
-1
@@ -202,6 +202,8 @@ EXPORTS.mozilla.dom += [
|
||||
'PartialSHistory.h',
|
||||
'Pose.h',
|
||||
'ProcessGlobal.h',
|
||||
'ResizeObserver.h',
|
||||
'ResizeObserverController.h',
|
||||
'ResponsiveImageSelector.h',
|
||||
'SameProcessMessageQueue.h',
|
||||
'ScreenOrientation.h',
|
||||
@@ -347,6 +349,8 @@ SOURCES += [
|
||||
'Pose.cpp',
|
||||
'PostMessageEvent.cpp',
|
||||
'ProcessGlobal.cpp',
|
||||
'ResizeObserver.cpp',
|
||||
'ResizeObserverController.cpp',
|
||||
'ResponsiveImageSelector.cpp',
|
||||
'SameProcessMessageQueue.cpp',
|
||||
'ScreenOrientation.cpp',
|
||||
@@ -416,7 +420,6 @@ EXTRA_JS_MODULES += [
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../battery',
|
||||
'../events',
|
||||
'../media',
|
||||
'../network',
|
||||
|
||||
@@ -268,7 +268,7 @@ public:
|
||||
// EnumTable can be initialized either with an int16_t value
|
||||
// or a value of an enumeration type that can fit within an int16_t.
|
||||
|
||||
constexpr EnumTable(const char* aTag, int16_t aValue)
|
||||
EnumTable(const char* aTag, int16_t aValue)
|
||||
: tag(aTag)
|
||||
, value(aValue)
|
||||
{
|
||||
@@ -276,7 +276,7 @@ public:
|
||||
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<std::is_enum<T>::value>::type>
|
||||
constexpr EnumTable(const char* aTag, T aValue)
|
||||
EnumTable(const char* aTag, T aValue)
|
||||
: tag(aTag)
|
||||
, value(static_cast<int16_t>(aValue))
|
||||
{
|
||||
|
||||
@@ -789,13 +789,14 @@ nsContentSink::ProcessStyleLink(nsIContent* aElement,
|
||||
// If this is a fragment parser, we don't want to observe.
|
||||
// We don't support CORS for processing instructions
|
||||
bool isAlternate;
|
||||
bool isExplicitlyEnabled;
|
||||
rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
|
||||
CORS_NONE, mDocument->GetReferrerPolicy(),
|
||||
integrity, mRunsToCompletion ? nullptr : this,
|
||||
&isAlternate);
|
||||
&isAlternate, &isExplicitlyEnabled);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!isAlternate && !mRunsToCompletion) {
|
||||
if ((!isAlternate || isExplicitlyEnabled) && !mRunsToCompletion) {
|
||||
++mPendingSheetCount;
|
||||
mScriptLoader->AddParserBlockingScriptExecutionBlocker();
|
||||
}
|
||||
|
||||
@@ -5105,6 +5105,14 @@ nsContentUtils::TriggerLink(nsIContent *aContent, nsPresContext *aPresContext,
|
||||
fileName.SetIsVoid(true); // No actionable download attribute was found.
|
||||
}
|
||||
|
||||
// Sanitize fileNames containing control characters by replacing them with
|
||||
// underscores.
|
||||
if (!fileName.IsVoid()) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
fileName.ReplaceChar(char16_t(i), '_');
|
||||
}
|
||||
}
|
||||
|
||||
handler->OnLinkClick(aContent, aLinkURI,
|
||||
fileName.IsVoid() ? aTargetSpec.get() : EmptyString().get(),
|
||||
fileName, nullptr, nullptr, aIsTrusted, aContent->NodePrincipal());
|
||||
@@ -9835,4 +9843,18 @@ nsContentUtils::IsLocalRefURL(const nsString& aString)
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ uint32_t
|
||||
nsContentUtils::GetNodeDepth(nsINode* aNode)
|
||||
{
|
||||
uint32_t depth = 1;
|
||||
|
||||
MOZ_ASSERT(aNode, "Node shouldn't be null");
|
||||
|
||||
while ((aNode = aNode->GetParentNode())) {
|
||||
++depth;
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
@@ -2745,6 +2745,14 @@ public:
|
||||
static bool
|
||||
IsLocalRefURL(const nsString& aString);
|
||||
|
||||
/**
|
||||
* Returns the length of the parent-traversal path (in terms of the number of
|
||||
* nodes) to an unparented/root node from aNode. An unparented/root node is
|
||||
* considered to have a depth of 1, its children have a depth of 2, etc.
|
||||
* aNode is expected to be non-null.
|
||||
*/
|
||||
static uint32_t GetNodeDepth(nsINode* aNode);
|
||||
|
||||
private:
|
||||
static bool InitializeEventTable();
|
||||
|
||||
|
||||
+46
-1
@@ -1727,6 +1727,10 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
|
||||
cb.NoteXPCOMChild(mql);
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp->mResizeObserverController) {
|
||||
tmp->mResizeObserverController->Traverse(cb);
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
|
||||
@@ -1827,11 +1831,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
|
||||
l != &tmp->mDOMMediaQueryLists; ) {
|
||||
PRCList *next = PR_NEXT_LINK(l);
|
||||
MediaQueryList *mql = static_cast<MediaQueryList*>(l);
|
||||
mql->RemoveAllListeners();
|
||||
mql->Disconnect();
|
||||
l = next;
|
||||
}
|
||||
|
||||
tmp->mInUnlinkOrDeletion = false;
|
||||
|
||||
if (tmp->mResizeObserverController) {
|
||||
tmp->mResizeObserverController->Unlink();
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
nsresult
|
||||
@@ -3681,6 +3689,12 @@ nsDocument::DeleteShell()
|
||||
// objects for @font-face rules that came from the style set.
|
||||
RebuildUserFontSet();
|
||||
|
||||
if (mResizeObserverController) {
|
||||
// If the shell is going away, we need to remove any links to this document
|
||||
// from the observer.
|
||||
mResizeObserverController->DetachFromDocument();
|
||||
}
|
||||
|
||||
nsIPresShell* oldShell = mPresShell;
|
||||
mPresShell = nullptr;
|
||||
UpdateFrameRequestCallbackSchedulingState(oldShell);
|
||||
@@ -12105,6 +12119,24 @@ nsDocument::QuerySelectorAll(const nsAString& aSelector, nsIDOMNodeList **aRetur
|
||||
return nsINode::QuerySelectorAll(aSelector, aReturn);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::AddResizeObserver(ResizeObserver* aResizeObserver)
|
||||
{
|
||||
if (!mResizeObserverController) {
|
||||
mResizeObserverController = MakeUnique<ResizeObserverController>(this);
|
||||
}
|
||||
|
||||
mResizeObserverController->AddResizeObserver(aResizeObserver);
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::ScheduleResizeObserversNotification() const
|
||||
{
|
||||
if (mResizeObserverController) {
|
||||
mResizeObserverController->ScheduleNotification();
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDocument>
|
||||
nsIDocument::Constructor(const GlobalObject& aGlobal,
|
||||
ErrorResult& rv)
|
||||
@@ -12745,3 +12777,16 @@ nsIDocument::GetSelection(ErrorResult& aRv)
|
||||
|
||||
return nsGlobalWindow::Cast(window)->GetSelection(aRv);
|
||||
}
|
||||
|
||||
bool
|
||||
nsIDocument::ModuleScriptsEnabled()
|
||||
{
|
||||
static bool sEnabledForContent = false;
|
||||
static bool sCachedPref = false;
|
||||
if (!sCachedPref) {
|
||||
sCachedPref = true;
|
||||
Preferences::AddBoolVarCache(&sEnabledForContent, "dom.moduleScripts.enabled", false);
|
||||
}
|
||||
|
||||
return nsContentUtils::IsChromeDoc(this) || sEnabledForContent;
|
||||
}
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/PendingAnimationTracker.h"
|
||||
#include "mozilla/dom/DOMImplementation.h"
|
||||
#include "mozilla/dom/ResizeObserverController.h"
|
||||
#include "mozilla/dom/ScriptLoader.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "nsDataHashtable.h"
|
||||
@@ -1206,6 +1207,10 @@ public:
|
||||
|
||||
virtual void UnblockDOMContentLoaded() override;
|
||||
|
||||
void AddResizeObserver(mozilla::dom::ResizeObserver* aResizeObserver) override;
|
||||
|
||||
void ScheduleResizeObserversNotification() const override;
|
||||
|
||||
protected:
|
||||
friend class nsNodeUtils;
|
||||
friend class nsDocumentOnStack;
|
||||
@@ -1342,6 +1347,9 @@ protected:
|
||||
|
||||
nsTArray<nsIObserver*> mCharSetObservers;
|
||||
|
||||
mozilla::UniquePtr<mozilla::dom::ResizeObserverController>
|
||||
mResizeObserverController;
|
||||
|
||||
PLDHashTable *mSubDocuments;
|
||||
|
||||
// Array of owning references to all children
|
||||
|
||||
@@ -580,7 +580,6 @@ GK_ATOM(marginTop, "margin-top")
|
||||
GK_ATOM(marginheight, "marginheight")
|
||||
GK_ATOM(marginwidth, "marginwidth")
|
||||
GK_ATOM(mark, "mark")
|
||||
GK_ATOM(marquee, "marquee")
|
||||
GK_ATOM(match, "match")
|
||||
GK_ATOM(max, "max")
|
||||
GK_ATOM(maxheight, "maxheight")
|
||||
|
||||
@@ -956,7 +956,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(DialogValueHolder)
|
||||
class nsOuterWindowProxy : public js::Wrapper
|
||||
{
|
||||
public:
|
||||
constexpr nsOuterWindowProxy() : js::Wrapper(0) { }
|
||||
nsOuterWindowProxy() : js::Wrapper(0) { }
|
||||
|
||||
virtual bool finalizeInBackground(const JS::Value& priv) const override {
|
||||
return false;
|
||||
@@ -1407,7 +1407,7 @@ nsOuterWindowProxy::singleton;
|
||||
class nsChromeOuterWindowProxy : public nsOuterWindowProxy
|
||||
{
|
||||
public:
|
||||
constexpr nsChromeOuterWindowProxy() : nsOuterWindowProxy() { }
|
||||
nsChromeOuterWindowProxy() : nsOuterWindowProxy() { }
|
||||
|
||||
virtual const char *className(JSContext *cx, JS::Handle<JSObject*> wrapper) const override;
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ class ProcessingInstruction;
|
||||
class Promise;
|
||||
class Selection;
|
||||
class ScriptLoader;
|
||||
class ResizeObserver;
|
||||
class StyleSheetList;
|
||||
class SVGDocument;
|
||||
class SVGSVGElement;
|
||||
@@ -2872,6 +2873,12 @@ public:
|
||||
virtual void ScheduleIntersectionObserverNotification() = 0;
|
||||
virtual void NotifyIntersectionObservers() = 0;
|
||||
|
||||
bool ModuleScriptsEnabled();
|
||||
|
||||
virtual void AddResizeObserver(mozilla::dom::ResizeObserver* aResizeObserver) = 0;
|
||||
|
||||
virtual void ScheduleResizeObserversNotification() const = 0;
|
||||
|
||||
protected:
|
||||
bool GetUseCounter(mozilla::UseCounter aUseCounter)
|
||||
{
|
||||
|
||||
@@ -933,8 +933,12 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
|
||||
MOZ_ASSERT(!req, "Shouldn't have non-null request here");
|
||||
// If we don't have a current URI, we might as well store this URI so people
|
||||
// know what we tried (and failed) to load.
|
||||
if (!mCurrentRequest)
|
||||
if (!mCurrentRequest) {
|
||||
mCurrentURI = aNewURI;
|
||||
if (mImageBlockingStatus == nsIContentPolicy::ACCEPT) {
|
||||
mImageBlockingStatus = nsIContentPolicy::REJECT_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
FireEvent(NS_LITERAL_STRING("error"));
|
||||
FireEvent(NS_LITERAL_STRING("loadend"));
|
||||
|
||||
@@ -1161,7 +1161,7 @@ TimeUntilNow(TimeStamp start)
|
||||
|
||||
struct CycleCollectorStats
|
||||
{
|
||||
constexpr CycleCollectorStats() :
|
||||
CycleCollectorStats() :
|
||||
mMaxGCDuration(0), mRanSyncForgetSkippable(false), mSuspected(0),
|
||||
mMaxSkippableDuration(0), mMaxSliceTime(0), mMaxSliceTimeSinceClear(0),
|
||||
mTotalSliceTime(0), mAnyLockedOut(false), mExtraForgetSkippableCalls(0),
|
||||
|
||||
@@ -313,7 +313,8 @@ nsJSUtils::ModuleInstantiate(JSContext* aCx, JS::Handle<JSObject*> aModule)
|
||||
|
||||
MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(nsContentUtils::IsInMicroTask());
|
||||
MOZ_ASSERT(CycleCollectedJSContext::Get() &&
|
||||
CycleCollectedJSContext::Get()->MicroTaskLevel());
|
||||
|
||||
NS_ENSURE_TRUE(xpc::Scriptability::Get(aModule).Allowed(), NS_OK);
|
||||
|
||||
|
||||
@@ -393,8 +393,9 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
nsAutoString title, type, media;
|
||||
bool isScoped;
|
||||
bool isAlternate;
|
||||
bool isExplicitlyEnabled;
|
||||
|
||||
GetStyleSheetInfo(title, type, media, &isScoped, &isAlternate);
|
||||
GetStyleSheetInfo(title, type, media, &isScoped, &isAlternate, &isExplicitlyEnabled);
|
||||
|
||||
if (!type.LowerCaseEqualsLiteral("text/css")) {
|
||||
return NS_OK;
|
||||
@@ -425,7 +426,7 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
// Parse the style sheet.
|
||||
rv = doc->CSSLoader()->
|
||||
LoadInlineStyle(thisContent, text, mLineNumber, title, media,
|
||||
scopeElement, aObserver, &doneLoading, &isAlternate);
|
||||
scopeElement, aObserver, &doneLoading, &isAlternate, &isExplicitlyEnabled);
|
||||
}
|
||||
else {
|
||||
nsAutoString integrity;
|
||||
@@ -452,13 +453,14 @@ nsStyleLinkElement::DoUpdateStyleSheet(nsIDocument* aOldDocument,
|
||||
rv = doc->CSSLoader()->
|
||||
LoadStyleLink(thisContent, clonedURI, title, media, isAlternate,
|
||||
GetCORSMode(), referrerPolicy, integrity,
|
||||
aObserver, &isAlternate);
|
||||
aObserver, &isAlternate, &isExplicitlyEnabled);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Don't propagate LoadStyleLink() errors further than this, since some
|
||||
// consumers (e.g. nsXMLContentSink) will completely abort on innocuous
|
||||
// things like a stylesheet load being blocked by the security system.
|
||||
doneLoading = true;
|
||||
isAlternate = false;
|
||||
isExplicitlyEnabled = false;
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,8 @@ protected:
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate) = 0;
|
||||
bool* aIsAlternate,
|
||||
bool* aIsExplicitlyEnabled) = 0;
|
||||
|
||||
virtual mozilla::CORSMode GetCORSMode() const
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840098
|
||||
<div id="content" style="display: none">
|
||||
<div id="foo"></div>
|
||||
</div>
|
||||
<marquee id="m">Hello</marquee>
|
||||
<div id="m">Hello</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@
|
||||
<div id="a" contenteditable><span id="test1">abc, abc, abc</span><br>
|
||||
<span id="test2" style="color: blue;">abc, abc, abc</span><br>
|
||||
<textarea id="test3">abc</textarea><input id="test4" value="abcdef"><br><br>
|
||||
<marquee>marquee</marquee>
|
||||
<div>div</div>
|
||||
</div>
|
||||
<input id="test5" value="The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well. Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. She took down a jar from one of the shelves as she passed; it was labelled `ORANGE MARMALADE', but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it." type="text">
|
||||
<input id="test6" type="number" style="width:150px; height:57px;" value="31415"><br>
|
||||
|
||||
@@ -1,913 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=641821
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 641821</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body onload="runTest()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641821">Mozilla Bug 641821</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 641821 **/
|
||||
|
||||
SimpleTest.requestFlakyTimeout("requestFlakyTimeout is silly. (But make sure marquee has time to initialize itself.)");
|
||||
|
||||
var div = document.createElement("div");
|
||||
|
||||
var M;
|
||||
if ("MozMutationObserver" in window) {
|
||||
M = window.MozMutationObserver;
|
||||
} else if ("WebKitMutationObserver" in window) {
|
||||
M = window.WebKitMutationObserver;
|
||||
} else {
|
||||
M = window.MutationObserver;
|
||||
}
|
||||
|
||||
function log(str) {
|
||||
var d = document.createElement("div");
|
||||
d.textContent = str;
|
||||
if (str.indexOf("PASSED") >= 0) {
|
||||
d.setAttribute("style", "color: green;");
|
||||
} else {
|
||||
d.setAttribute("style", "color: red;");
|
||||
}
|
||||
document.getElementById("log").appendChild(d);
|
||||
}
|
||||
|
||||
// Some helper functions so that this test runs also outside mochitest.
|
||||
if (!("ok" in window)) {
|
||||
window.ok = function(val, str) {
|
||||
log(str + (val ? " PASSED\n" : " FAILED\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!("is" in window)) {
|
||||
window.is = function(val, refVal, str) {
|
||||
log(str + (val == refVal? " PASSED " : " FAILED ") +
|
||||
(val != refVal ? "expected " + refVal + " got " + val + "\n" : "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!("isnot" in window)) {
|
||||
window.isnot = function(val, refVal, str) {
|
||||
log(str + (val != refVal? " PASSED " : " FAILED ") +
|
||||
(val == refVal ? "Didn't expect " + refVal + "\n" : "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
if (!("SimpleTest" in window)) {
|
||||
window.SimpleTest =
|
||||
{
|
||||
finish: function() {
|
||||
document.getElementById("log").appendChild(document.createTextNode("DONE"));
|
||||
},
|
||||
waitForExplicitFinish: function() {}
|
||||
}
|
||||
}
|
||||
|
||||
function then(thenFn) {
|
||||
setTimeout(function() {
|
||||
if (thenFn) {
|
||||
setTimeout(thenFn, 0);
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
var m;
|
||||
var m2;
|
||||
var m3;
|
||||
var m4;
|
||||
|
||||
// Checks basic parameter validation and normal 'this' handling.
|
||||
// Tests also basic attribute handling.
|
||||
function runTest() {
|
||||
m = new M(function(){});
|
||||
ok(m, "MutationObserver supported");
|
||||
|
||||
var e = null;
|
||||
try {
|
||||
m.observe(document, {});
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(e, "Should have thrown an exception");
|
||||
is(e.name, "TypeError", "Should have thrown TypeError");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document, { childList: true, attributeOldValue: true });
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(!e, "Shouldn't have thrown an exception");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document, { childList: true, attributeFilter: ["foo"] });
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(!e, "Shouldn't have thrown an exception");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document, { childList: true, characterDataOldValue: true });
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(!e, "Shouldn't have thrown an exception");
|
||||
|
||||
e = null;
|
||||
try {
|
||||
m.observe(document);
|
||||
} catch (ex) {
|
||||
e = ex;
|
||||
}
|
||||
ok(e, "Should have thrown an exception");
|
||||
|
||||
m = new M(function(records, observer) {
|
||||
is(observer, m, "2nd parameter should be the mutation observer");
|
||||
is(observer, this, "2nd parameter should be 'this'");
|
||||
is(records.length, 1, "Should have one record.");
|
||||
is(records[0].type, "attributes", "Should have got attributes record");
|
||||
is(records[0].target, div, "Should have got div as target");
|
||||
is(records[0].attributeName, "foo", "Should have got record about foo attribute");
|
||||
observer.disconnect();
|
||||
then(testThisBind);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { attributes: true, attributeFilter: ["foo"] });
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributes, true);
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeFilter.length, 1)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeFilter[0], "foo")
|
||||
div.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
// 'this' handling when fn.bind() is used.
|
||||
function testThisBind() {
|
||||
var child = div.appendChild(document.createElement("div"));
|
||||
var gchild = child.appendChild(document.createElement("div"));
|
||||
m = new M((function(records, observer) {
|
||||
is(observer, m, "2nd parameter should be the mutation observer");
|
||||
isnot(observer, this, "2nd parameter should be 'this'");
|
||||
is(records.length, 3, "Should have one record.");
|
||||
is(records[0].type, "attributes", "Should have got attributes record");
|
||||
is(records[0].target, div, "Should have got div as target");
|
||||
is(records[0].attributeName, "foo", "Should have got record about foo attribute");
|
||||
is(records[0].oldValue, "bar", "oldValue should be bar");
|
||||
is(records[1].type, "attributes", "Should have got attributes record");
|
||||
is(records[1].target, div, "Should have got div as target");
|
||||
is(records[1].attributeName, "foo", "Should have got record about foo attribute");
|
||||
is(records[1].oldValue, "bar2", "oldValue should be bar2");
|
||||
is(records[2].type, "attributes", "Should have got attributes record");
|
||||
is(records[2].target, gchild, "Should have got div as target");
|
||||
is(records[2].attributeName, "foo", "Should have got record about foo attribute");
|
||||
is(records[2].oldValue, null, "oldValue should be bar2");
|
||||
observer.disconnect();
|
||||
then(testCharacterData);
|
||||
m = null;
|
||||
}).bind(window));
|
||||
m.observe(div, { attributes: true, attributeOldValue: true, subtree: true });
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributes, true)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].attributeOldValue, true)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[0].getObservingInfo()[0].subtree, true)
|
||||
div.setAttribute("foo", "bar2");
|
||||
div.removeAttribute("foo");
|
||||
div.removeChild(child);
|
||||
child.removeChild(gchild);
|
||||
div.appendChild(gchild);
|
||||
div.removeChild(gchild);
|
||||
gchild.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
function testCharacterData() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "characterData", "Should have got characterData");
|
||||
is(records[0].oldValue, null, "Shouldn't have got oldData");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
});
|
||||
m2 = new M(function(records, observer) {
|
||||
is(records[0].type, "characterData", "Should have got characterData");
|
||||
is(records[0].oldValue, "foo", "Should have got oldData");
|
||||
observer.disconnect();
|
||||
m2 = null;
|
||||
});
|
||||
m3 = new M(function(records, observer) {
|
||||
ok(false, "This should not be called!");
|
||||
observer.disconnect();
|
||||
m3 = null;
|
||||
});
|
||||
m4 = new M(function(records, observer) {
|
||||
is(records[0].oldValue, null, "Shouldn't have got oldData");
|
||||
observer.disconnect();
|
||||
m3.disconnect();
|
||||
m3 = null;
|
||||
then(testChildList);
|
||||
m4 = null;
|
||||
});
|
||||
|
||||
div.appendChild(document.createTextNode("foo"));
|
||||
m.observe(div, { characterData: true, subtree: true });
|
||||
m2.observe(div, { characterData: true, characterDataOldValue: true, subtree: true});
|
||||
// If observing the same node twice, only the latter option should apply.
|
||||
m3.observe(div, { characterData: true, subtree: true });
|
||||
m3.observe(div, { characterData: true, subtree: false });
|
||||
m4.observe(div.firstChild, { characterData: true, subtree: false });
|
||||
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers().length, 3)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[2].getObservingInfo()[0].characterData, true)
|
||||
is(SpecialPowers.wrap(div).getBoundMutationObservers()[2].getObservingInfo()[0].subtree, false)
|
||||
|
||||
div.firstChild.data = "bar";
|
||||
}
|
||||
|
||||
function testChildList() {
|
||||
var fc = div.firstChild;
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "childList", "Should have got childList");
|
||||
is(records[0].addedNodes.length, 0, "Shouldn't have got addedNodes");
|
||||
is(records[0].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[0].removedNodes[0], fc, "Should have removed a text node");
|
||||
observer.disconnect();
|
||||
then(testChildList2);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true});
|
||||
div.removeChild(div.firstChild);
|
||||
}
|
||||
|
||||
function testChildList2() {
|
||||
div.innerHTML = "<span>1</span><span>2</span>";
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "childList", "Should have got childList");
|
||||
is(records[0].removedNodes.length, 2, "Should have got removedNodes");
|
||||
is(records[0].addedNodes.length, 1, "Should have got addedNodes");
|
||||
observer.disconnect();
|
||||
then(testChildList3);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true });
|
||||
div.innerHTML = "<span><span>foo</span></span>";
|
||||
}
|
||||
|
||||
function testChildList3() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records[0].type, "childList", "Should have got childList");
|
||||
is(records[0].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[0].addedNodes.length, 1, "Should have got addedNodes");
|
||||
observer.disconnect();
|
||||
then(testChildList4);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true });
|
||||
div.textContent = "hello";
|
||||
}
|
||||
|
||||
function testChildList4() {
|
||||
div.textContent = null;
|
||||
var df = document.createDocumentFragment();
|
||||
var t1 = df.appendChild(document.createTextNode("Hello "));
|
||||
var t2 = df.appendChild(document.createTextNode("world!"));
|
||||
var s1 = div.appendChild(document.createElement("span"));
|
||||
s1.textContent = "foo";
|
||||
var s2 = div.appendChild(document.createElement("span"));
|
||||
function callback(records, observer) {
|
||||
is(records.length, 3, "Should have got one record for removing nodes from document fragment and one record for adding them to div");
|
||||
is(records[0].removedNodes.length, 2, "Should have got removedNodes");
|
||||
is(records[0].removedNodes[0], t1, "Should be the 1st textnode");
|
||||
is(records[0].removedNodes[1], t2, "Should be the 2nd textnode");
|
||||
is(records[1].addedNodes.length, 2, "Should have got addedNodes");
|
||||
is(records[1].addedNodes[0], t1, "Should be the 1st textnode");
|
||||
is(records[1].addedNodes[1], t2, "Should be the 2nd textnode");
|
||||
is(records[1].previousSibling, s1, "Should have previousSibling");
|
||||
is(records[1].nextSibling, s2, "Should have nextSibling");
|
||||
is(records[2].type, "characterData", "3rd record should be characterData");
|
||||
is(records[2].target, t1, "target should be the textnode");
|
||||
is(records[2].oldValue, "Hello ", "oldValue was 'Hello '");
|
||||
observer.disconnect();
|
||||
then(testChildList5);
|
||||
m = null;
|
||||
};
|
||||
m = new M(callback);
|
||||
m.observe(df, { childList: true, characterData: true, characterDataOldValue: true, subtree: true });
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].childList, true)
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].characterData, true)
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].characterDataOldValue, true)
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo()[0].subtree, true)
|
||||
ok(SpecialPowers.compare(SpecialPowers.wrap(df).getBoundMutationObservers()[0].mutationCallback, callback))
|
||||
m.observe(div, { childList: true });
|
||||
is(SpecialPowers.wrap(df).getBoundMutationObservers()[0].getObservingInfo().length, 2)
|
||||
|
||||
// Make sure transient observers aren't leaked.
|
||||
var leakTest = new M(function(){});
|
||||
leakTest.observe(div, { characterData: true, subtree: true });
|
||||
|
||||
div.insertBefore(df, s2);
|
||||
s1.firstChild.data = "bar"; // This should *not* create a record.
|
||||
t1.data = "Hello the whole "; // This should create a record.
|
||||
}
|
||||
|
||||
function testChildList5() {
|
||||
div.textContent = null;
|
||||
var c1 = div.appendChild(document.createElement("div"));
|
||||
var c2 = document.createElement("div");
|
||||
var div2 = document.createElement("div");
|
||||
var c3 = div2.appendChild(document.createElement("div"));
|
||||
var c4 = document.createElement("div");
|
||||
var c5 = document.createElement("div");
|
||||
var df = document.createDocumentFragment();
|
||||
var emptyDF = document.createDocumentFragment();
|
||||
var dfc1 = df.appendChild(document.createElement("div"));
|
||||
var dfc2 = df.appendChild(document.createElement("div"));
|
||||
var dfc3 = df.appendChild(document.createElement("div"));
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 6 , "");
|
||||
is(records[0].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[0].removedNodes[0], c1, "");
|
||||
is(records[0].addedNodes.length, 1, "Should have got addedNodes");
|
||||
is(records[0].addedNodes[0], c2, "");
|
||||
is(records[0].previousSibling, null, "");
|
||||
is(records[0].nextSibling, null, "");
|
||||
is(records[1].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[1].removedNodes[0], c3, "");
|
||||
is(records[1].addedNodes.length, 0, "Shouldn't have got addedNodes");
|
||||
is(records[1].previousSibling, null, "");
|
||||
is(records[1].nextSibling, null, "");
|
||||
is(records[2].removedNodes.length, 1, "Should have got removedNodes");
|
||||
is(records[2].removedNodes[0], c2, "");
|
||||
is(records[2].addedNodes.length, 1, "Should have got addedNodes");
|
||||
is(records[2].addedNodes[0], c3, "");
|
||||
is(records[2].previousSibling, null, "");
|
||||
is(records[2].nextSibling, null, "");
|
||||
// Check document fragment handling
|
||||
is(records[5].removedNodes.length, 1, "");
|
||||
is(records[5].removedNodes[0], c4, "");
|
||||
is(records[5].addedNodes.length, 3, "");
|
||||
is(records[5].addedNodes[0], dfc1, "");
|
||||
is(records[5].addedNodes[1], dfc2, "");
|
||||
is(records[5].addedNodes[2], dfc3, "");
|
||||
is(records[5].previousSibling, c3, "");
|
||||
is(records[5].nextSibling, c5, "");
|
||||
observer.disconnect();
|
||||
then(testAdoptNode);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true, subtree: true });
|
||||
m.observe(div2, { childList: true, subtree: true });
|
||||
div.replaceChild(c2, c1);
|
||||
div.replaceChild(c3, c2);
|
||||
div.appendChild(c4);
|
||||
div.appendChild(c5);
|
||||
div.replaceChild(df, c4);
|
||||
div.appendChild(emptyDF); // empty document shouldn't cause mutation records
|
||||
}
|
||||
|
||||
function testAdoptNode() {
|
||||
var d1 = document.implementation.createHTMLDocument(null);
|
||||
var d2 = document.implementation.createHTMLDocument(null);
|
||||
var addedNode;
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 3, "Should have 2 records");
|
||||
is(records[0].target.ownerDocument, d1, "ownerDocument should be the initial document")
|
||||
is(records[1].target.ownerDocument, d2, "ownerDocument should be the new document");
|
||||
is(records[2].type, "attributes", "Should have got attribute mutation")
|
||||
is(records[2].attributeName, "foo", "Should have got foo attribute mutation")
|
||||
observer.disconnect();
|
||||
then(testOuterHTML);
|
||||
m = null;
|
||||
});
|
||||
m.observe(d1, { childList: true, subtree: true, attributes: true });
|
||||
d2.body.appendChild(d1.body);
|
||||
addedNode = d2.body.lastChild.appendChild(d2.createElement("div"));
|
||||
addedNode.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
function testOuterHTML() {
|
||||
var doc = document.implementation.createHTMLDocument(null);
|
||||
var d1 = doc.body.appendChild(document.createElement("div"));
|
||||
var d2 = doc.body.appendChild(document.createElement("div"));
|
||||
var d3 = doc.body.appendChild(document.createElement("div"));
|
||||
var d4 = doc.body.appendChild(document.createElement("div"));
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 4, "Should have 1 record");
|
||||
is(records[0].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[0].addedNodes.length, 2, "Should have 2 added nodes");
|
||||
is(records[0].previousSibling, null, "");
|
||||
is(records[0].nextSibling, d2, "");
|
||||
is(records[1].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[1].addedNodes.length, 2, "Should have 2 added nodes");
|
||||
is(records[1].previousSibling, records[0].addedNodes[1], "");
|
||||
is(records[1].nextSibling, d3, "");
|
||||
is(records[2].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[2].addedNodes.length, 2, "Should have 2 added nodes");
|
||||
is(records[2].previousSibling, records[1].addedNodes[1], "");
|
||||
is(records[2].nextSibling, d4, "");
|
||||
is(records[3].removedNodes.length, 1, "Should have 1 removed nodes");
|
||||
is(records[3].addedNodes.length, 0);
|
||||
is(records[3].previousSibling, records[2].addedNodes[1], "");
|
||||
is(records[3].nextSibling, null, "");
|
||||
observer.disconnect();
|
||||
then(testInsertAdjacentHTML);
|
||||
m = null;
|
||||
});
|
||||
m.observe(doc, { childList: true, subtree: true });
|
||||
d1.outerHTML = "<div>1</div><div>1</div>";
|
||||
d2.outerHTML = "<div>2</div><div>2</div>";
|
||||
d3.outerHTML = "<div>3</div><div>3</div>";
|
||||
d4.outerHTML = "";
|
||||
}
|
||||
|
||||
function testInsertAdjacentHTML() {
|
||||
var doc = document.implementation.createHTMLDocument(null);
|
||||
var d1 = doc.body.appendChild(document.createElement("div"));
|
||||
var d2 = doc.body.appendChild(document.createElement("div"));
|
||||
var d3 = doc.body.appendChild(document.createElement("div"));
|
||||
var d4 = doc.body.appendChild(document.createElement("div"));
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 4, "");
|
||||
is(records[0].target, doc.body, "");
|
||||
is(records[0].previousSibling, null, "");
|
||||
is(records[0].nextSibling, d1, "");
|
||||
is(records[1].target, d2, "");
|
||||
is(records[1].previousSibling, null, "");
|
||||
is(records[1].nextSibling, null, "");
|
||||
is(records[2].target, d3, "");
|
||||
is(records[2].previousSibling, null, "");
|
||||
is(records[2].nextSibling, null, "");
|
||||
is(records[3].target, doc.body, "");
|
||||
is(records[3].previousSibling, d4, "");
|
||||
is(records[3].nextSibling, null, "");
|
||||
observer.disconnect();
|
||||
then(testSyncXHR);
|
||||
m = null;
|
||||
});
|
||||
m.observe(doc, { childList: true, subtree: true });
|
||||
d1.insertAdjacentHTML("beforebegin", "<div></div><div></div>");
|
||||
d2.insertAdjacentHTML("afterbegin", "<div></div><div></div>");
|
||||
d3.insertAdjacentHTML("beforeend", "<div></div><div></div>");
|
||||
d4.insertAdjacentHTML("afterend", "<div></div><div></div>");
|
||||
}
|
||||
|
||||
|
||||
var callbackHandled = false;
|
||||
|
||||
function testSyncXHR() {
|
||||
div.textContent = null;
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "");
|
||||
is(records[0].addedNodes.length, 1, "");
|
||||
callbackHandled = true;
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true, subtree: true });
|
||||
div.innerHTML = "<div>hello</div>";
|
||||
var x = new XMLHttpRequest();
|
||||
x.open("GET", window.location, false);
|
||||
x.send();
|
||||
ok(!callbackHandled, "Shouldn't have called the mutation callback!");
|
||||
setTimeout(testSyncXHR2, 0);
|
||||
}
|
||||
|
||||
function testSyncXHR2() {
|
||||
ok(callbackHandled, "Should have called the mutation callback!");
|
||||
then(testTakeRecords);
|
||||
}
|
||||
|
||||
function testTakeRecords() {
|
||||
var s = "<span>1</span><span>2</span>";
|
||||
div.innerHTML = s;
|
||||
var takenRecords;
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 3, "Should have got 3 records");
|
||||
|
||||
is(records[0].type, "attributes", "Should have got attributes");
|
||||
is(records[0].attributeName, "foo", "");
|
||||
is(records[0].attributeNamespace, null, "");
|
||||
is(records[0].prevValue, null, "");
|
||||
is(records[1].type, "childList", "Should have got childList");
|
||||
is(records[1].removedNodes.length, 2, "Should have got removedNodes");
|
||||
is(records[1].addedNodes.length, 2, "Should have got addedNodes");
|
||||
is(records[2].type, "attributes", "Should have got attributes");
|
||||
is(records[2].attributeName, "foo", "");
|
||||
|
||||
is(records.length, takenRecords.length, "Should have had similar mutations");
|
||||
is(records[0].type, takenRecords[0].type, "Should have had similar mutations");
|
||||
is(records[1].type, takenRecords[1].type, "Should have had similar mutations");
|
||||
is(records[2].type, takenRecords[2].type, "Should have had similar mutations");
|
||||
|
||||
is(records[1].removedNodes.length, takenRecords[1].removedNodes.length, "Should have had similar mutations");
|
||||
is(records[1].addedNodes.length, takenRecords[1].addedNodes.length, "Should have had similar mutations");
|
||||
|
||||
is(m.takeRecords().length, 0, "Shouldn't have any records");
|
||||
observer.disconnect();
|
||||
then(testMutationObserverAndEvents);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { childList: true, attributes: true });
|
||||
div.setAttribute("foo", "bar");
|
||||
div.innerHTML = s;
|
||||
div.removeAttribute("foo");
|
||||
takenRecords = m.takeRecords();
|
||||
div.setAttribute("foo", "bar");
|
||||
div.innerHTML = s;
|
||||
div.removeAttribute("foo");
|
||||
}
|
||||
|
||||
function testTakeRecords() {
|
||||
function mutationListener(e) {
|
||||
++mutationEventCount;
|
||||
is(e.attrChange, MutationEvent.ADDITION, "unexpected change");
|
||||
}
|
||||
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 2, "Should have got 2 records");
|
||||
is(records[0].type, "attributes", "Should have got attributes");
|
||||
is(records[0].attributeName, "foo", "");
|
||||
is(records[0].oldValue, null, "");
|
||||
is(records[1].type, "attributes", "Should have got attributes");
|
||||
is(records[1].attributeName, "foo", "");
|
||||
is(records[1].oldValue, "bar", "");
|
||||
observer.disconnect();
|
||||
div.removeEventListener("DOMAttrModified", mutationListener);
|
||||
then(testExpandos);
|
||||
m = null;
|
||||
});
|
||||
m.observe(div, { attributes: true, attributeOldValue: true });
|
||||
// Note, [0] points to a mutation observer which is there for a leak test!
|
||||
ok(SpecialPowers.compare(SpecialPowers.wrap(div).getBoundMutationObservers()[1], m));
|
||||
var mutationEventCount = 0;
|
||||
div.addEventListener("DOMAttrModified", mutationListener);
|
||||
div.setAttribute("foo", "bar");
|
||||
div.setAttribute("foo", "bar");
|
||||
is(mutationEventCount, 1, "Should have got only one mutation event!");
|
||||
}
|
||||
|
||||
function testExpandos() {
|
||||
var m2 = new M(function(records, observer) {
|
||||
is(observer.expandoProperty, true);
|
||||
observer.disconnect();
|
||||
then(testOutsideShadowDOM);
|
||||
});
|
||||
m2.expandoProperty = true;
|
||||
m2.observe(div, { attributes: true });
|
||||
m2 = null;
|
||||
if (SpecialPowers) {
|
||||
// Run GC several times to see if the expando property disappears.
|
||||
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.gc();
|
||||
}
|
||||
div.setAttribute("foo", "bar2");
|
||||
}
|
||||
|
||||
function testOutsideShadowDOM() {
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 1);
|
||||
is(records[0].type, "attributes", "Should have got attributes");
|
||||
observer.disconnect();
|
||||
then(testInsideShadowDOM);
|
||||
});
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
})
|
||||
var sr = div.createShadowRoot();
|
||||
sr.innerHTML = "<div" + ">text</" + "div>";
|
||||
sr.firstChild.setAttribute("foo", "bar");
|
||||
sr.firstChild.firstChild.data = "text2";
|
||||
sr.firstChild.appendChild(document.createElement("div"));
|
||||
div.setAttribute("foo", "bar");
|
||||
}
|
||||
|
||||
function testInsideShadowDOM() {
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 4);
|
||||
is(records[0].type, "childList");
|
||||
is(records[1].type, "attributes");
|
||||
is(records[2].type, "characterData");
|
||||
is(records[3].type, "childList");
|
||||
observer.disconnect();
|
||||
then(testMarquee);
|
||||
});
|
||||
var sr = div.createShadowRoot();
|
||||
m.observe(sr, {
|
||||
attributes: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
sr.innerHTML = "<div" + ">text</" + "div>";
|
||||
sr.firstChild.setAttribute("foo", "bar");
|
||||
sr.firstChild.firstChild.data = "text2";
|
||||
sr.firstChild.appendChild(document.createElement("div"));
|
||||
div.setAttribute("foo", "bar2");
|
||||
|
||||
}
|
||||
|
||||
function testMarquee() {
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 1);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].attributeName, "ok");
|
||||
is(records[0].oldValue, null);
|
||||
observer.disconnect();
|
||||
then(testStyleCreate);
|
||||
});
|
||||
var marquee = document.createElement("marquee");
|
||||
m.observe(marquee, {
|
||||
attributes: true,
|
||||
attributeOldValue: true,
|
||||
childList: true,
|
||||
characterData: true,
|
||||
subtree: true
|
||||
});
|
||||
document.body.appendChild(marquee);
|
||||
setTimeout(function() {marquee.setAttribute("ok", "ok")}, 500);
|
||||
}
|
||||
|
||||
function testStyleCreate() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "style", "record.attributeName");
|
||||
is(records[0].oldValue, null, "record.oldValue");
|
||||
isnot(div.getAttribute("style"), null, "style attribute after creation");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("style");
|
||||
then(testStyleModify);
|
||||
});
|
||||
m.observe(div, { attributes: true, attributeOldValue: true });
|
||||
is(div.getAttribute("style"), null, "style attribute before creation");
|
||||
div.style.color = "blue";
|
||||
}
|
||||
|
||||
function testStyleModify() {
|
||||
div.style.color = "yellow";
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "style", "record.attributeName");
|
||||
isnot(div.getAttribute("style"), null, "style attribute after modification");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("style");
|
||||
then(testStyleRead);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
isnot(div.getAttribute("style"), null, "style attribute before modification");
|
||||
div.style.color = "blue";
|
||||
}
|
||||
|
||||
function testStyleRead() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "data-test", "record.attributeName");
|
||||
is(div.getAttribute("style"), null, "style attribute after read");
|
||||
observer.disconnect();
|
||||
div.removeAttribute("data-test");
|
||||
m = null;
|
||||
then(testStyleRemoveProperty);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
is(div.getAttribute("style"), null, "style attribute before read");
|
||||
var value = div.style.color; // shouldn't generate any mutation records
|
||||
div.setAttribute("data-test", "a");
|
||||
}
|
||||
|
||||
function testStyleRemoveProperty() {
|
||||
div.style.color = "blue";
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "style", "record.attributeName");
|
||||
isnot(div.getAttribute("style"), null, "style attribute after successful removeProperty");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("style");
|
||||
then(testStyleRemoveProperty2);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
isnot(div.getAttribute("style"), null, "style attribute before successful removeProperty");
|
||||
div.style.removeProperty("color");
|
||||
}
|
||||
|
||||
function testStyleRemoveProperty2() {
|
||||
m = new M(function(records, observer) {
|
||||
is(records.length, 1, "number of records");
|
||||
is(records[0].type, "attributes", "record.type");
|
||||
is(records[0].attributeName, "data-test", "record.attributeName");
|
||||
is(div.getAttribute("style"), null, "style attribute after unsuccessful removeProperty");
|
||||
observer.disconnect();
|
||||
m = null;
|
||||
div.removeAttribute("data-test");
|
||||
then(testAttributeRecordMerging1);
|
||||
});
|
||||
m.observe(div, { attributes: true });
|
||||
is(div.getAttribute("style"), null, "style attribute before unsuccessful removeProperty");
|
||||
div.style.removeProperty("color"); // shouldn't generate any mutation records
|
||||
div.setAttribute("data-test", "a");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging1() {
|
||||
ok(true, "testAttributeRecordMerging1");
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 2);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, null);
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, null);
|
||||
observer.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testAttributeRecordMerging2);
|
||||
});
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging2() {
|
||||
ok(true, "testAttributeRecordMerging2");
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 2);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, "initial");
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, "initial");
|
||||
observer.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testAttributeRecordMerging3);
|
||||
});
|
||||
|
||||
div.setAttribute("foo", "initial");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "initial");
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
attributeOldValue: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging3() {
|
||||
ok(true, "testAttributeRecordMerging3");
|
||||
var m = new M(function(records, observer) {
|
||||
is(records.length, 4);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, "initial");
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, "initial");
|
||||
|
||||
is(records[2].type, "attributes");
|
||||
is(records[2].target, div);
|
||||
is(records[2].attributeName, "foo");
|
||||
is(records[2].attributeNamespace, null);
|
||||
is(records[2].oldValue, "bar_1");
|
||||
|
||||
is(records[3].type, "attributes");
|
||||
is(records[3].target, div.firstChild);
|
||||
is(records[3].attributeName, "foo");
|
||||
is(records[3].attributeNamespace, null);
|
||||
is(records[3].oldValue, "bar_1");
|
||||
|
||||
observer.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testAttributeRecordMerging4);
|
||||
});
|
||||
|
||||
div.setAttribute("foo", "initial");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "initial");
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
attributeOldValue: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
// No merging should happen.
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
}
|
||||
|
||||
function testAttributeRecordMerging4() {
|
||||
ok(true, "testAttributeRecordMerging4");
|
||||
var m = new M(function(records, observer) {
|
||||
});
|
||||
|
||||
div.setAttribute("foo", "initial");
|
||||
div.innerHTML = "<div></div>";
|
||||
div.firstChild.setAttribute("foo", "initial");
|
||||
m.observe(div, {
|
||||
attributes: true,
|
||||
subtree: true,
|
||||
attributeOldValue: true
|
||||
});
|
||||
SpecialPowers.wrap(m).mergeAttributeRecords = true;
|
||||
|
||||
div.setAttribute("foo", "bar_1");
|
||||
div.setAttribute("foo", "bar_2");
|
||||
div.firstChild.setAttribute("foo", "bar_1");
|
||||
div.firstChild.setAttribute("foo", "bar_2");
|
||||
|
||||
var records = m.takeRecords();
|
||||
|
||||
is(records.length, 2);
|
||||
is(records[0].type, "attributes");
|
||||
is(records[0].target, div);
|
||||
is(records[0].attributeName, "foo");
|
||||
is(records[0].attributeNamespace, null);
|
||||
is(records[0].oldValue, "initial");
|
||||
|
||||
is(records[1].type, "attributes");
|
||||
is(records[1].target, div.firstChild);
|
||||
is(records[1].attributeName, "foo");
|
||||
is(records[1].attributeNamespace, null);
|
||||
is(records[1].oldValue, "initial");
|
||||
m.disconnect();
|
||||
div.innerHTML = "";
|
||||
div.removeAttribute("foo");
|
||||
then(testChromeOnly);
|
||||
}
|
||||
|
||||
function testChromeOnly() {
|
||||
// Content can't access nativeAnonymousChildList
|
||||
try {
|
||||
var mo = new M(function(records, observer) { });
|
||||
mo.observe(div, { nativeAnonymousChildList: true });
|
||||
ok(false, "Should have thrown when trying to observe with chrome-only init");
|
||||
} catch (e) {
|
||||
ok(true, "Throws when trying to observe with chrome-only init");
|
||||
}
|
||||
|
||||
then();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<div id="log">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,212 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include "BatteryManager.h"
|
||||
#include "Constants.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/dom/BatteryManagerBinding.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIDocument.h"
|
||||
|
||||
/**
|
||||
* We have to use macros here because our leak analysis tool things we are
|
||||
* leaking strings when we have |static const nsString|. Sad :(
|
||||
*/
|
||||
#define LEVELCHANGE_EVENT_NAME NS_LITERAL_STRING("levelchange")
|
||||
#define CHARGINGCHANGE_EVENT_NAME NS_LITERAL_STRING("chargingchange")
|
||||
#define DISCHARGINGTIMECHANGE_EVENT_NAME NS_LITERAL_STRING("dischargingtimechange")
|
||||
#define CHARGINGTIMECHANGE_EVENT_NAME NS_LITERAL_STRING("chargingtimechange")
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace battery {
|
||||
|
||||
BatteryManager::BatteryManager(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow)
|
||||
, mLevel(kDefaultLevel)
|
||||
, mCharging(kDefaultCharging)
|
||||
, mRemainingTime(kDefaultRemainingTime)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::Init()
|
||||
{
|
||||
hal::RegisterBatteryObserver(this);
|
||||
|
||||
hal::BatteryInformation batteryInfo;
|
||||
hal::GetCurrentBatteryInformation(&batteryInfo);
|
||||
|
||||
UpdateFromBatteryInfo(batteryInfo);
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::Shutdown()
|
||||
{
|
||||
hal::UnregisterBatteryObserver(this);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
BatteryManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
||||
{
|
||||
return BatteryManagerBinding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
bool
|
||||
BatteryManager::Charging() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default", false)) {
|
||||
return true;
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.charging", false)) {
|
||||
return true;
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mCharging;
|
||||
}
|
||||
|
||||
double
|
||||
BatteryManager::DischargingTime() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default", false)) {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.discharging", false)) {
|
||||
return 42.0;
|
||||
}
|
||||
|
||||
if (Charging() || mRemainingTime == kUnknownRemainingTime) {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
return mRemainingTime;
|
||||
}
|
||||
|
||||
double
|
||||
BatteryManager::ChargingTime() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default", false)) {
|
||||
return 0.0;
|
||||
}
|
||||
if (Preferences::GetBool("dom.battery.test.charging", false)) {
|
||||
return 42.0;
|
||||
}
|
||||
|
||||
if (!Charging() || mRemainingTime == kUnknownRemainingTime) {
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
|
||||
return mRemainingTime;
|
||||
}
|
||||
|
||||
double
|
||||
BatteryManager::Level() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
// For testing, unable to report the battery status information
|
||||
if (Preferences::GetBool("dom.battery.test.default")) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
return mLevel;
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo)
|
||||
{
|
||||
mLevel = aBatteryInfo.level();
|
||||
|
||||
// Round to the nearest ten percent for non-chrome and non-certified apps
|
||||
nsIDocument* doc = GetOwner() ? GetOwner()->GetDoc() : nullptr;
|
||||
uint16_t status = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
|
||||
if (doc) {
|
||||
status = doc->NodePrincipal()->GetAppStatus();
|
||||
}
|
||||
|
||||
mCharging = aBatteryInfo.charging();
|
||||
mRemainingTime = aBatteryInfo.remainingTime();
|
||||
|
||||
if (!nsContentUtils::IsChromeDoc(doc) &&
|
||||
status != nsIPrincipal::APP_STATUS_CERTIFIED)
|
||||
{
|
||||
mLevel = lround(mLevel * 10.0) / 10.0;
|
||||
if (mLevel == 1.0) {
|
||||
mRemainingTime = mCharging ? kDefaultRemainingTime : kUnknownRemainingTime;
|
||||
} else if (mRemainingTime != kUnknownRemainingTime) {
|
||||
// Round the remaining time to a multiple of 15 minutes and never zero
|
||||
const double MINUTES_15 = 15.0 * 60.0;
|
||||
mRemainingTime = fmax(lround(mRemainingTime / MINUTES_15) * MINUTES_15,
|
||||
MINUTES_15);
|
||||
}
|
||||
}
|
||||
|
||||
// Add some guards to make sure the values are coherent.
|
||||
if (mLevel == 1.0 && mCharging == true &&
|
||||
mRemainingTime != kDefaultRemainingTime) {
|
||||
mRemainingTime = kDefaultRemainingTime;
|
||||
NS_ERROR("Battery API: When charging and level at 1.0, remaining time "
|
||||
"should be 0. Please fix your backend!");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BatteryManager::Notify(const hal::BatteryInformation& aBatteryInfo)
|
||||
{
|
||||
double previousLevel = mLevel;
|
||||
bool previousCharging = mCharging;
|
||||
double previousRemainingTime = mRemainingTime;
|
||||
|
||||
UpdateFromBatteryInfo(aBatteryInfo);
|
||||
|
||||
if (previousCharging != mCharging) {
|
||||
DispatchTrustedEvent(CHARGINGCHANGE_EVENT_NAME);
|
||||
}
|
||||
|
||||
if (previousLevel != mLevel) {
|
||||
DispatchTrustedEvent(LEVELCHANGE_EVENT_NAME);
|
||||
}
|
||||
|
||||
/*
|
||||
* There are a few situations that could happen here:
|
||||
* 1. Charging state changed:
|
||||
* a. Previous remaining time wasn't unkwonw, we have to fire an event for
|
||||
* the change.
|
||||
* b. New remaining time isn't unkwonw, we have to fire an event for it.
|
||||
* 2. Charging state didn't change but remainingTime did, we have to fire
|
||||
* the event that correspond to the current charging state.
|
||||
*/
|
||||
if (mCharging != previousCharging) {
|
||||
if (previousRemainingTime != kUnknownRemainingTime) {
|
||||
DispatchTrustedEvent(previousCharging ? CHARGINGTIMECHANGE_EVENT_NAME
|
||||
: DISCHARGINGTIMECHANGE_EVENT_NAME);
|
||||
}
|
||||
if (mRemainingTime != kUnknownRemainingTime) {
|
||||
DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
|
||||
: DISCHARGINGTIMECHANGE_EVENT_NAME);
|
||||
}
|
||||
} else if (previousRemainingTime != mRemainingTime) {
|
||||
DispatchTrustedEvent(mCharging ? CHARGINGTIMECHANGE_EVENT_NAME
|
||||
: DISCHARGINGTIMECHANGE_EVENT_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace battery
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
@@ -1,84 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_battery_BatteryManager_h
|
||||
#define mozilla_dom_battery_BatteryManager_h
|
||||
|
||||
#include "Types.h"
|
||||
#include "mozilla/DOMEventTargetHelper.h"
|
||||
#include "mozilla/Observer.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace hal {
|
||||
class BatteryInformation;
|
||||
} // namespace hal
|
||||
|
||||
namespace dom {
|
||||
namespace battery {
|
||||
|
||||
class BatteryManager : public DOMEventTargetHelper
|
||||
, public BatteryObserver
|
||||
{
|
||||
public:
|
||||
explicit BatteryManager(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
// For IObserver.
|
||||
void Notify(const hal::BatteryInformation& aBatteryInfo) override;
|
||||
|
||||
/**
|
||||
* WebIDL Interface
|
||||
*/
|
||||
|
||||
nsPIDOMWindowInner* GetParentObject() const
|
||||
{
|
||||
return GetOwner();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
bool Charging() const;
|
||||
|
||||
double ChargingTime() const;
|
||||
|
||||
double DischargingTime() const;
|
||||
|
||||
double Level() const;
|
||||
|
||||
IMPL_EVENT_HANDLER(chargingchange)
|
||||
IMPL_EVENT_HANDLER(chargingtimechange)
|
||||
IMPL_EVENT_HANDLER(dischargingtimechange)
|
||||
IMPL_EVENT_HANDLER(levelchange)
|
||||
|
||||
private:
|
||||
/**
|
||||
* Update the battery information stored in the battery manager object using
|
||||
* a battery information object.
|
||||
*/
|
||||
void UpdateFromBatteryInfo(const hal::BatteryInformation& aBatteryInfo);
|
||||
|
||||
/**
|
||||
* Represents the battery level, ranging from 0.0 (dead or removed?)
|
||||
* to 1.0 (fully charged)
|
||||
*/
|
||||
double mLevel;
|
||||
bool mCharging;
|
||||
/**
|
||||
* Represents the discharging time or the charging time, depending on the
|
||||
* current battery status (charging or not).
|
||||
*/
|
||||
double mRemainingTime;
|
||||
};
|
||||
|
||||
} // namespace battery
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_battery_BatteryManager_h
|
||||
@@ -1,27 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_battery_Constants_h__
|
||||
#define mozilla_dom_battery_Constants_h__
|
||||
|
||||
/**
|
||||
* A set of constants that might need to be used by battery backends.
|
||||
* It's not part of BatteryManager.h to prevent those backends to include it.
|
||||
*/
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
namespace battery {
|
||||
|
||||
static const double kDefaultLevel = 1.0;
|
||||
static const bool kDefaultCharging = true;
|
||||
static const double kDefaultRemainingTime = 0;
|
||||
static const double kUnknownRemainingTime = -1;
|
||||
|
||||
} // namespace battery
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_battery_Constants_h__
|
||||
@@ -1,23 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_battery_Types_h
|
||||
#define mozilla_dom_battery_Types_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace hal {
|
||||
class BatteryInformation;
|
||||
} // namespace hal
|
||||
|
||||
template <class T>
|
||||
class Observer;
|
||||
|
||||
typedef Observer<hal::BatteryInformation> BatteryObserver;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_battery_Types_h
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
EXPORTS.mozilla.dom.battery += [
|
||||
'Constants.h',
|
||||
'Types.h',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
'BatteryManager.cpp',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
@@ -1,3 +0,0 @@
|
||||
[test_battery_basics.html]
|
||||
[test_battery_charging.html]
|
||||
[test_battery_discharging.html]
|
||||
@@ -1 +0,0 @@
|
||||
[test_battery_unprivileged.html]
|
||||
@@ -1,39 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** Test for Battery API **/
|
||||
ok("getBattery" in navigator, "navigator.getBattery should exist");
|
||||
ok(!("battery" in navigator), "navigator.battery should not exist");
|
||||
|
||||
navigator.getBattery().then(function (battery) {
|
||||
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.default", true]]}, function () {
|
||||
ok(battery.charging, "Battery should be charging by default");
|
||||
is(battery.chargingTime, 0, "Battery chargingTime " + battery.chargingTime + " should be zero by default");
|
||||
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity by default");
|
||||
is(battery.level, 1.0, "Battery level " + battery.level + " should be 1.0 by default");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** Test for Battery API **/
|
||||
navigator.getBattery().then(function (battery) {
|
||||
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.charging", true]]}, function () {
|
||||
is(battery.charging, true, "Battery should be charging");
|
||||
ok(battery.chargingTime >= 0, "Battery chargingTime " + battery.chargingTime + " should be nonnegative when charging");
|
||||
is(battery.dischargingTime, Infinity, "Battery dischargingTime should be Infinity when charging");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
/** Test for Battery API **/
|
||||
navigator.getBattery().then(function (battery) {
|
||||
ok(battery.level >= 0.0 && battery.level <= 1.0, "Battery level " + battery.level + " should be in the range [0.0, 1.0]");
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.battery.test.discharging", true]]}, function () {
|
||||
is(battery.charging, false, "Battery should be discharging");
|
||||
is(battery.chargingTime, Infinity, "Battery chargingTime should be Infinity when discharging");
|
||||
ok(battery.dischargingTime > 0, "Battery dischargingTime " + battery.dischargingTime + " should be positive when discharging");
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,24 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for Battery API</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
"use strict";
|
||||
|
||||
/** Test for Battery API **/
|
||||
ok(!("getBattery" in navigator), "navigator.getBattery should not exist for unprivileged web content");
|
||||
ok(!("battery" in navigator), "navigator.battery should not exist");
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2487,6 +2487,12 @@ ConstructJSImplementation(const char* aContractId,
|
||||
{
|
||||
AutoNoJSAPI nojsapi;
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||
if (!window->IsCurrentInnerWindow()) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the XPCOM component containing the JS implementation.
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupports> implISupports = do_CreateInstance(aContractId, &rv);
|
||||
@@ -2501,7 +2507,6 @@ ConstructJSImplementation(const char* aContractId,
|
||||
// and our global is a window.
|
||||
nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi =
|
||||
do_QueryInterface(implISupports);
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
|
||||
if (gpi) {
|
||||
JS::Rooted<JS::Value> initReturn(RootingCx());
|
||||
rv = gpi->Init(window, &initReturn);
|
||||
|
||||
@@ -3071,21 +3071,21 @@ class GetCCParticipant
|
||||
{
|
||||
// Helper for GetCCParticipant for classes that participate in CC.
|
||||
template<class U>
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
GetHelper(int, typename U::NS_CYCLE_COLLECTION_INNERCLASS* dummy=nullptr)
|
||||
{
|
||||
return T::NS_CYCLE_COLLECTION_INNERCLASS::GetParticipant();
|
||||
}
|
||||
// Helper for GetCCParticipant for classes that don't participate in CC.
|
||||
template<class U>
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
GetHelper(double)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
Get()
|
||||
{
|
||||
// Passing int() here will try to call the GetHelper that takes an int as
|
||||
@@ -3100,7 +3100,7 @@ template<class T>
|
||||
class GetCCParticipant<T, true>
|
||||
{
|
||||
public:
|
||||
static constexpr nsCycleCollectionParticipant*
|
||||
static nsCycleCollectionParticipant*
|
||||
Get()
|
||||
{
|
||||
return nullptr;
|
||||
@@ -3123,7 +3123,7 @@ EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||
template <class T>
|
||||
struct CreateGlobalOptions
|
||||
{
|
||||
static constexpr ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
static const ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
ProtoAndIfaceCache::NonWindowLike;
|
||||
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||
{
|
||||
@@ -3140,7 +3140,7 @@ struct CreateGlobalOptions
|
||||
template <>
|
||||
struct CreateGlobalOptions<nsGlobalWindow>
|
||||
{
|
||||
static constexpr ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
static const ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||
ProtoAndIfaceCache::WindowLike;
|
||||
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
|
||||
static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
|
||||
|
||||
@@ -717,6 +717,21 @@ DOMInterfaces = {
|
||||
},
|
||||
},
|
||||
|
||||
'ResizeObservation': {
|
||||
'nativeType': 'mozilla::dom::ResizeObservation',
|
||||
'headerFile': 'mozilla/dom/ResizeObserver.h',
|
||||
},
|
||||
|
||||
'ResizeObserver': {
|
||||
'nativeType': 'mozilla::dom::ResizeObserver',
|
||||
'headerFile': 'mozilla/dom/ResizeObserver.h',
|
||||
},
|
||||
|
||||
'ResizeObserverEntry': {
|
||||
'nativeType': 'mozilla::dom::ResizeObserverEntry',
|
||||
'headerFile': 'mozilla/dom/ResizeObserver.h',
|
||||
},
|
||||
|
||||
'Response': {
|
||||
'binaryNames': { 'headers': 'headers_' },
|
||||
},
|
||||
|
||||
@@ -210,7 +210,7 @@ struct NativePropertiesN {
|
||||
|
||||
const int32_t iteratorAliasMethodIndex;
|
||||
|
||||
constexpr const NativePropertiesN<7>* Upcast() const {
|
||||
const NativePropertiesN<7>* Upcast() const {
|
||||
return reinterpret_cast<const NativePropertiesN<7>*>(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ def generateLine(propName, extendedAttrs):
|
||||
propName)
|
||||
def generate(output, idlFilename, preprocessorHeader):
|
||||
print(idlFilename)
|
||||
sys.stdout.flush()
|
||||
cpp = list(buildconfig.substs['CPP'])
|
||||
cpp += shellutil.split(buildconfig.substs['ACDEFINES'])
|
||||
cpp.append(preprocessorHeader)
|
||||
|
||||
@@ -64,7 +64,6 @@ LOCAL_INCLUDES += [
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/dom/battery',
|
||||
'/dom/canvas',
|
||||
'/dom/geolocation',
|
||||
'/dom/html',
|
||||
|
||||
@@ -12,6 +12,7 @@ import hashlib
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
|
||||
from copy import deepcopy
|
||||
|
||||
@@ -270,6 +271,7 @@ class WebIDLCodegenManager(LoggingMixin):
|
||||
for filename in sorted(changed_inputs):
|
||||
basename = mozpath.basename(filename)
|
||||
print basename
|
||||
sys.stdout.flush()
|
||||
result.inputs.add(filename)
|
||||
written, deps = self._generate_build_files_for_webidl(filename)
|
||||
result.created |= written[0]
|
||||
|
||||
Vendored
+1
-1
@@ -2460,7 +2460,7 @@ Validate(mozIStorageConnection* aConn)
|
||||
typedef nsresult (*MigrationFunc)(mozIStorageConnection*, bool&);
|
||||
struct Migration
|
||||
{
|
||||
constexpr Migration(int32_t aFromVersion, MigrationFunc aFunc)
|
||||
Migration(int32_t aFromVersion, MigrationFunc aFunc)
|
||||
: mFromVersion(aFromVersion)
|
||||
, mFunc(aFunc)
|
||||
{ }
|
||||
|
||||
Vendored
+3
-3
@@ -253,7 +253,7 @@ TypeUtils::ToResponse(const CacheResponse& aIn)
|
||||
{
|
||||
if (aIn.type() == ResponseType::Error) {
|
||||
RefPtr<InternalResponse> error = InternalResponse::NetworkError();
|
||||
RefPtr<Response> r = new Response(GetGlobalObject(), error);
|
||||
RefPtr<Response> r = new Response(GetGlobalObject(), error, nullptr);
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
@@ -302,7 +302,7 @@ TypeUtils::ToResponse(const CacheResponse& aIn)
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(ir);
|
||||
|
||||
RefPtr<Response> ref = new Response(GetGlobalObject(), ir);
|
||||
RefPtr<Response> ref = new Response(GetGlobalObject(), ir, nullptr);
|
||||
return ref.forget();
|
||||
}
|
||||
already_AddRefed<InternalRequest>
|
||||
@@ -345,7 +345,7 @@ already_AddRefed<Request>
|
||||
TypeUtils::ToRequest(const CacheRequest& aIn)
|
||||
{
|
||||
RefPtr<InternalRequest> internalRequest = ToInternalRequest(aIn);
|
||||
RefPtr<Request> request = new Request(GetGlobalObject(), internalRequest);
|
||||
RefPtr<Request> request = new Request(GetGlobalObject(), internalRequest, nullptr);
|
||||
return request.forget();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,456 +0,0 @@
|
||||
/*
|
||||
* Copyright 2008 The Closure Compiler Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Definitions for WebKit's custom CSS properties. Copied from:
|
||||
* {@link
|
||||
* http://trac.webkit.org/browser/trunk/Source/WebCore/css/CSSPropertyNames.in}
|
||||
*
|
||||
* If you make changes to this file, notice that every property appears
|
||||
* twice: once as an uppercase name and once as a lowercase name.
|
||||
* WebKit allows both. The uppercase version is preferred.
|
||||
*
|
||||
* @externs
|
||||
* @author nicksantos@google.com (Nick Santos)
|
||||
*/
|
||||
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAlignContent;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAlignItems;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAlignSelf;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimation;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationDelay;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationDuration;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationFillMode;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationIterationCount;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationName;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationPlayState;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAnimationTimingFunction;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAppearance;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAppRegion;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitAspectRatio;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBackfaceVisibility;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBackgroundClip;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBackgroundComposite;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBackgroundOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBackgroundSize;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBinding;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBlendMode;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderAfterColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderAfterStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderAfterWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderBeforeColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderBeforeStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderBeforeWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderBottomLeftRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderBottomRightRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderEnd;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderEndColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderEndStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderEndWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderFit;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderHorizontalSpacing;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderImage;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderStart;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderStartColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderStartStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderStartWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderTopLeftRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderTopRightRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBorderVerticalSpacing;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxAlign;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxDecorationBreak;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxFlex;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxFlexGroup;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxLines;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxOrdinalGroup;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxOrient;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxPack;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxReflect;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxShadow;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitBoxSizing;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColorCorrection;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnAxis;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnBreakAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnBreakBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnBreakInside;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnCount;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnGap;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnProgression;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnRule;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnRuleColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnRuleStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnRuleWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumns;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnSpan;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitColumnWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitDashboardRegion;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFilter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlex;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlexBasis;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlexDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlexFlow;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlexGrow;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlexShrink;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlexWrap;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlowFrom;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFlowInto;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFontSizeDelta;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitFontSmoothing;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitGridColumn;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitGridColumns;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitGridRow;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitGridRows;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitHighlight;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitHyphenateCharacter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitHyphenateLimitAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitHyphenateLimitBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitHyphenateLimitLines;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitHyphens;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitJustifyContent;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLineAlign;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLineBoxContain;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLineBreak;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLineClamp;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLineGrid;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLineSnap;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLocale;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLogicalHeight;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitLogicalWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginAfterCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginBeforeCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginBottomCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginEnd;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginStart;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarginTopCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarquee;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarqueeDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarqueeIncrement;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarqueeRepetition;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarqueeSpeed;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMarqueeStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMask;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskAttachment;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImage;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageOutset;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageRepeat;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageSlice;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageSource;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskBoxImageWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskClip;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskComposite;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskImage;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskPosition;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskPositionX;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskPositionY;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskRepeat;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskRepeatX;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskRepeatY;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaskSize;
|
||||
/** @type {string} */
|
||||
CSSProperties.prototype.WebkitMatchNearestMailBlockquoteColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaxLogicalHeight;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMaxLogicalWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMinLogicalHeight;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitMinLogicalWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitNbspMode;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitOrder;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitOverflowScrolling;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPaddingAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPaddingBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPaddingEnd;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPaddingStart;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPerspective;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPerspectiveOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPerspectiveOriginX;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPerspectiveOriginY;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitPrintColorAdjust;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitRegionBreakAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitRegionBreakBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitRegionBreakInside;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitRegionOverflow;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitRtlOrdering;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitRubyPosition;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitShapeInside;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitShapeMargin;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitShapeOutside;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitShapePadding;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTapHighlightColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextAlignLast;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextCombine;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextDecorationLine;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextDecorationsInEffect;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextDecorationStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasis;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasisColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasisPosition;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextEmphasisStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextFillColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextOrientation;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextSecurity;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextSizeAdjust;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextStroke;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextStrokeColor;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTextStrokeWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransform;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransformOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransformOriginX;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransformOriginY;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransformOriginZ;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransformStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransition;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransitionDelay;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransitionDuration;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransitionProperty;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransitionRepeatCount;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitTransitionTimingFunction;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitUserDrag;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitUserModify;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitUserSelect;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitWrap;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitWrapFlow;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitWrapThrough;
|
||||
/** @type {string} */ CSSProperties.prototype.WebkitWritingMode;
|
||||
|
||||
// WebKit also adds bindings for the lowercase versions of these properties.
|
||||
// The uppercase version is preferred.
|
||||
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAlignContent;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAlignItems;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAlignSelf;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimation;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationDelay;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationDuration;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationFillMode;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationIterationCount;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationName;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationPlayState;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAnimationTimingFunction;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAppearance;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAppRegion;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitAspectRatio;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBackfaceVisibility;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBackgroundClip;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBackgroundComposite;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBackgroundOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBackgroundSize;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBinding;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBlendMode;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderAfterColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderAfterStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderAfterWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderBeforeColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderBeforeStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderBeforeWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderBottomLeftRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderBottomRightRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderEnd;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderEndColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderEndStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderEndWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderFit;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderHorizontalSpacing;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderImage;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderStart;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderStartColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderStartStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderStartWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderTopLeftRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderTopRightRadius;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBorderVerticalSpacing;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxAlign;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxDecorationBreak;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxFlex;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxFlexGroup;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxLines;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxOrdinalGroup;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxOrient;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxPack;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxReflect;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxShadow;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitBoxSizing;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColorCorrection;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnAxis;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnBreakAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnBreakBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnBreakInside;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnCount;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnGap;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnProgression;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnRule;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnRuleColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnRuleStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnRuleWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumns;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnSpan;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitColumnWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitDashboardRegion;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFilter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlex;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlexBasis;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlexDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlexFlow;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlexGrow;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlexShrink;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlexWrap;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlowFrom;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFlowInto;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFontSizeDelta;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitFontSmoothing;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitGridColumn;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitGridColumns;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitGridRow;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitGridRows;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitHighlight;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitHyphenateCharacter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitHyphenateLimitAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitHyphenateLimitBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitHyphenateLimitLines;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitHyphens;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitJustifyContent;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLineAlign;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLineBoxContain;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLineBreak;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLineClamp;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLineGrid;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLineSnap;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLocale;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLogicalHeight;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitLogicalWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginAfterCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginBeforeCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginBottomCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginEnd;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginStart;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarginTopCollapse;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarquee;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarqueeDirection;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarqueeIncrement;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarqueeRepetition;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarqueeSpeed;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMarqueeStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMask;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskAttachment;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImage;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageOutset;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageRepeat;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageSlice;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageSource;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskBoxImageWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskClip;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskComposite;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskImage;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskPosition;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskPositionX;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskPositionY;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskRepeat;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskRepeatX;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskRepeatY;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaskSize;
|
||||
/** @type {string} */
|
||||
CSSProperties.prototype.webkitMatchNearestMailBlockquoteColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaxLogicalHeight;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMaxLogicalWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMinLogicalHeight;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitMinLogicalWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitNbspMode;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitOrder;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitOverflowScrolling;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPaddingAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPaddingBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPaddingEnd;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPaddingStart;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPerspective;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPerspectiveOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPerspectiveOriginX;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPerspectiveOriginY;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitPrintColorAdjust;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitRegionBreakAfter;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitRegionBreakBefore;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitRegionBreakInside;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitRegionOverflow;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitRtlOrdering;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitRubyPosition;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitShapeInside;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitShapeMargin;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitShapeOutside;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitShapePadding;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTapHighlightColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextAlignLast;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextCombine;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextDecorationLine;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextDecorationsInEffect;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextDecorationStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextEmphasis;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextEmphasisColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextEmphasisPosition;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextEmphasisStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextFillColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextOrientation;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextSecurity;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextSizeAdjust;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextStroke;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextStrokeColor;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTextStrokeWidth;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransform;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransformOrigin;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransformOriginX;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransformOriginY;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransformOriginZ;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransformStyle;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransition;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransitionDelay;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransitionDuration;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransitionProperty;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransitionRepeatCount;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitTransitionTimingFunction;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitUserDrag;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitUserModify;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitUserSelect;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitWrap;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitWrapFlow;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitWrapThrough;
|
||||
/** @type {string} */ CSSProperties.prototype.webkitWritingMode;
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
*/
|
||||
function WebKitPoint(x, y) {}
|
||||
|
||||
/** @type {number} */
|
||||
WebKitPoint.prototype.x;
|
||||
|
||||
/** @type {number} */
|
||||
WebKitPoint.prototype.y;
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
typedef uint64_t InternalType;
|
||||
typedef uint8_t ServoType;
|
||||
|
||||
constexpr EventStates()
|
||||
EventStates()
|
||||
: mStates(0)
|
||||
{
|
||||
}
|
||||
@@ -37,12 +37,12 @@ public:
|
||||
// In that case, we could be sure that only macros at the end were creating
|
||||
// EventStates instances with mStates set to something else than 0.
|
||||
// Unfortunately, this constructor is needed at at least two places now.
|
||||
explicit constexpr EventStates(InternalType aStates)
|
||||
explicit EventStates(InternalType aStates)
|
||||
: mStates(aStates)
|
||||
{
|
||||
}
|
||||
|
||||
EventStates constexpr operator|(const EventStates& aEventStates) const
|
||||
EventStates operator|(const EventStates& aEventStates) const
|
||||
{
|
||||
return EventStates(mStates | aEventStates.mStates);
|
||||
}
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
// NOTE: calling if (eventStates1 & eventStates2) will not build.
|
||||
// This might work correctly if operator bool() is defined
|
||||
// but using HasState, HasAllStates or HasAtLeastOneOfStates is recommended.
|
||||
EventStates constexpr operator&(const EventStates& aEventStates) const
|
||||
EventStates operator&(const EventStates& aEventStates) const
|
||||
{
|
||||
return EventStates(mStates & aEventStates.mStates);
|
||||
}
|
||||
|
||||
+34
-11
@@ -111,6 +111,12 @@ public:
|
||||
return mSignalMainThread;
|
||||
}
|
||||
|
||||
AbortSignal*
|
||||
GetSignalForTargetThread()
|
||||
{
|
||||
return mFollowingSignal;
|
||||
}
|
||||
|
||||
void
|
||||
Shutdown()
|
||||
{
|
||||
@@ -161,7 +167,7 @@ public:
|
||||
}
|
||||
|
||||
AbortSignal*
|
||||
GetAbortSignal()
|
||||
GetAbortSignalForMainThread()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@@ -172,6 +178,18 @@ public:
|
||||
return mSignalProxy->GetOrCreateSignalForMainThread();
|
||||
}
|
||||
|
||||
AbortSignal*
|
||||
GetAbortSignalForTargetThread()
|
||||
{
|
||||
mPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
|
||||
|
||||
if (!mSignalProxy) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mSignalProxy->GetSignalForTargetThread();
|
||||
}
|
||||
|
||||
void
|
||||
OnResponseAvailableInternal(InternalResponse* aResponse) override;
|
||||
|
||||
@@ -205,14 +223,16 @@ class MainThreadFetchResolver final : public FetchDriverObserver
|
||||
RefPtr<Promise> mPromise;
|
||||
RefPtr<Response> mResponse;
|
||||
RefPtr<FetchObserver> mFetchObserver;
|
||||
RefPtr<AbortSignal> mSignal;
|
||||
|
||||
nsCOMPtr<nsIDocument> mDocument;
|
||||
|
||||
NS_DECL_OWNINGTHREAD
|
||||
public:
|
||||
MainThreadFetchResolver(Promise* aPromise, FetchObserver* aObserver)
|
||||
MainThreadFetchResolver(Promise* aPromise, FetchObserver* aObserver, AbortSignal* aSignal)
|
||||
: mPromise(aPromise)
|
||||
, mFetchObserver(aObserver)
|
||||
, mSignal(aSignal)
|
||||
{}
|
||||
|
||||
void
|
||||
@@ -287,7 +307,7 @@ public:
|
||||
fetch->SetWorkerScript(spec);
|
||||
}
|
||||
|
||||
RefPtr<AbortSignal> signal = mResolver->GetAbortSignal();
|
||||
RefPtr<AbortSignal> signal = mResolver->GetAbortSignalForMainThread();
|
||||
|
||||
// ...but release it before calling Fetch, because mResolver's callback can
|
||||
// be called synchronously and they want the mutex, too.
|
||||
@@ -329,10 +349,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
|
||||
|
||||
RefPtr<InternalRequest> r = request->GetInternalRequest();
|
||||
|
||||
RefPtr<AbortSignal> signal;
|
||||
if (aInit.mSignal.WasPassed()) {
|
||||
signal = &aInit.mSignal.Value();
|
||||
}
|
||||
RefPtr<AbortSignal> signal = request->GetSignal();
|
||||
|
||||
if (signal && signal->Aborted()) {
|
||||
// An already aborted signal should reject immediately.
|
||||
@@ -373,7 +390,7 @@ FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
|
||||
}
|
||||
|
||||
RefPtr<MainThreadFetchResolver> resolver =
|
||||
new MainThreadFetchResolver(p, observer);
|
||||
new MainThreadFetchResolver(p, observer, signal);
|
||||
RefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup);
|
||||
fetch->SetDocument(doc);
|
||||
resolver->SetDocument(doc);
|
||||
@@ -416,7 +433,7 @@ MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> go = mPromise->GetParentObject();
|
||||
mResponse = new Response(go, aResponse);
|
||||
mResponse = new Response(go, aResponse, mSignal);
|
||||
mPromise->MaybeResolve(mResponse);
|
||||
} else {
|
||||
if (mFetchObserver) {
|
||||
@@ -479,7 +496,7 @@ public:
|
||||
}
|
||||
|
||||
RefPtr<nsIGlobalObject> global = aWorkerPrivate->GlobalScope();
|
||||
RefPtr<Response> response = new Response(global, mInternalResponse);
|
||||
RefPtr<Response> response = new Response(global, mInternalResponse, mResolver->GetAbortSignalForTargetThread());
|
||||
promise->MaybeResolve(response);
|
||||
} else {
|
||||
if (mResolver->mFetchObserver) {
|
||||
@@ -926,6 +943,12 @@ template <class Derived>
|
||||
already_AddRefed<Promise>
|
||||
FetchBody<Derived>::ConsumeBody(FetchConsumeType aType, ErrorResult& aRv)
|
||||
{
|
||||
RefPtr<AbortSignal> signal = DerivedClass()->GetSignal();
|
||||
if (signal && signal->Aborted()) {
|
||||
aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (BodyUsed()) {
|
||||
aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
|
||||
return nullptr;
|
||||
@@ -935,7 +958,7 @@ FetchBody<Derived>::ConsumeBody(FetchConsumeType aType, ErrorResult& aRv)
|
||||
|
||||
RefPtr<Promise> promise =
|
||||
FetchBodyConsumer<Derived>::Create(DerivedClass()->GetParentObject(),
|
||||
this, aType, aRv);
|
||||
this, signal, aType, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -162,6 +162,9 @@ public:
|
||||
return mMimeType;
|
||||
}
|
||||
|
||||
virtual AbortSignal*
|
||||
GetSignal() const = 0;
|
||||
|
||||
protected:
|
||||
FetchBody();
|
||||
|
||||
|
||||
@@ -284,6 +284,7 @@ template <class Derived>
|
||||
/* static */ already_AddRefed<Promise>
|
||||
FetchBodyConsumer<Derived>::Create(nsIGlobalObject* aGlobal,
|
||||
FetchBody<Derived>* aBody,
|
||||
AbortSignal* aSignal,
|
||||
FetchConsumeType aType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
@@ -345,6 +346,10 @@ FetchBodyConsumer<Derived>::Create(nsIGlobalObject* aGlobal,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aSignal) {
|
||||
consumer->Follow(aSignal);
|
||||
}
|
||||
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
@@ -368,6 +373,8 @@ FetchBodyConsumer<Derived>::ReleaseObject()
|
||||
#ifdef DEBUG
|
||||
mBody = nullptr;
|
||||
#endif
|
||||
|
||||
Unfollow();
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
@@ -684,6 +691,14 @@ FetchBodyConsumer<Derived>::Observe(nsISupports* aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
FetchBodyConsumer<Derived>::Aborted()
|
||||
{
|
||||
AssertIsOnTargetThread();
|
||||
ContinueConsumeBody(NS_ERROR_DOM_ABORT_ERR, 0, nullptr);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
NS_IMPL_ADDREF(FetchBodyConsumer<Derived>)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "mozilla/dom/AbortSignal.h"
|
||||
#include "mozilla/dom/MutableBlobStorage.h"
|
||||
|
||||
class nsIThread;
|
||||
@@ -34,6 +35,7 @@ template <class Derived> class FetchBody;
|
||||
template <class Derived>
|
||||
class FetchBodyConsumer final : public nsIObserver
|
||||
, public nsSupportsWeakReference
|
||||
, public AbortSignal::Follower
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
@@ -42,6 +44,7 @@ public:
|
||||
static already_AddRefed<Promise>
|
||||
Create(nsIGlobalObject* aGlobal,
|
||||
FetchBody<Derived>* aBody,
|
||||
AbortSignal* aSignal,
|
||||
FetchConsumeType aType,
|
||||
ErrorResult& aRv);
|
||||
|
||||
@@ -73,6 +76,9 @@ public:
|
||||
mConsumeBodyPump = nullptr;
|
||||
}
|
||||
|
||||
// Override AbortSignal::Follower::Aborted
|
||||
void Aborted() override;
|
||||
|
||||
private:
|
||||
FetchBodyConsumer(nsIGlobalObject* aGlobalObject,
|
||||
workers::WorkerPrivate* aWorkerPrivate,
|
||||
|
||||
@@ -499,6 +499,11 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!mChannel) {
|
||||
MOZ_ASSERT(!mObserver);
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
// We should only get to the following code once.
|
||||
MOZ_ASSERT(!mPipeOutputStream);
|
||||
MOZ_ASSERT(mObserver);
|
||||
@@ -704,10 +709,12 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest,
|
||||
// about races.
|
||||
|
||||
if (mObserver) {
|
||||
// Need to keep mObserver alive.
|
||||
RefPtr<FetchDriverObserver> observer = mObserver;
|
||||
if (NS_IsMainThread()) {
|
||||
mObserver->OnDataAvailable();
|
||||
observer->OnDataAvailable();
|
||||
} else {
|
||||
RefPtr<Runnable> runnable = new DataAvailableRunnable(mObserver);
|
||||
RefPtr<Runnable> runnable = new DataAvailableRunnable(observer);
|
||||
nsresult rv = NS_DispatchToMainThread(runnable);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
@@ -715,12 +722,15 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest,
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t aRead;
|
||||
// Explicitly initialized to 0 because in some cases nsStringInputStream may
|
||||
// not write to aRead.
|
||||
uint32_t aRead = 0;
|
||||
MOZ_ASSERT(mResponse);
|
||||
MOZ_ASSERT(mPipeOutputStream);
|
||||
|
||||
// From "Main Fetch" step 17: SRI-part2.
|
||||
if (mResponse->Type() != ResponseType::Error &&
|
||||
if (mResponse &&
|
||||
mResponse->Type() != ResponseType::Error &&
|
||||
!mRequest->GetIntegrity().IsEmpty()) {
|
||||
MOZ_ASSERT(mSRIDataVerifier);
|
||||
|
||||
@@ -762,6 +772,17 @@ FetchDriver::OnDataAvailable(nsIRequest* aRequest,
|
||||
nsresult rv = aInputStream->ReadSegments(NS_CopySegmentToStream,
|
||||
mPipeOutputStream,
|
||||
aCount, &aRead);
|
||||
|
||||
// If no data was read, it's possible the output stream is closed but the
|
||||
// ReadSegments call followed its contract of returning NS_OK despite write
|
||||
// errors. Unfortunately, nsIOutputStream has an ill-conceived contract when
|
||||
// taken together with ReadSegments' contract, because the pipe will just
|
||||
// NS_OK if we try and invoke its Write* functions ourselves with a 0 count.
|
||||
// So we must just assume the pipe is broken.
|
||||
if (aRead == 0 && aCount != 0) {
|
||||
return NS_BASE_STREAM_CLOSED;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
+30
-4
@@ -37,15 +37,18 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
|
||||
Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest, AbortSignal* aSignal)
|
||||
: FetchBody<Request>()
|
||||
, mOwner(aOwner)
|
||||
, mRequest(aRequest)
|
||||
, mSignal(aSignal)
|
||||
{
|
||||
MOZ_ASSERT(aRequest->Headers()->Guard() == HeadersGuardEnum::Immutable ||
|
||||
aRequest->Headers()->Guard() == HeadersGuardEnum::Request ||
|
||||
aRequest->Headers()->Guard() == HeadersGuardEnum::Request_no_cors);
|
||||
SetMimeType();
|
||||
|
||||
// aSignal can be null.
|
||||
}
|
||||
|
||||
Request::~Request()
|
||||
@@ -286,6 +289,8 @@ Request::Constructor(const GlobalObject& aGlobal,
|
||||
RefPtr<InternalRequest> request;
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
|
||||
RefPtr<AbortSignal> signal;
|
||||
|
||||
if (aInput.IsRequest()) {
|
||||
RefPtr<Request> inputReq = &aInput.GetAsRequest();
|
||||
@@ -300,6 +305,7 @@ Request::Constructor(const GlobalObject& aGlobal,
|
||||
}
|
||||
|
||||
request = inputReq->GetInternalRequest();
|
||||
signal = inputReq->GetOrCreateSignal();
|
||||
} else {
|
||||
// aInput is USVString.
|
||||
// We need to get url before we create a InternalRequest.
|
||||
@@ -418,6 +424,10 @@ Request::Constructor(const GlobalObject& aGlobal,
|
||||
request->SetReferrerPolicy(aInit.mReferrerPolicy.Value());
|
||||
}
|
||||
|
||||
if (aInit.mSignal.WasPassed()) {
|
||||
signal = aInit.mSignal.Value();
|
||||
}
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global);
|
||||
if (window) {
|
||||
@@ -579,7 +589,7 @@ Request::Constructor(const GlobalObject& aGlobal,
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<Request> domRequest = new Request(global, request);
|
||||
RefPtr<Request> domRequest = new Request(global, request, signal);
|
||||
domRequest->SetMimeType();
|
||||
|
||||
if (aInput.IsRequest()) {
|
||||
@@ -595,7 +605,7 @@ Request::Constructor(const GlobalObject& aGlobal,
|
||||
}
|
||||
|
||||
already_AddRefed<Request>
|
||||
Request::Clone(ErrorResult& aRv) const
|
||||
Request::Clone(ErrorResult& aRv)
|
||||
{
|
||||
if (BodyUsed()) {
|
||||
aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
|
||||
@@ -608,7 +618,7 @@ Request::Clone(ErrorResult& aRv) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<Request> request = new Request(mOwner, ir);
|
||||
RefPtr<Request> request = new Request(mOwner, ir, GetOrCreateSignal());
|
||||
return request.forget();
|
||||
}
|
||||
|
||||
@@ -622,5 +632,21 @@ Request::Headers_()
|
||||
return mHeaders;
|
||||
}
|
||||
|
||||
AbortSignal*
|
||||
Request::GetOrCreateSignal()
|
||||
{
|
||||
if (!mSignal) {
|
||||
mSignal = new AbortSignal(false);
|
||||
}
|
||||
|
||||
return mSignal;
|
||||
}
|
||||
|
||||
AbortSignal*
|
||||
Request::GetSignal() const
|
||||
{
|
||||
return mSignal;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
+11
-2
@@ -33,7 +33,7 @@ class Request final : public nsISupports
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Request)
|
||||
|
||||
public:
|
||||
Request(nsIGlobalObject* aOwner, InternalRequest* aRequest);
|
||||
Request(nsIGlobalObject* aOwner, InternalRequest* aRequest, AbortSignal* aSignal);
|
||||
|
||||
static bool
|
||||
RequestContextEnabled(JSContext* aCx, JSObject* aObj);
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
}
|
||||
|
||||
already_AddRefed<Request>
|
||||
Clone(ErrorResult& aRv) const;
|
||||
Clone(ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<InternalRequest>
|
||||
GetInternalRequest();
|
||||
@@ -153,13 +153,22 @@ public:
|
||||
return mRequest->GetPrincipalInfo();
|
||||
}
|
||||
|
||||
AbortSignal*
|
||||
GetOrCreateSignal();
|
||||
|
||||
// This can return a null AbortSignal.
|
||||
AbortSignal*
|
||||
GetSignal() const override;
|
||||
|
||||
private:
|
||||
~Request();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mOwner;
|
||||
RefPtr<InternalRequest> mRequest;
|
||||
|
||||
// Lazily created.
|
||||
RefPtr<Headers> mHeaders;
|
||||
RefPtr<AbortSignal> mSignal;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -34,10 +34,11 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Response)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
Response::Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse)
|
||||
Response::Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse, AbortSignal* aSignal)
|
||||
: FetchBody<Response>()
|
||||
, mOwner(aGlobal)
|
||||
, mInternalResponse(aInternalResponse)
|
||||
, mSignal(aSignal)
|
||||
{
|
||||
MOZ_ASSERT(aInternalResponse->Headers()->Guard() == HeadersGuardEnum::Immutable ||
|
||||
aInternalResponse->Headers()->Guard() == HeadersGuardEnum::Response);
|
||||
@@ -53,7 +54,7 @@ Response::Error(const GlobalObject& aGlobal)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
|
||||
RefPtr<InternalResponse> error = InternalResponse::NetworkError();
|
||||
RefPtr<Response> r = new Response(global, error);
|
||||
RefPtr<Response> r = new Response(global, error, nullptr);
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
@@ -173,7 +174,7 @@ Response::Constructor(const GlobalObject& aGlobal,
|
||||
internalResponse->InitChannelInfo(worker->GetChannelInfo());
|
||||
}
|
||||
|
||||
RefPtr<Response> r = new Response(global, internalResponse);
|
||||
RefPtr<Response> r = new Response(global, internalResponse, nullptr);
|
||||
|
||||
if (aInit.mHeaders.WasPassed()) {
|
||||
internalResponse->Headers()->Clear();
|
||||
@@ -236,7 +237,7 @@ Response::Clone(ErrorResult& aRv) const
|
||||
}
|
||||
|
||||
RefPtr<InternalResponse> ir = mInternalResponse->Clone();
|
||||
RefPtr<Response> response = new Response(mOwner, ir);
|
||||
RefPtr<Response> response = new Response(mOwner, ir, mSignal);
|
||||
return response.forget();
|
||||
}
|
||||
|
||||
@@ -250,7 +251,7 @@ Response::CloneUnfiltered(ErrorResult& aRv) const
|
||||
|
||||
RefPtr<InternalResponse> clone = mInternalResponse->Clone();
|
||||
RefPtr<InternalResponse> ir = clone->Unfiltered();
|
||||
RefPtr<Response> ref = new Response(mOwner, ir);
|
||||
RefPtr<Response> ref = new Response(mOwner, ir, mSignal);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class Response final : public nsISupports
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Response)
|
||||
|
||||
public:
|
||||
Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse);
|
||||
Response(nsIGlobalObject* aGlobal, InternalResponse* aInternalResponse, AbortSignal* aSignal);
|
||||
|
||||
Response(const Response& aOther) = delete;
|
||||
|
||||
@@ -134,13 +134,21 @@ public:
|
||||
already_AddRefed<InternalResponse>
|
||||
GetInternalResponse() const;
|
||||
|
||||
AbortSignal*
|
||||
GetSignal() const override
|
||||
{
|
||||
return mSignal;
|
||||
}
|
||||
|
||||
private:
|
||||
~Response();
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> mOwner;
|
||||
RefPtr<InternalResponse> mInternalResponse;
|
||||
|
||||
// Lazily created
|
||||
RefPtr<Headers> mHeaders;
|
||||
RefPtr<AbortSignal> mSignal;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
||||
@@ -1455,7 +1455,7 @@ HeapSnapshot::CreateUniqueCoreDumpFile(ErrorResult& rv,
|
||||
class DeleteHeapSnapshotTempFileHelperChild
|
||||
{
|
||||
public:
|
||||
constexpr DeleteHeapSnapshotTempFileHelperChild() { }
|
||||
DeleteHeapSnapshotTempFileHelperChild() { }
|
||||
|
||||
void operator()(PHeapSnapshotTempFileHelperChild* ptr) const {
|
||||
Unused << NS_WARN_IF(!HeapSnapshotTempFileHelperChild::Send__delete__(ptr));
|
||||
|
||||
@@ -34,20 +34,6 @@ HTMLDivElement::ParseAttribute(int32_t aNamespaceID,
|
||||
nsAttrValue& aResult)
|
||||
{
|
||||
if (aNamespaceID == kNameSpaceID_None) {
|
||||
if (mNodeInfo->Equals(nsGkAtoms::marquee)) {
|
||||
if ((aAttribute == nsGkAtoms::width) ||
|
||||
(aAttribute == nsGkAtoms::height)) {
|
||||
return aResult.ParseSpecialIntValue(aValue);
|
||||
}
|
||||
if (aAttribute == nsGkAtoms::bgcolor) {
|
||||
return aResult.ParseColor(aValue);
|
||||
}
|
||||
if ((aAttribute == nsGkAtoms::hspace) ||
|
||||
(aAttribute == nsGkAtoms::vspace)) {
|
||||
return aResult.ParseIntWithBounds(aValue, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (mNodeInfo->Equals(nsGkAtoms::div) &&
|
||||
aAttribute == nsGkAtoms::align) {
|
||||
return ParseDivAlignValue(aValue, aResult);
|
||||
@@ -66,15 +52,6 @@ HTMLDivElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
|
||||
}
|
||||
|
||||
static void
|
||||
MapMarqueeAttributesIntoRule(const nsMappedAttributes* aAttributes, nsRuleData* aData)
|
||||
{
|
||||
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
|
||||
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
|
||||
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
|
||||
nsGenericHTMLElement::MapBGColorInto(aAttributes, aData);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
HTMLDivElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
||||
{
|
||||
@@ -85,14 +62,6 @@ HTMLDivElement::IsAttributeMapped(const nsIAtom* aAttribute) const
|
||||
};
|
||||
return FindAttributeDependence(aAttribute, map);
|
||||
}
|
||||
if (mNodeInfo->Equals(nsGkAtoms::marquee)) {
|
||||
static const MappedAttributeEntry* const map[] = {
|
||||
sImageMarginSizeAttributeMap,
|
||||
sBackgroundColorAttributeMap,
|
||||
sCommonAttributeMap
|
||||
};
|
||||
return FindAttributeDependence(aAttribute, map);
|
||||
}
|
||||
|
||||
return nsGenericHTMLElement::IsAttributeMapped(aAttribute);
|
||||
}
|
||||
@@ -103,9 +72,6 @@ HTMLDivElement::GetAttributeMappingFunction() const
|
||||
if (mNodeInfo->Equals(nsGkAtoms::div)) {
|
||||
return &MapAttributesIntoRule;
|
||||
}
|
||||
if (mNodeInfo->Equals(nsGkAtoms::marquee)) {
|
||||
return &MapMarqueeAttributesIntoRule;
|
||||
}
|
||||
return nsGenericHTMLElement::GetAttributeMappingFunction();
|
||||
}
|
||||
|
||||
|
||||
@@ -324,7 +324,7 @@ HTMLImageElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
|
||||
nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
|
||||
nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
|
||||
nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
|
||||
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
|
||||
nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData, true);
|
||||
nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
|
||||
}
|
||||
|
||||
|
||||
@@ -206,6 +206,11 @@ public:
|
||||
return GetReferrerPolicyAsEnum();
|
||||
}
|
||||
|
||||
bool IsAwaitingLoad() const
|
||||
{
|
||||
return !!mPendingImageLoadTask;
|
||||
}
|
||||
|
||||
int32_t X();
|
||||
int32_t Y();
|
||||
// Uses XPCOM GetLowsrc.
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#define LINK_ELEMENT_FLAG_BIT(n_) \
|
||||
NODE_FLAG_BIT(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + (n_))
|
||||
|
||||
#define LINK_DISABLED Preferences::GetBool("dom.link.disabled_attribute.enabled", true)
|
||||
|
||||
// Link element specific bits
|
||||
enum {
|
||||
// Indicates that a DNS Prefetch has been requested from this Link element.
|
||||
@@ -92,9 +94,14 @@ NS_INTERFACE_TABLE_TAIL_INHERITING(nsGenericHTMLElement)
|
||||
|
||||
NS_IMPL_ELEMENT_CLONE(HTMLLinkElement)
|
||||
|
||||
|
||||
bool
|
||||
HTMLLinkElement::Disabled()
|
||||
HTMLLinkElement::Disabled() const
|
||||
{
|
||||
if (LINK_DISABLED) {
|
||||
return GetBoolAttr(nsGkAtoms::disabled);
|
||||
}
|
||||
|
||||
StyleSheet* ss = GetSheet();
|
||||
return ss && ss->Disabled();
|
||||
}
|
||||
@@ -107,8 +114,12 @@ HTMLLinkElement::GetMozDisabled(bool* aDisabled)
|
||||
}
|
||||
|
||||
void
|
||||
HTMLLinkElement::SetDisabled(bool aDisabled)
|
||||
{
|
||||
HTMLLinkElement::SetDisabled(bool aDisabled, ErrorResult& aRv)
|
||||
{
|
||||
if (LINK_DISABLED) {
|
||||
return SetHTMLBoolAttr(nsGkAtoms::disabled, aDisabled, aRv);
|
||||
}
|
||||
|
||||
if (StyleSheet* ss = GetSheet()) {
|
||||
ss->SetDisabled(aDisabled);
|
||||
}
|
||||
@@ -117,11 +128,11 @@ HTMLLinkElement::SetDisabled(bool aDisabled)
|
||||
NS_IMETHODIMP
|
||||
HTMLLinkElement::SetMozDisabled(bool aDisabled)
|
||||
{
|
||||
SetDisabled(aDisabled);
|
||||
return NS_OK;
|
||||
ErrorResult rv;
|
||||
SetDisabled(aDisabled, rv);
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
|
||||
NS_IMPL_STRING_ATTR(HTMLLinkElement, Charset, charset)
|
||||
NS_IMPL_URI_ATTR(HTMLLinkElement, Href, href)
|
||||
NS_IMPL_STRING_ATTR(HTMLLinkElement, Hreflang, hreflang)
|
||||
@@ -369,7 +380,8 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
aName == nsGkAtoms::rel ||
|
||||
aName == nsGkAtoms::title ||
|
||||
aName == nsGkAtoms::media ||
|
||||
aName == nsGkAtoms::type)) {
|
||||
aName == nsGkAtoms::type ||
|
||||
(LINK_DISABLED && aName == nsGkAtoms::disabled))) {
|
||||
bool dropSheet = false;
|
||||
if (aName == nsGkAtoms::rel) {
|
||||
nsAutoString value;
|
||||
@@ -396,17 +408,24 @@ HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
dropSheet ||
|
||||
(aName == nsGkAtoms::title ||
|
||||
aName == nsGkAtoms::media ||
|
||||
aName == nsGkAtoms::type));
|
||||
aName == nsGkAtoms::type ||
|
||||
(LINK_DISABLED && aName == nsGkAtoms::disabled)));
|
||||
}
|
||||
} else {
|
||||
// Since removing href or rel makes us no longer link to a
|
||||
// stylesheet, force updates for those too.
|
||||
// If the disabled attribute is removed from a link element, the
|
||||
// stylesheet may be explicitly enabled.
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
if (aName == nsGkAtoms::disabled && LINK_DISABLED) {
|
||||
mExplicitlyEnabled = true;
|
||||
}
|
||||
// Since removing href or rel makes us no longer link to a
|
||||
// stylesheet, force updates for those too.
|
||||
if (aName == nsGkAtoms::href ||
|
||||
aName == nsGkAtoms::rel ||
|
||||
aName == nsGkAtoms::title ||
|
||||
aName == nsGkAtoms::media ||
|
||||
aName == nsGkAtoms::type) {
|
||||
aName == nsGkAtoms::type ||
|
||||
(LINK_DISABLED && aName == nsGkAtoms::disabled)) {
|
||||
UpdateStyleSheetInternal(nullptr, nullptr, true);
|
||||
}
|
||||
if (aName == nsGkAtoms::href ||
|
||||
@@ -499,13 +518,15 @@ HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate)
|
||||
bool* aIsAlternate,
|
||||
bool* aIsExplicitlyEnabled)
|
||||
{
|
||||
aTitle.Truncate();
|
||||
aType.Truncate();
|
||||
aMedia.Truncate();
|
||||
*aIsScoped = false;
|
||||
*aIsAlternate = false;
|
||||
*aIsExplicitlyEnabled = false;
|
||||
|
||||
nsAutoString rel;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::rel, rel);
|
||||
@@ -515,6 +536,20 @@ HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
|
||||
return;
|
||||
}
|
||||
|
||||
if (LINK_DISABLED) {
|
||||
|
||||
// Is the link disabled?
|
||||
if (Disabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Is it explicitly enabled?
|
||||
if (mExplicitlyEnabled) {
|
||||
*aIsExplicitlyEnabled = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsAutoString title;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
|
||||
title.CompressWhitespace();
|
||||
|
||||
@@ -84,8 +84,8 @@ public:
|
||||
virtual bool HasDeferredDNSPrefetchRequest() override;
|
||||
|
||||
// WebIDL
|
||||
bool Disabled();
|
||||
void SetDisabled(bool aDisabled);
|
||||
bool Disabled() const;
|
||||
void SetDisabled(bool aDisabled, ErrorResult& aRv);
|
||||
// XPCOM GetHref is fine.
|
||||
void SetHref(const nsAString& aHref, ErrorResult& aRv)
|
||||
{
|
||||
@@ -179,10 +179,18 @@ protected:
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate) override;
|
||||
protected:
|
||||
bool* aIsAlternate,
|
||||
bool* aIsExplicitlyEnabled) override;
|
||||
|
||||
RefPtr<nsDOMTokenList> mRelList;
|
||||
|
||||
// The "explicitly enabled" flag. This flag is set whenever the 'disabled'
|
||||
// attribute is explicitly unset, and makes alternate stylesheets not be
|
||||
// disabled by default anymore.
|
||||
//
|
||||
// See https://github.com/whatwg/html/issues/3840#issuecomment-481034206.
|
||||
bool mExplicitlyEnabled = false;
|
||||
|
||||
private:
|
||||
RefPtr<ImportLoader> mImportLoader;
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "mozilla/dom/HTMLSourceElement.h"
|
||||
#include "mozilla/dom/ElementInlines.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
@@ -1245,7 +1246,18 @@ void HTMLMediaElement::NoSupportedMediaSourceError(const nsACString& aErrorDetai
|
||||
if (mDecoder) {
|
||||
ShutdownDecoder();
|
||||
}
|
||||
mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED, aErrorDetails);
|
||||
|
||||
// aErrorDetails can include sensitive details like MimeType or HTTP Status
|
||||
// Code. We should not leak this and pass a Generic Error Message unless the
|
||||
// user has explicitly enabled error reporting for debugging purposes.
|
||||
bool reportDetails = Preferences::GetBool("media.sourceErrorDetails.enabled", false);
|
||||
if (reportDetails) {
|
||||
mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED, aErrorDetails);
|
||||
} else {
|
||||
mErrorSink->SetError(MEDIA_ERR_SRC_NOT_SUPPORTED,
|
||||
NS_LITERAL_CSTRING("Failed to open media"));
|
||||
}
|
||||
|
||||
ChangeDelayLoadStatus(false);
|
||||
UpdateAudioChannelPlayingState();
|
||||
RejectPromises(TakePendingPlayPromises(), NS_ERROR_DOM_MEDIA_NOT_SUPPORTED_ERR);
|
||||
|
||||
@@ -279,12 +279,20 @@ HTMLScriptElement::GetScriptCharset(nsAString& charset)
|
||||
}
|
||||
|
||||
void
|
||||
HTMLScriptElement::FreezeUriAsyncDefer()
|
||||
HTMLScriptElement::FreezeExecutionAttrs(nsIDocument* aOwnerDoc)
|
||||
{
|
||||
if (mFrozen) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mIsModule && !mAsync && !mDefer && !mExternal);
|
||||
|
||||
// Determine whether this is a classic script or a module script.
|
||||
nsAutoString type;
|
||||
GetScriptType(type);
|
||||
mIsModule = aOwnerDoc->ModuleScriptsEnabled() &&
|
||||
!type.IsEmpty() && type.LowerCaseEqualsASCII("module");
|
||||
|
||||
// variation of this code in nsSVGScriptElement - check if changes
|
||||
// need to be transfered when modifying. Note that we don't use GetSrc here
|
||||
// because it will return the base URL when the attr value is "".
|
||||
@@ -299,14 +307,13 @@ HTMLScriptElement::FreezeUriAsyncDefer()
|
||||
|
||||
// At this point mUri will be null for invalid URLs.
|
||||
mExternal = true;
|
||||
|
||||
bool defer, async;
|
||||
GetAsync(&async);
|
||||
GetDefer(&defer);
|
||||
|
||||
mDefer = !async && defer;
|
||||
mAsync = async;
|
||||
}
|
||||
|
||||
bool defer, async;
|
||||
GetAsync(&async);
|
||||
mAsync = (mExternal || mIsModule) && async;
|
||||
GetDefer(&defer);
|
||||
mDefer = mExternal && !async && defer;
|
||||
|
||||
mFrozen = true;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public:
|
||||
virtual bool GetScriptType(nsAString& type) override;
|
||||
virtual void GetScriptText(nsAString& text) override;
|
||||
virtual void GetScriptCharset(nsAString& charset) override;
|
||||
virtual void FreezeUriAsyncDefer() override;
|
||||
virtual void FreezeExecutionAttrs(nsIDocument* aOwnerDoc) override;
|
||||
virtual CORSMode GetCORSMode() const override;
|
||||
|
||||
// nsIContent
|
||||
|
||||
@@ -66,7 +66,7 @@ HTMLStyleElement::GetMozDisabled(bool* aDisabled)
|
||||
}
|
||||
|
||||
bool
|
||||
HTMLStyleElement::Disabled()
|
||||
HTMLStyleElement::Disabled() const
|
||||
{
|
||||
StyleSheet* ss = GetSheet();
|
||||
return ss && ss->Disabled();
|
||||
@@ -222,12 +222,14 @@ HTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate)
|
||||
bool* aIsAlternate,
|
||||
bool* aIsExplicitlyEnabled)
|
||||
{
|
||||
aTitle.Truncate();
|
||||
aType.Truncate();
|
||||
aMedia.Truncate();
|
||||
*aIsAlternate = false;
|
||||
*aIsExplicitlyEnabled = false;
|
||||
|
||||
nsAutoString title;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
|
||||
|
||||
@@ -58,7 +58,7 @@ public:
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
|
||||
bool Disabled();
|
||||
bool Disabled() const;
|
||||
void SetDisabled(bool aDisabled);
|
||||
void SetMedia(const nsAString& aMedia, ErrorResult& aError)
|
||||
{
|
||||
@@ -87,7 +87,8 @@ protected:
|
||||
nsAString& aType,
|
||||
nsAString& aMedia,
|
||||
bool* aIsScoped,
|
||||
bool* aIsAlternate) override;
|
||||
bool* aIsAlternate,
|
||||
bool* aIsExplicitlyEnabled) override;
|
||||
/**
|
||||
* Common method to call from the various mutation observer methods.
|
||||
* aContent is a content node that's either the one that changed or its
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// Map html attribute string values to TextTrackKind enums.
|
||||
static constexpr nsAttrValue::EnumTable kKindTable[] = {
|
||||
static nsAttrValue::EnumTable kKindTable[] = {
|
||||
{ "subtitles", static_cast<int16_t>(TextTrackKind::Subtitles) },
|
||||
{ "captions", static_cast<int16_t>(TextTrackKind::Captions) },
|
||||
{ "descriptions", static_cast<int16_t>(TextTrackKind::Descriptions) },
|
||||
@@ -68,7 +68,7 @@ static constexpr nsAttrValue::EnumTable kKindTable[] = {
|
||||
|
||||
// Invalid values are treated as "metadata" in ParseAttribute, but if no value
|
||||
// at all is specified, it's treated as "subtitles" in GetKind
|
||||
static constexpr const nsAttrValue::EnumTable* kKindTableInvalidValueDefault = &kKindTable[4];
|
||||
static const nsAttrValue::EnumTable* kKindTableInvalidValueDefault = &kKindTable[4];
|
||||
|
||||
class WindowDestroyObserver final : public nsIObserver
|
||||
{
|
||||
|
||||
@@ -1449,29 +1449,57 @@ nsGenericHTMLElement::MapImageMarginAttributeInto(const nsMappedAttributes* aAtt
|
||||
|
||||
void
|
||||
nsGenericHTMLElement::MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData)
|
||||
nsRuleData* aData,
|
||||
bool aMapAspectRatio)
|
||||
{
|
||||
if (!(aData->mSIDs & NS_STYLE_INHERIT_BIT(Position)))
|
||||
return;
|
||||
|
||||
auto* aWidth = aAttributes->GetAttr(nsGkAtoms::width);
|
||||
auto* aHeight = aAttributes->GetAttr(nsGkAtoms::height);
|
||||
|
||||
// width: value
|
||||
nsCSSValue* width = aData->ValueForWidth();
|
||||
if (width->GetUnit() == eCSSUnit_Null) {
|
||||
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::width);
|
||||
if (value && value->Type() == nsAttrValue::eInteger)
|
||||
width->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
|
||||
else if (value && value->Type() == nsAttrValue::ePercent)
|
||||
width->SetPercentValue(value->GetPercentValue());
|
||||
if (aWidth) {
|
||||
nsCSSValue* cWidth = aData->ValueForWidth();
|
||||
if (cWidth->GetUnit() == eCSSUnit_Null) {
|
||||
if (aWidth->Type() == nsAttrValue::eInteger)
|
||||
cWidth->SetFloatValue((float)aWidth->GetIntegerValue(), eCSSUnit_Pixel);
|
||||
else if (aWidth->Type() == nsAttrValue::ePercent)
|
||||
cWidth->SetPercentValue(aWidth->GetPercentValue());
|
||||
}
|
||||
}
|
||||
|
||||
// height: value
|
||||
nsCSSValue* height = aData->ValueForHeight();
|
||||
if (height->GetUnit() == eCSSUnit_Null) {
|
||||
const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::height);
|
||||
if (value && value->Type() == nsAttrValue::eInteger)
|
||||
height->SetFloatValue((float)value->GetIntegerValue(), eCSSUnit_Pixel);
|
||||
else if (value && value->Type() == nsAttrValue::ePercent)
|
||||
height->SetPercentValue(value->GetPercentValue());
|
||||
if (aHeight) {
|
||||
nsCSSValue* cHeight = aData->ValueForHeight();
|
||||
if (cHeight->GetUnit() == eCSSUnit_Null) {
|
||||
if (aHeight->Type() == nsAttrValue::eInteger)
|
||||
cHeight->SetFloatValue((float)aHeight->GetIntegerValue(), eCSSUnit_Pixel);
|
||||
else if (aHeight->Type() == nsAttrValue::ePercent)
|
||||
cHeight->SetPercentValue(aHeight->GetPercentValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (Preferences::GetBool("layout.css.intrinsic-aspect-ratio.enabled") &&
|
||||
aMapAspectRatio && aWidth && aHeight) {
|
||||
Maybe<double> w;
|
||||
if (aWidth->Type() == nsAttrValue::eInteger) {
|
||||
w.emplace(aWidth->GetIntegerValue());
|
||||
} else if (aWidth->Type() == nsAttrValue::eDoubleValue) {
|
||||
w.emplace(aWidth->GetDoubleValue());
|
||||
}
|
||||
|
||||
Maybe<double> h;
|
||||
if (aHeight->Type() == nsAttrValue::eInteger) {
|
||||
h.emplace(aHeight->GetIntegerValue());
|
||||
} else if (aHeight->Type() == nsAttrValue::eDoubleValue) {
|
||||
h.emplace(aHeight->GetDoubleValue());
|
||||
}
|
||||
|
||||
if (w && h && *w != 0 && *h != 0) {
|
||||
nsCSSValue* aspect_ratio = aData->ValueForAspectRatio();
|
||||
aspect_ratio->SetFloatValue((float(*w) / float(*h)), eCSSUnit_Number);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -712,10 +712,12 @@ public:
|
||||
*
|
||||
* @param aAttributes the list of attributes to map
|
||||
* @param aData the returned rule data [INOUT]
|
||||
* @param aMapAspectRatio map width and height attributes on aspect-ratio
|
||||
* @see GetAttributeMappingFunction
|
||||
*/
|
||||
static void MapImageSizeAttributesInto(const nsMappedAttributes* aAttributes,
|
||||
nsRuleData* aData);
|
||||
nsRuleData* aData,
|
||||
bool = false);
|
||||
/**
|
||||
* Helper to map the background attribute
|
||||
* into a style struct.
|
||||
|
||||
@@ -1511,6 +1511,9 @@ nsHTMLDocument::Open(JSContext* cx,
|
||||
// document again otherwise the document could have a non-zero onload block
|
||||
// count without the onload blocker request being in the loadgroup.
|
||||
EnsureOnloadBlocker();
|
||||
|
||||
// Throw away loaded modules created for the previous global.
|
||||
ScriptLoader()->ClearModuleMap();
|
||||
}
|
||||
|
||||
// Step 8 - Clear all event listeners out of our DOM tree
|
||||
|
||||
@@ -168,7 +168,6 @@ HTML_TAG("listing", "Pre");
|
||||
HTML_TAG("main", "");
|
||||
HTML_TAG("map", "Map");
|
||||
HTML_TAG("mark", "");
|
||||
HTML_TAG("marquee", "Div");
|
||||
HTML_TAG("menu", "Menu");
|
||||
HTML_TAG("meta", "Meta");
|
||||
HTML_TAG("meter", "Meter");
|
||||
|
||||
@@ -117,7 +117,7 @@ var elementNames =
|
||||
'input','ins','isindex','kbd','keygen','label','li','legend','link','menu',
|
||||
'multicol','noscript','noframes','object','spacer','table','td','td','th',
|
||||
'thead','tfoot','tr','textarea','select','option','spacer','param',
|
||||
'marquee','hr','title','hx','tt','u','ul','var','wbr','sub','sup','cite',
|
||||
'hr','title','hx','tt','u','ul','var','wbr','sub','sup','cite',
|
||||
'code','q','nobr','ol','p','pre','s','samp','small','body','html','map',
|
||||
'bdo','legend','listing','style','script','tbody','caption','meta',
|
||||
'optgroup','button','span','strike','strong','td'].sort();
|
||||
|
||||
@@ -270,7 +270,7 @@ const uint32_t kDEBUGTransactionThreadSleepMS = 0;
|
||||
#endif
|
||||
|
||||
template <size_t N>
|
||||
constexpr size_t
|
||||
size_t
|
||||
LiteralStringLength(const char (&aArr)[N])
|
||||
{
|
||||
static_assert(N, "Zero-length string literal?!");
|
||||
@@ -2905,11 +2905,11 @@ UpgradeKeyFunction::CopyAndUpgradeKeyBufferInternal(const uint8_t*& aSource,
|
||||
MOZ_ASSERT(aDestination);
|
||||
MOZ_ASSERT(aTagOffset <= Key::kMaxArrayCollapse);
|
||||
|
||||
static constexpr uint8_t kOldNumberTag = 0x1;
|
||||
static constexpr uint8_t kOldDateTag = 0x2;
|
||||
static constexpr uint8_t kOldStringTag = 0x3;
|
||||
static constexpr uint8_t kOldArrayTag = 0x4;
|
||||
static constexpr uint8_t kOldMaxType = kOldArrayTag;
|
||||
static uint8_t kOldNumberTag = 0x1;
|
||||
static uint8_t kOldDateTag = 0x2;
|
||||
static uint8_t kOldStringTag = 0x3;
|
||||
static uint8_t kOldArrayTag = 0x4;
|
||||
static uint8_t kOldMaxType = kOldArrayTag;
|
||||
|
||||
if (NS_WARN_IF(aRecursionDepth > Key::kMaxRecursionDepth)) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
|
||||
@@ -6,10 +6,11 @@
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'InputMethod.manifest',
|
||||
'Keyboard.jsm',
|
||||
'MozKeyboard.js',
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES += ['Keyboard.jsm']
|
||||
|
||||
JAR_MANIFESTS += ['jar.mn']
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['mochitest/chrome.ini']
|
||||
@@ -277,7 +277,7 @@ protected:
|
||||
};
|
||||
|
||||
struct BlockOwner {
|
||||
constexpr BlockOwner() {}
|
||||
BlockOwner() {}
|
||||
|
||||
// The stream that owns this block, or null if the block is free.
|
||||
MediaCacheStream* mStream = nullptr;
|
||||
|
||||
@@ -652,7 +652,7 @@ public:
|
||||
* and boolean to control if we want input/output
|
||||
*/
|
||||
bool mInputWanted;
|
||||
int mInputDeviceID;
|
||||
Atomic<int> mInputDeviceID;
|
||||
bool mOutputWanted;
|
||||
int mOutputDeviceID;
|
||||
// Maps AudioDataListeners to a usecount of streams using the listener
|
||||
|
||||
@@ -49,10 +49,10 @@ public:
|
||||
void SetCDMProxy(CDMProxy* aProxy);
|
||||
#endif
|
||||
|
||||
static constexpr int kYUV400 = 0;
|
||||
static constexpr int kYUV420 = 1;
|
||||
static constexpr int kYUV422 = 2;
|
||||
static constexpr int kYUV444 = 3;
|
||||
static const int kYUV400 = 0;
|
||||
static const int kYUV420 = 1;
|
||||
static const int kYUV422 = 2;
|
||||
static const int kYUV444 = 3;
|
||||
|
||||
private:
|
||||
virtual ~PDMFactory();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Google Inc. All rights reserved.
|
||||
* Copyright (C) 2020 M. Straver. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -72,6 +73,7 @@ HRTFDatabaseLoader::HRTFDatabaseLoader(float sampleRate)
|
||||
, m_threadLock("HRTFDatabaseLoader")
|
||||
, m_databaseLoaderThread(nullptr)
|
||||
, m_databaseSampleRate(sampleRate)
|
||||
, m_databaseLoaded(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
@@ -164,6 +166,7 @@ void HRTFDatabaseLoader::load()
|
||||
MOZ_ASSERT(!m_hrtfDatabase.get(), "Called twice");
|
||||
// Load the default HRTF database.
|
||||
m_hrtfDatabase = HRTFDatabase::create(m_databaseSampleRate);
|
||||
m_databaseLoaded = true;
|
||||
// Notifies the main thread of completion. See loadAsynchronously().
|
||||
Release();
|
||||
}
|
||||
|
||||
Loaded 100 of 439 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user