Merge mozilla-central to autoland

--HG--
rename : third_party/rust/euclid/src/matrix2d.rs => third_party/rust/euclid-0.13.0/src/matrix2d.rs
rename : third_party/rust/euclid/src/matrix4d.rs => third_party/rust/euclid-0.13.0/src/matrix4d.rs
This commit is contained in:
Carsten "Tomcat" Book 2017-06-14 14:51:37 +02:00
Родитель 00e2b11a13 5e8c1546ec
Коммит 865741ad85
108 изменённых файлов: 2013 добавлений и 1032 удалений

Просмотреть файл

@ -697,6 +697,12 @@ getRoleCB(AtkObject *aAtkObj)
aAtkObj->role = ATK_ROLE_LIST_ITEM; aAtkObj->role = ATK_ROLE_LIST_ITEM;
else if (aAtkObj->role == ATK_ROLE_MATH && !IsAtkVersionAtLeast(2, 12)) else if (aAtkObj->role == ATK_ROLE_MATH && !IsAtkVersionAtLeast(2, 12))
aAtkObj->role = ATK_ROLE_SECTION; aAtkObj->role = ATK_ROLE_SECTION;
else if (aAtkObj->role == ATK_ROLE_COMMENT && !IsAtkVersionAtLeast(2, 12))
aAtkObj->role = ATK_ROLE_SECTION;
else if (aAtkObj->role == ATK_ROLE_LANDMARK && !IsAtkVersionAtLeast(2, 12))
aAtkObj->role = ATK_ROLE_SECTION;
else if (aAtkObj->role == ATK_ROLE_FOOTNOTE && !IsAtkVersionAtLeast(2, 25, 2))
aAtkObj->role = ATK_ROLE_SECTION;
else if (aAtkObj->role == ATK_ROLE_STATIC && !IsAtkVersionAtLeast(2, 16)) else if (aAtkObj->role == ATK_ROLE_STATIC && !IsAtkVersionAtLeast(2, 16))
aAtkObj->role = ATK_ROLE_TEXT; aAtkObj->role = ATK_ROLE_TEXT;
else if ((aAtkObj->role == ATK_ROLE_MATH_FRACTION || else if ((aAtkObj->role == ATK_ROLE_MATH_FRACTION ||

Просмотреть файл

@ -26,7 +26,7 @@ extern "C" __attribute__((weak,visibility("default"))) int atk_bridge_adaptor_in
using namespace mozilla; using namespace mozilla;
using namespace mozilla::a11y; using namespace mozilla::a11y;
int atkMajorVersion = 1, atkMinorVersion = 12; int atkMajorVersion = 1, atkMinorVersion = 12, atkMicroVersion = 0;
GType (*gAtkTableCellGetTypeFunc)(); GType (*gAtkTableCellGetTypeFunc)();
@ -168,8 +168,11 @@ a11y::PlatformInit()
if (version) { if (version) {
char* endPtr = nullptr; char* endPtr = nullptr;
atkMajorVersion = strtol(version, &endPtr, 10); atkMajorVersion = strtol(version, &endPtr, 10);
if (*endPtr == '.') if (atkMajorVersion != 0L) {
atkMinorVersion = strtol(endPtr + 1, &endPtr, 10); atkMinorVersion = strtol(endPtr + 1, &endPtr, 10);
if (atkMinorVersion != 0L)
atkMicroVersion = strtol(endPtr + 1, &endPtr, 10);
}
} }
} }

Просмотреть файл

@ -75,17 +75,19 @@ mozilla::a11y::AccessibleOrProxy GetInternalObj(AtkObject* aObj);
AtkObject* GetWrapperFor(mozilla::a11y::ProxyAccessible* aProxy); AtkObject* GetWrapperFor(mozilla::a11y::ProxyAccessible* aProxy);
AtkObject* GetWrapperFor(mozilla::a11y::AccessibleOrProxy aObj); AtkObject* GetWrapperFor(mozilla::a11y::AccessibleOrProxy aObj);
extern int atkMajorVersion, atkMinorVersion; extern int atkMajorVersion, atkMinorVersion, atkMicroVersion;
/** /**
* Return true if the loaded version of libatk-1.0.so is at least * Return true if the loaded version of libatk-1.0.so is at least
* aMajor.aMinor.0. * aMajor.aMinor.aMicro.
*/ */
static inline bool static inline bool
IsAtkVersionAtLeast(int aMajor, int aMinor) IsAtkVersionAtLeast(int aMajor, int aMinor, int aMicro=0)
{ {
return aMajor < atkMajorVersion || return aMajor < atkMajorVersion ||
(aMajor == atkMajorVersion && aMinor <= atkMinorVersion); (aMajor == atkMajorVersion &&
(aMinor < atkMinorVersion ||
(aMinor == atkMinorVersion && aMicro <= atkMicroVersion)));
} }
// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a // This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a

Просмотреть файл

@ -186,6 +186,396 @@ static const nsRoleMapEntry sWAIRoleMaps[] =
eList, eList,
states::READONLY states::READONLY
}, },
{ // doc-abstract
&nsGkAtoms::docAbstract,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-acknowledgments
&nsGkAtoms::docAcknowledgments,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-afterword
&nsGkAtoms::docAfterword,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-appendix
&nsGkAtoms::docAppendix,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-backlink
&nsGkAtoms::docBacklink,
roles::LINK,
kUseMapRole,
eNoValue,
eJumpAction,
eNoLiveAttr,
kGenericAccType,
states::LINKED
},
{ // doc-biblioentry
&nsGkAtoms::docBiblioentry,
roles::LISTITEM,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
states::READONLY
},
{ // doc-bibliography
&nsGkAtoms::docBibliography,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-biblioref
&nsGkAtoms::docBiblioref,
roles::LINK,
kUseMapRole,
eNoValue,
eJumpAction,
eNoLiveAttr,
kGenericAccType,
states::LINKED
},
{ // doc-chapter
&nsGkAtoms::docChapter,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-colophon
&nsGkAtoms::docColophon,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-conclusion
&nsGkAtoms::docConclusion,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-cover
&nsGkAtoms::docCover,
roles::GRAPHIC,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-credit
&nsGkAtoms::docCredit,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-credits
&nsGkAtoms::docCredits,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-dedication
&nsGkAtoms::docDedication,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-endnote
&nsGkAtoms::docEndnote,
roles::LISTITEM,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
states::READONLY
},
{ // doc-endnotes
&nsGkAtoms::docEndnotes,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-epigraph
&nsGkAtoms::docEpigraph,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-epilogue
&nsGkAtoms::docEpilogue,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-errata
&nsGkAtoms::docErrata,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-example
&nsGkAtoms::docExample,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-footnote
&nsGkAtoms::docFootnote,
roles::FOOTNOTE,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-foreword
&nsGkAtoms::docForeword,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-glossary
&nsGkAtoms::docGlossary,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-glossref
&nsGkAtoms::docGlossref,
roles::LINK,
kUseMapRole,
eNoValue,
eJumpAction,
eNoLiveAttr,
kGenericAccType,
states::LINKED
},
{ // doc-index
&nsGkAtoms::docIndex,
roles::NAVIGATION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-introduction
&nsGkAtoms::docIntroduction,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-noteref
&nsGkAtoms::docNoteref,
roles::LINK,
kUseMapRole,
eNoValue,
eJumpAction,
eNoLiveAttr,
kGenericAccType,
states::LINKED
},
{ // doc-notice
&nsGkAtoms::docNotice,
roles::NOTE,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-pagebreak
&nsGkAtoms::docPagebreak,
roles::SEPARATOR,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-pagelist
&nsGkAtoms::docPagelist,
roles::NAVIGATION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-part
&nsGkAtoms::docPart,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-preface
&nsGkAtoms::docPreface,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-prologue
&nsGkAtoms::docPrologue,
roles::LANDMARK,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // doc-pullquote
&nsGkAtoms::docPullquote,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-qna
&nsGkAtoms::docQna,
roles::SECTION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-subtitle
&nsGkAtoms::docSubtitle,
roles::HEADING,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-tip
&nsGkAtoms::docTip,
roles::NOTE,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
kGenericAccType,
kNoReqStates
},
{ // doc-toc
&nsGkAtoms::docToc,
roles::NAVIGATION,
kUseMapRole,
eNoValue,
eNoAction,
eNoLiveAttr,
eLandmark,
kNoReqStates
},
{ // document { // document
&nsGkAtoms::document, &nsGkAtoms::document,
roles::DOCUMENT, roles::DOCUMENT,

Просмотреть файл

@ -982,7 +982,25 @@ enum Role {
*/ */
SUMMARY = 168, SUMMARY = 168,
LAST_ROLE = SUMMARY /**
* An ARIA landmark. See related NAVIGATION role.
*/
LANDMARK = 169,
/**
* A specific type of ARIA landmark. The ability to distinguish navigation
* landmarks from other types of landmarks is, for example, needed on macOS
* where specific AXSubrole and AXRoleDescription for navigation landmarks
* are used.
*/
NAVIGATION = 170,
/**
* An object that contains the text of a footnote.
*/
FOOTNOTE = 171,
LAST_ROLE = FOOTNOTE
}; };
} // namespace role } // namespace role

Просмотреть файл

@ -1002,7 +1002,7 @@ ROLE(EMBEDDED_OBJECT,
ROLE(NOTE, ROLE(NOTE,
"note", "note",
ATK_ROLE_SECTION, ATK_ROLE_COMMENT,
NSAccessibilityGroupRole, NSAccessibilityGroupRole,
USE_ROLE_STRING, USE_ROLE_STRING,
IA2_ROLE_NOTE, IA2_ROLE_NOTE,
@ -1368,3 +1368,26 @@ ROLE(SUMMARY,
ROLE_SYSTEM_PUSHBUTTON, ROLE_SYSTEM_PUSHBUTTON,
eNameFromSubtreeRule) eNameFromSubtreeRule)
ROLE(LANDMARK,
"landmark",
ATK_ROLE_LANDMARK,
NSAccessibilityGroupRole,
USE_ROLE_STRING,
IA2_ROLE_LANDMARK,
eNoNameRule)
ROLE(NAVIGATION,
"navigation",
ATK_ROLE_LANDMARK,
NSAccessibilityGroupRole,
USE_ROLE_STRING,
IA2_ROLE_LANDMARK,
eNoNameRule)
ROLE(FOOTNOTE,
"footnote",
ATK_ROLE_FOOTNOTE,
NSAccessibilityGroupRole,
USE_ROLE_STRING,
IA2_ROLE_FOOTNOTE,
eNoNameRule)

Просмотреть файл

@ -977,4 +977,21 @@ interface nsIAccessibleRole : nsISupports
* SUMMARY role. * SUMMARY role.
*/ */
const unsigned long ROLE_SUMMARY = 168; const unsigned long ROLE_SUMMARY = 168;
/**
* An ARIA landmark. See related NAVIGATION role.
*/
const unsigned long ROLE_LANDMARK = 169;
/**
* A specific type of ARIA landmark. The ability to distinguish navigation
* landmarks from other types of landmarks is needed because macOS has a
* specific AXSubrole and AXRoleDescription for navigation landmarks.
*/
const unsigned long ROLE_NAVIGATION = 170;
/**
* An object that contains the text of a footnote.
*/
const unsigned long ROLE_FOOTNOTE = 171;
}; };

Просмотреть файл

@ -726,6 +726,8 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
else if (proxy) else if (proxy)
landmark = proxy->LandmarkRole(); landmark = proxy->LandmarkRole();
// HTML Elements treated as landmarks
// XXX bug 1371712
if (landmark) { if (landmark) {
if (landmark == nsGkAtoms::application) if (landmark == nsGkAtoms::application)
return @"AXLandmarkApplication"; return @"AXLandmarkApplication";
@ -747,6 +749,13 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
return @"AXSearchField"; return @"AXSearchField";
} }
// macOS groups the specific landmark types of DPub ARIA into two broad
// categories with corresponding subroles: Navigation and region/container.
if (mRole == roles::NAVIGATION)
return @"AXLandmarkNavigation";
if (mRole == roles::LANDMARK)
return @"AXLandmarkRegion";
// Now, deal with widget roles // Now, deal with widget roles
nsIAtom* roleAtom = nullptr; nsIAtom* roleAtom = nullptr;
if (accWrap && accWrap->HasARIARole()) { if (accWrap && accWrap->HasARIARole()) {
@ -889,6 +898,17 @@ ConvertToNSArray(nsTArray<ProxyAccessible*>& aArray)
case roles::SUMMARY: case roles::SUMMARY:
return @"AXSummary"; return @"AXSummary";
case roles::NOTE:
return @"AXDocumentNote";
// macOS added an AXSubrole value to distinguish generic AXGroup objects
// from those which are AXGroups as a result of an explicit ARIA role,
// such as the non-landmark, non-listitem text containers in DPub ARIA.
case roles::SECTION:
if (roleAtom)
return @"AXApplicationGroup";
break;
default: default:
break; break;
} }

Просмотреть файл

@ -2,6 +2,7 @@
support-files = support-files =
!/accessible/tests/mochitest/*.js !/accessible/tests/mochitest/*.js
[test_dpub_aria_xml-roles.html]
[test_obj.html] [test_obj.html]
[test_obj_css.html] [test_obj_css.html]
[test_obj_css.xul] [test_obj_css.xul]

Просмотреть файл

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html>
<head>
<title>XML roles tests</title>
<link rel="stylesheet" type="text/css"
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript"
src="../attributes.js"></script>
<script type="application/javascript">
function doTest()
{
// DPub ARIA roles should be exposed via the xml-roles object attribute.
let dpub_attrs = [
'doc-abstract',
'doc-acknowledgments',
'doc-afterword',
'doc-appendix',
'doc-backlink',
'doc-biblioentry',
'doc-bibliography',
'doc-biblioref',
'doc-chapter',
'doc-colophon',
'doc-conclusion',
'doc-cover',
'doc-credit',
'doc-credits',
'doc-dedication',
'doc-endnote',
'doc-endnotes',
'doc-epigraph',
'doc-epilogue',
'doc-errata',
'doc-example',
'doc-footnote',
'doc-foreword',
'doc-glossary',
'doc-glossref',
'doc-index',
'doc-introduction',
'doc-noteref',
'doc-notice',
'doc-pagebreak',
'doc-pagelist',
'doc-part',
'doc-preface',
'doc-prologue',
'doc-pullquote',
'doc-qna',
'doc-subtitle',
'doc-tip',
'doc-toc'
];
for (let attr of dpub_attrs) {
testAttrs(attr, {"xml-roles" : attr}, true);
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1343537"
title="implement ARIA DPUB extension">
Bug 1343537
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<div id="doc-abstract" role="doc-abstract">abstract</div>
<div id="doc-acknowledgments" role="doc-acknowledgments">acknowledgments</div>
<div id="doc-afterword" role="doc-afterword">afterword</div>
<div id="doc-appendix" role="doc-appendix">appendix</div>
<div id="doc-backlink" role="doc-backlink">backlink</div>
<div id="doc-biblioentry" role="doc-biblioentry">biblioentry</div>
<div id="doc-bibliography" role="doc-bibliography">bibliography</div>
<div id="doc-biblioref" role="doc-biblioref">biblioref</div>
<div id="doc-chapter" role="doc-chapter">chapter</div>
<div id="doc-colophon" role="doc-colophon">colophon</div>
<div id="doc-conclusion" role="doc-conclusion">conclusion</div>
<div id="doc-cover" role="doc-cover">cover</div>
<div id="doc-credit" role="doc-credit">credit</div>
<div id="doc-credits" role="doc-credits">credits</div>
<div id="doc-dedication" role="doc-dedication">dedication</div>
<div id="doc-endnote" role="doc-endnote">endnote</div>
<div id="doc-endnotes" role="doc-endnotes">endnotes</div>
<div id="doc-epigraph" role="doc-epigraph">epigraph</div>
<div id="doc-epilogue" role="doc-epilogue">epilogue</div>
<div id="doc-errata" role="doc-errata">errata</div>
<div id="doc-example" role="doc-example">example</div>
<div id="doc-footnote" role="doc-footnote">footnote</div>
<div id="doc-foreword" role="doc-foreword">foreword</div>
<div id="doc-glossary" role="doc-glossary">glossary</div>
<div id="doc-glossref" role="doc-glossref">glossref</div>
<div id="doc-index" role="doc-index">index</div>
<div id="doc-introduction" role="doc-introduction">introduction</div>
<div id="doc-noteref" role="doc-noteref">noteref</div>
<div id="doc-notice" role="doc-notice">notice</div>
<div id="doc-pagebreak" role="doc-pagebreak">pagebreak</div>
<div id="doc-pagelist" role="doc-pagelist">pagelist</div>
<div id="doc-part" role="doc-part">part</div>
<div id="doc-preface" role="doc-preface">preface</div>
<div id="doc-prologue" role="doc-prologue">prologue</div>
<div id="doc-pullquote" role="doc-pullquote">pullquote</div>
<div id="doc-qna" role="doc-qna">qna</div>
<div id="doc-subtitle" role="doc-subtitle">subtitle</div>
<div id="doc-tip" role="doc-tip">tip</div>
<div id="doc-toc" role="doc-toc">toc</div>
</body>
</html>

Просмотреть файл

@ -28,6 +28,7 @@ const ROLE_ENTRY = nsIAccessibleRole.ROLE_ENTRY;
const ROLE_EQUATION = nsIAccessibleRole.ROLE_EQUATION; const ROLE_EQUATION = nsIAccessibleRole.ROLE_EQUATION;
const ROLE_FIGURE = nsIAccessibleRole.ROLE_FIGURE; const ROLE_FIGURE = nsIAccessibleRole.ROLE_FIGURE;
const ROLE_FOOTER = nsIAccessibleRole.ROLE_FOOTER; const ROLE_FOOTER = nsIAccessibleRole.ROLE_FOOTER;
const ROLE_FOOTNOTE = nsIAccessibleRole.ROLE_FOOTNOTE;
const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION; const ROLE_FLAT_EQUATION = nsIAccessibleRole.ROLE_FLAT_EQUATION;
const ROLE_FORM = nsIAccessibleRole.ROLE_FORM; const ROLE_FORM = nsIAccessibleRole.ROLE_FORM;
const ROLE_GRAPHIC = nsIAccessibleRole.ROLE_GRAPHIC; const ROLE_GRAPHIC = nsIAccessibleRole.ROLE_GRAPHIC;
@ -38,6 +39,7 @@ const ROLE_HEADING = nsIAccessibleRole.ROLE_HEADING;
const ROLE_IMAGE_MAP = nsIAccessibleRole.ROLE_IMAGE_MAP; const ROLE_IMAGE_MAP = nsIAccessibleRole.ROLE_IMAGE_MAP;
const ROLE_INTERNAL_FRAME = nsIAccessibleRole.ROLE_INTERNAL_FRAME; const ROLE_INTERNAL_FRAME = nsIAccessibleRole.ROLE_INTERNAL_FRAME;
const ROLE_LABEL = nsIAccessibleRole.ROLE_LABEL; const ROLE_LABEL = nsIAccessibleRole.ROLE_LABEL;
const ROLE_LANDMARK = nsIAccessibleRole.ROLE_LANDMARK;
const ROLE_LINK = nsIAccessibleRole.ROLE_LINK; const ROLE_LINK = nsIAccessibleRole.ROLE_LINK;
const ROLE_LIST = nsIAccessibleRole.ROLE_LIST; const ROLE_LIST = nsIAccessibleRole.ROLE_LIST;
const ROLE_LISTBOX = nsIAccessibleRole.ROLE_LISTBOX; const ROLE_LISTBOX = nsIAccessibleRole.ROLE_LISTBOX;
@ -79,6 +81,7 @@ const ROLE_MATHML_STACK_LINE = nsIAccessibleRole.ROLE_MATHML_STACK_LINE;
const ROLE_MENUBAR = nsIAccessibleRole.ROLE_MENUBAR; const ROLE_MENUBAR = nsIAccessibleRole.ROLE_MENUBAR;
const ROLE_MENUITEM = nsIAccessibleRole.ROLE_MENUITEM; const ROLE_MENUITEM = nsIAccessibleRole.ROLE_MENUITEM;
const ROLE_MENUPOPUP = nsIAccessibleRole.ROLE_MENUPOPUP; const ROLE_MENUPOPUP = nsIAccessibleRole.ROLE_MENUPOPUP;
const ROLE_NAVIGATION = nsIAccessibleRole.ROLE_NAVIGATION;
const ROLE_NOTHING = nsIAccessibleRole.ROLE_NOTHING; const ROLE_NOTHING = nsIAccessibleRole.ROLE_NOTHING;
const ROLE_NOTE = nsIAccessibleRole.ROLE_NOTE; const ROLE_NOTE = nsIAccessibleRole.ROLE_NOTE;
const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION; const ROLE_OPTION = nsIAccessibleRole.ROLE_OPTION;

Просмотреть файл

@ -5,6 +5,7 @@ support-files =
[test_aria.html] [test_aria.html]
[test_aria.xul] [test_aria.xul]
[test_dpub_aria.html]
[test_general.html] [test_general.html]
[test_general.xul] [test_general.xul]
[test_svg.html] [test_svg.html]

Просмотреть файл

@ -0,0 +1,116 @@
<!DOCTYPE html>
<html>
<head>
<title>Test DPub ARIA roles</title>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript"
src="../common.js"></script>
<script type="application/javascript"
src="../role.js"></script>
<script type="application/javascript">
function doTest()
{
// DPub ARIA role map.
testRole("doc-abstract", ROLE_SECTION);
testRole("doc-acknowledgments", ROLE_LANDMARK);
testRole("doc-afterword", ROLE_LANDMARK);
testRole("doc-appendix", ROLE_LANDMARK);
testRole("doc-backlink", ROLE_LINK);
testRole("doc-biblioentry", ROLE_LISTITEM);
testRole("doc-bibliography", ROLE_LANDMARK);
testRole("doc-biblioref", ROLE_LINK);
testRole("doc-chapter", ROLE_LANDMARK);
testRole("doc-colophon", ROLE_SECTION);
testRole("doc-conclusion", ROLE_LANDMARK);
testRole("doc-cover", ROLE_GRAPHIC);
testRole("doc-credit", ROLE_SECTION);
testRole("doc-credits", ROLE_LANDMARK);
testRole("doc-dedication", ROLE_SECTION);
testRole("doc-endnote", ROLE_LISTITEM);
testRole("doc-endnotes", ROLE_LANDMARK);
testRole("doc-epigraph", ROLE_SECTION);
testRole("doc-epilogue", ROLE_LANDMARK);
testRole("doc-errata", ROLE_LANDMARK);
testRole("doc-example", ROLE_SECTION);
testRole("doc-footnote", ROLE_FOOTNOTE);
testRole("doc-foreword", ROLE_LANDMARK);
testRole("doc-glossary", ROLE_LANDMARK);
testRole("doc-glossref", ROLE_LINK);
testRole("doc-index", ROLE_NAVIGATION);
testRole("doc-introduction", ROLE_LANDMARK);
testRole("doc-noteref", ROLE_LINK);
testRole("doc-notice", ROLE_NOTE);
testRole("doc-pagebreak", ROLE_SEPARATOR);
testRole("doc-pagelist", ROLE_NAVIGATION);
testRole("doc-part", ROLE_LANDMARK);
testRole("doc-preface", ROLE_LANDMARK);
testRole("doc-prologue", ROLE_LANDMARK);
testRole("doc-pullquote", ROLE_SECTION);
testRole("doc-qna", ROLE_SECTION);
testRole("doc-subtitle", ROLE_HEADING);
testRole("doc-tip", ROLE_NOTE);
testRole("doc-toc", ROLE_NAVIGATION);
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addA11yLoadEvent(doTest);
</script>
</head>
<body>
<a target="_blank"
href="https://bugzilla.mozilla.org/show_bug.cgi?id=1343537"
title="implement ARIA DPUB extension">
Bug 1343537
</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<div id="doc-abstract" role="doc-abstract">abstract</div>
<div id="doc-acknowledgments" role="doc-acknowledgments">acknowledgments</div>
<div id="doc-afterword" role="doc-afterword">afterword</div>
<div id="doc-appendix" role="doc-appendix">appendix</div>
<div id="doc-backlink" role="doc-backlink">backlink</div>
<div id="doc-biblioentry" role="doc-biblioentry">biblioentry</div>
<div id="doc-bibliography" role="doc-bibliography">bibliography</div>
<div id="doc-biblioref" role="doc-biblioref">biblioref</div>
<div id="doc-chapter" role="doc-chapter">chapter</div>
<div id="doc-colophon" role="doc-colophon">colophon</div>
<div id="doc-conclusion" role="doc-conclusion">conclusion</div>
<div id="doc-cover" role="doc-cover">cover</div>
<div id="doc-credit" role="doc-credit">credit</div>
<div id="doc-credits" role="doc-credits">credits</div>
<div id="doc-dedication" role="doc-dedication">dedication</div>
<div id="doc-endnote" role="doc-endnote">endnote</div>
<div id="doc-endnotes" role="doc-endnotes">endnotes</div>
<div id="doc-epigraph" role="doc-epigraph">epigraph</div>
<div id="doc-epilogue" role="doc-epilogue">epilogue</div>
<div id="doc-errata" role="doc-errata">errata</div>
<div id="doc-example" role="doc-example">example</div>
<div id="doc-footnote" role="doc-footnote">footnote</div>
<div id="doc-foreword" role="doc-foreword">foreword</div>
<div id="doc-glossary" role="doc-glossary">glossary</div>
<div id="doc-glossref" role="doc-glossref">glossref</div>
<div id="doc-index" role="doc-index">index</div>
<div id="doc-introduction" role="doc-introduction">introduction</div>
<div id="doc-noteref" role="doc-noteref">noteref</div>
<div id="doc-notice" role="doc-notice">notice</div>
<div id="doc-pagebreak" role="doc-pagebreak">pagebreak</div>
<div id="doc-pagelist" role="doc-pagelist">pagelist</div>
<div id="doc-part" role="doc-part">part</div>
<div id="doc-preface" role="doc-preface">preface</div>
<div id="doc-prologue" role="doc-prologue">prologue</div>
<div id="doc-pullquote" role="doc-pullquote">pullquote</div>
<div id="doc-qna" role="doc-qna">qna</div>
<div id="doc-subtitle" role="doc-subtitle">subtitle</div>
<div id="doc-tip" role="doc-tip">tip</div>
<div id="doc-toc" role="doc-toc">toc</div>
</body>
</html>

Просмотреть файл

@ -23,6 +23,8 @@ const {
const SHOW_GRID_AREAS = "devtools.gridinspector.showGridAreas"; const SHOW_GRID_AREAS = "devtools.gridinspector.showGridAreas";
const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers"; const SHOW_GRID_LINE_NUMBERS = "devtools.gridinspector.showGridLineNumbers";
const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines"; const SHOW_INFINITE_LINES_PREF = "devtools.gridinspector.showInfiniteLines";
// @remove after release 56 (See Bug 1355747)
const PROMOTE_COUNT_PREF = "devtools.promote.layoutview";
// Default grid colors. // Default grid colors.
const GRID_COLORS = [ const GRID_COLORS = [
@ -480,6 +482,9 @@ GridInspector.prototype = {
return; return;
} }
// @remove after release 56 (See Bug 1355747)
Services.prefs.setIntPref(PROMOTE_COUNT_PREF, 0);
this.inspector.reflowTracker.trackReflows(this, this.onReflow); this.inspector.reflowTracker.trackReflows(this, this.onReflow);
this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange); this.layoutInspector.on("grid-layout-changed", this.onGridLayoutChange);
this.updateGridPanel(); this.updateGridPanel();

Просмотреть файл

@ -18,6 +18,7 @@ const BoxModelTypes = require("devtools/client/inspector/boxmodel/types");
const GridTypes = require("devtools/client/inspector/grids/types"); const GridTypes = require("devtools/client/inspector/grids/types");
const Accordion = createFactory(require("./Accordion")); const Accordion = createFactory(require("./Accordion"));
const LayoutPromoteBar = createFactory(require("./LayoutPromoteBar"));
const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties"; const BOXMODEL_STRINGS_URI = "devtools/client/locales/boxmodel.properties";
const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI); const BOXMODEL_L10N = new LocalizationHelper(BOXMODEL_STRINGS_URI);
@ -41,6 +42,7 @@ const App = createClass({
showBoxModelProperties: PropTypes.bool.isRequired, showBoxModelProperties: PropTypes.bool.isRequired,
showGridOutline: PropTypes.bool.isRequired, showGridOutline: PropTypes.bool.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired, onHideBoxModelHighlighter: PropTypes.func.isRequired,
onPromoteLearnMoreClick: PropTypes.func.isRequired,
onSetGridOverlayColor: PropTypes.func.isRequired, onSetGridOverlayColor: PropTypes.func.isRequired,
onShowBoxModelEditor: PropTypes.func.isRequired, onShowBoxModelEditor: PropTypes.func.isRequired,
onShowBoxModelHighlighter: PropTypes.func.isRequired, onShowBoxModelHighlighter: PropTypes.func.isRequired,
@ -53,11 +55,16 @@ const App = createClass({
mixins: [ addons.PureRenderMixin ], mixins: [ addons.PureRenderMixin ],
render() { render() {
let { onPromoteLearnMoreClick } = this.props;
return dom.div( return dom.div(
{ {
id: "layout-container", id: "layout-container",
className: "devtools-monospace", className: "devtools-monospace",
}, },
LayoutPromoteBar({
onPromoteLearnMoreClick,
}),
Accordion({ Accordion({
items: [ items: [
{ {

Просмотреть файл

@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/**
* !!!! TO BE REMOVED AFTER RELEASE 56 !!!!
* !!!! !!!!
* !!!! This file is a temporary panel that should only be used for release 56 to !!!!
* !!!! promote the new layout panel. After release 56, it should be removed. !!!!
* !!!! See bug 1355747. !!!!
*/
const Services = require("Services");
const { addons, createClass, DOM: dom, PropTypes } =
require("devtools/client/shared/vendor/react");
const { LocalizationHelper } = require("devtools/shared/l10n");
const LAYOUT_STRINGS_URI = "devtools/client/locales/layout.properties";
const LAYOUT_L10N = new LocalizationHelper(LAYOUT_STRINGS_URI);
const SHOW_PROMOTE_BAR_PREF = "devtools.promote.layoutview.showPromoteBar";
module.exports = createClass({
displayName: "LayoutPromoteBar",
propTypes: {
onPromoteLearnMoreClick: PropTypes.func.isRequired,
},
mixins: [ addons.PureRenderMixin ],
getInitialState() {
return {
showPromoteBar: Services.prefs.getBoolPref(SHOW_PROMOTE_BAR_PREF)
};
},
onPromoteCloseButtonClick() {
Services.prefs.setBoolPref(SHOW_PROMOTE_BAR_PREF, false);
this.setState({ showPromoteBar: false });
},
render() {
let { onPromoteLearnMoreClick } = this.props;
let { showPromoteBar } = this.state;
return showPromoteBar ?
dom.div({ className: "layout-promote-bar" },
dom.span({ className: "layout-promote-info-icon" }),
dom.div({ className: "layout-promote-message" },
LAYOUT_L10N.getStr("layout.promoteMessage"),
dom.a(
{
className: "layout-promote-learn-more-link theme-link",
href: "#",
onClick: onPromoteLearnMoreClick,
},
LAYOUT_L10N.getStr("layout.learnMore")
)
),
dom.button(
{
className: "layout-promote-close-button devtools-button",
onClick: this.onPromoteCloseButtonClick,
}
)
)
:
null;
},
});

Просмотреть файл

@ -8,4 +8,5 @@ DevToolsModules(
'Accordion.css', 'Accordion.css',
'Accordion.js', 'Accordion.js',
'App.js', 'App.js',
'LayoutPromoteBar.js',
) )

Просмотреть файл

@ -16,12 +16,19 @@ const INSPECTOR_L10N =
new LocalizationHelper("devtools/client/locales/inspector.properties"); new LocalizationHelper("devtools/client/locales/inspector.properties");
const SHOW_GRID_OUTLINE_PREF = "devtools.gridinspector.showGridOutline"; const SHOW_GRID_OUTLINE_PREF = "devtools.gridinspector.showGridOutline";
// @remove after release 56 (See Bug 1355747)
const PROMOTE_COUNT_PREF = "devtools.promote.layoutview";
// @remove after release 56 (See Bug 1355747)
const GRID_LINK = "https://www.mozilla.org/en-US/developer/css-grid/?utm_source=gridtooltip&utm_medium=devtools&utm_campaign=cssgrid_layout";
function LayoutView(inspector, window) { function LayoutView(inspector, window) {
this.document = window.document; this.document = window.document;
this.inspector = inspector; this.inspector = inspector;
this.store = inspector.store; this.store = inspector.store;
this.onPromoteLearnMoreClick = this.onPromoteLearnMoreClick.bind(this);
this.init(); this.init();
} }
@ -56,6 +63,10 @@ LayoutView.prototype = {
onToggleShowInfiniteLines, onToggleShowInfiniteLines,
} = this.inspector.gridInspector.getComponentProps(); } = this.inspector.gridInspector.getComponentProps();
let {
onPromoteLearnMoreClick,
} = this;
let app = App({ let app = App({
getSwatchColorPickerTooltip, getSwatchColorPickerTooltip,
setSelectedNode, setSelectedNode,
@ -72,6 +83,7 @@ LayoutView.prototype = {
showGridOutline: Services.prefs.getBoolPref(SHOW_GRID_OUTLINE_PREF), showGridOutline: Services.prefs.getBoolPref(SHOW_GRID_OUTLINE_PREF),
onHideBoxModelHighlighter, onHideBoxModelHighlighter,
onPromoteLearnMoreClick,
onSetGridOverlayColor, onSetGridOverlayColor,
onShowBoxModelEditor, onShowBoxModelEditor,
onShowBoxModelHighlighter, onShowBoxModelHighlighter,
@ -87,10 +99,14 @@ LayoutView.prototype = {
}); });
let provider = createElement(Provider, { let provider = createElement(Provider, {
store: this.store,
id: "layoutview", id: "layoutview",
title: INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
key: "layoutview", key: "layoutview",
store: this.store,
title: INSPECTOR_L10N.getStr("inspector.sidebar.layoutViewTitle2"),
// @remove after release 56 (See Bug 1355747)
badge: Services.prefs.getIntPref(PROMOTE_COUNT_PREF) > 0 ?
INSPECTOR_L10N.getStr("inspector.sidebar.newBadge") : null,
showBadge: () => Services.prefs.getIntPref(PROMOTE_COUNT_PREF) > 0,
}, app); }, app);
let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar"); let defaultTab = Services.prefs.getCharPref("devtools.inspector.activeSidebar");
@ -112,6 +128,11 @@ LayoutView.prototype = {
this.store = null; this.store = null;
}, },
onPromoteLearnMoreClick() {
let browserWin = this.inspector.target.tab.ownerDocument.defaultView;
browserWin.openUILinkIn(GRID_LINK, "current");
}
}; };
module.exports = LayoutView; module.exports = LayoutView;

Просмотреть файл

@ -351,6 +351,11 @@ inspector.sidebar.computedViewTitle=Computed
# that corresponds to the tool displaying layout information defined in the page. # that corresponds to the tool displaying layout information defined in the page.
inspector.sidebar.layoutViewTitle2=Layout inspector.sidebar.layoutViewTitle2=Layout
# LOCALIZATION NOTE (inspector.sidebar.newBadge):
# This is the text of a promotion badge showed in the inspector sidebar, next to a panel
# name. Used to promote new/recent panels such as the layout panel.
inspector.sidebar.newBadge=new!
# LOCALIZATION NOTE (inspector.sidebar.animationInspectorTitle): # LOCALIZATION NOTE (inspector.sidebar.animationInspectorTitle):
# This is the title shown in a tab in the side panel of the Inspector panel # This is the title shown in a tab in the side panel of the Inspector panel
# that corresponds to the tool displaying animations defined in the page. # that corresponds to the tool displaying animations defined in the page.

Просмотреть файл

@ -46,3 +46,11 @@ layout.overlayGrid=Overlay Grid
# LOCALIZATION NOTE (layout.rowColumnPositions): The row and column position of a grid # LOCALIZATION NOTE (layout.rowColumnPositions): The row and column position of a grid
# cell shown in the grid cell infobar when hovering over the CSS grid outline. # cell shown in the grid cell infobar when hovering over the CSS grid outline.
layout.rowColumnPositions=Row %S / Column %S layout.rowColumnPositions=Row %S / Column %S
# LOCALIZATION NOTE (layout.promoteMessage): Text displayed in the promote bar for the
# layout panel.
layout.promoteMessage=Explore CSS Grids with the latest CSS Grid Inspector.
# LOCALIZATION NOTE (layout.learnMore): Text for the link displayed in the promote bar
# for the layout panel.
layout.learnMore=Learn more…

Просмотреть файл

@ -71,6 +71,13 @@ pref("devtools.fontinspector.enabled", true);
// Enable the Layout View // Enable the Layout View
pref("devtools.layoutview.enabled", false); pref("devtools.layoutview.enabled", false);
// Counter to promote the inspector layout view.
// @remove after release 56 (See Bug 1355747)
pref("devtools.promote.layoutview", 1);
// Whether or not to show the promote bar in the layout view
// @remove after release 56 (See Bug 1355747)
pref("devtools.promote.layoutview.showPromoteBar", true);
// Grid highlighter preferences // Grid highlighter preferences
pref("devtools.gridinspector.showGridAreas", false); pref("devtools.gridinspector.showGridAreas", false);
pref("devtools.gridinspector.showGridLineNumbers", false); pref("devtools.gridinspector.showGridLineNumbers", false);

Просмотреть файл

@ -20,16 +20,33 @@
.tabs .tabs-menu-item { .tabs .tabs-menu-item {
display: inline-block; display: inline-block;
position: relative;
} }
.tabs .tabs-menu-item a { .tabs .tabs-menu-item a {
display: block; display: flex;
justify-content: center;
padding: 4px 8px; padding: 4px 8px;
border: 1px solid transparent; border: 1px solid transparent;
text-decoration: none; text-decoration: none;
white-space: nowrap; white-space: nowrap;
} }
.tabs .tabs-menu-item .tab-badge {
color: var(--theme-highlight-blue);
font-size: 80%;
font-style: italic;
/* Tabs have a 15px padding start/end, so we set the margins here in order to center the
badge after the tab title, with a 5px effective margin. */
margin-inline-start: 5px;
margin-inline-end: -10px;
}
.tabs .tabs-menu-item.is-active .tab-badge {
/* Use the same color as the tab-item when active */
color: inherit;
}
/* To avoid "select all" commands from selecting content in hidden tabs */ /* To avoid "select all" commands from selecting content in hidden tabs */
.tabs .hidden, .tabs .hidden,
.tabs .hidden * { .tabs .hidden * {

Просмотреть файл

@ -234,16 +234,21 @@ define(function (require, exports, module) {
.map((tab) => typeof tab === "function" ? tab() : tab) .map((tab) => typeof tab === "function" ? tab() : tab)
.filter((tab) => tab) .filter((tab) => tab)
.map((tab, index) => { .map((tab, index) => {
let id = tab.props.id; let {
id,
className: tabClassName,
title,
badge,
showBadge,
} = tab.props;
let ref = "tab-menu-" + index; let ref = "tab-menu-" + index;
let title = tab.props.title;
let tabClassName = tab.props.className;
let isTabSelected = this.state.tabActive === index; let isTabSelected = this.state.tabActive === index;
let className = [ let className = [
"tabs-menu-item", "tabs-menu-item",
tabClassName, tabClassName,
isTabSelected ? "is-active" : "" isTabSelected ? "is-active" : "",
].join(" "); ].join(" ");
// Set tabindex to -1 (except the selected tab) so, it's focusable, // Set tabindex to -1 (except the selected tab) so, it's focusable,
@ -266,7 +271,11 @@ define(function (require, exports, module) {
role: "tab", role: "tab",
onClick: this.onClickTab.bind(this, index), onClick: this.onClickTab.bind(this, index),
}, },
title title,
badge && !isTabSelected && showBadge() ?
DOM.span({ className: "tab-badge" }, badge)
:
null
) )
) )
); );

Просмотреть файл

@ -48,6 +48,56 @@
align-items: center; align-items: center;
} }
/**
* Layout Promote Bar
*/
.layout-promote-bar {
align-items: center;
background-color: var(--theme-toolbar-background);
border-bottom: 1px solid var(--theme-splitter-color);
display: flex;
font-size: 11px;
padding: 5px;
transition: all 0.25s ease;
width: 100%;
-moz-user-select: none;
}
.layout-promote-bar:hover {
background-color: var(--theme-toolbar-hover);
}
.layout-promote-info-icon {
display: inline-block;
background-size: 16px;
width: 16px;
height: 16px;
margin: 6px;
background-image: url("chrome://browser/skin/info.svg");
}
.layout-promote-message {
flex: 1;
}
.layout-promote-learn-more-link {
margin-inline-start: 5px;
}
.layout-promote-learn-more-link:hover {
text-decoration: underline;
}
.layout-promote-close-button {
margin: 6px;
}
.layout-promote-close-button::before {
background-image: url("chrome://devtools/skin/images/close.svg");
margin: -6px 0 0 -6px;
}
/** /**
* Grid Container * Grid Container
*/ */

Просмотреть файл

@ -4084,42 +4084,33 @@ enum nsPreviousIntersectionThreshold {
void void
Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver) Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{ {
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers = RegisteredIntersectionObservers()->LookupForAdd(aObserver).OrInsert([]() {
RegisteredIntersectionObservers(); // Value can be:
if (observers->Contains(aObserver)) { // -2: Makes sure next calculated threshold always differs, leading to a
return; // notification task being scheduled.
} // -1: Non-intersecting.
// >= 0: Intersecting, valid index of aObserver->mThresholds.
// Value can be: return eUninitialized;
// -2: Makes sure next calculated threshold always differs, leading to a });
// notification task being scheduled.
// -1: Non-intersecting.
// >= 0: Intersecting, valid index of aObserver->mThresholds.
RegisteredIntersectionObservers()->Put(aObserver, eUninitialized);
} }
void void
Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver) Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{ {
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers = RegisteredIntersectionObservers()->Remove(aObserver);
RegisteredIntersectionObservers();
observers->Remove(aObserver);
} }
bool bool
Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold) Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
{ {
nsDataHashtable<nsRefPtrHashKey<DOMIntersectionObserver>, int32_t>* observers = bool updated = false;
RegisteredIntersectionObservers(); RegisteredIntersectionObservers()->LookupRemoveIf(aObserver,
if (!observers->Contains(aObserver)) { [&updated, aThreshold] (int32_t& aValue) {
return false; updated = aValue != aThreshold;
} aValue = aThreshold;
int32_t previousThreshold = observers->Get(aObserver); return false; // don't remove the entry
if (previousThreshold != aThreshold) { });
observers->Put(aObserver, aThreshold); return updated;
return true;
}
return false;
} }
void void

Просмотреть файл

@ -28,26 +28,27 @@ ImageTracker::Add(imgIRequest* aImage)
{ {
MOZ_ASSERT(aImage); MOZ_ASSERT(aImage);
// See if the image is already in the hashtable. If it is, get the old count.
uint32_t oldCount = 0;
mImages.Get(aImage, &oldCount);
// Put the image in the hashtable, with the proper count.
mImages.Put(aImage, oldCount + 1);
nsresult rv = NS_OK; nsresult rv = NS_OK;
auto entry = mImages.LookupForAdd(aImage);
if (entry) {
// The image is already in the hashtable. Increment its count.
uint32_t oldCount = entry.Data();
MOZ_ASSERT(oldCount > 0, "Entry in the image tracker with count 0!");
entry.Data() = oldCount + 1;
} else {
// A new entry was inserted - set the count to 1.
entry.OrInsert([]() { return 1; });
// If this is the first insertion and we're locking images, lock this image // If we're locking images, lock this image too.
// too. if (mLocking) {
if (oldCount == 0 && mLocking) { rv = aImage->LockImage();
rv = aImage->LockImage(); }
}
// If this is the first insertion and we're animating images, request // If we're animating images, request that this image be animated too.
// that this image be animated too. if (mAnimating) {
if (oldCount == 0 && mAnimating) { nsresult rv2 = aImage->IncrementAnimationConsumers();
nsresult rv2 = aImage->IncrementAnimationConsumers(); rv = NS_SUCCEEDED(rv) ? rv2 : rv;
rv = NS_SUCCEEDED(rv) ? rv2 : rv; }
} }
return rv; return rv;
@ -59,23 +60,23 @@ ImageTracker::Remove(imgIRequest* aImage, uint32_t aFlags)
NS_ENSURE_ARG_POINTER(aImage); NS_ENSURE_ARG_POINTER(aImage);
// Get the old count. It should exist and be > 0. // Get the old count. It should exist and be > 0.
uint32_t count = 0; DebugOnly<bool> found = false;
DebugOnly<bool> found = mImages.Get(aImage, &count); bool remove = false;
mImages.LookupRemoveIf(aImage,
[&found, &remove] (uint32_t& aCount) {
found = true;
MOZ_ASSERT(aCount > 0, "Entry in the image tracker with count 0!");
--aCount;
// If the count is now zero, remove it from the tracker.
remove = aCount == 0;
return remove;
});
MOZ_ASSERT(found, "Removing image that wasn't in the tracker!"); MOZ_ASSERT(found, "Removing image that wasn't in the tracker!");
MOZ_ASSERT(count > 0, "Entry in the cache tracker with count 0!"); if (!remove) {
// We're removing, so decrement the count.
count--;
// If the count is now zero, remove from the tracker.
// Otherwise, set the new value.
if (count != 0) {
mImages.Put(aImage, count);
return NS_OK; return NS_OK;
} }
mImages.Remove(aImage);
nsresult rv = NS_OK; nsresult rv = NS_OK;
// Now that we're no longer tracking this image, unlock it if we'd // Now that we're no longer tracking this image, unlock it if we'd

Просмотреть файл

@ -99,13 +99,14 @@ StructuredCloneBlob::Deserialize(JSContext* aCx, JS::HandleObject aTargetScope,
/* static */ JSObject* /* static */ JSObject*
StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader) StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader,
StructuredCloneHolder* aHolder)
{ {
JS::RootedObject obj(aCx); JS::RootedObject obj(aCx);
{ {
RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob(); RefPtr<StructuredCloneBlob> holder = new StructuredCloneBlob();
if (!holder->ReadStructuredCloneInternal(aCx, aReader) || if (!holder->ReadStructuredCloneInternal(aCx, aReader, aHolder) ||
!holder->WrapObject(aCx, nullptr, &obj)) { !holder->WrapObject(aCx, nullptr, &obj)) {
return nullptr; return nullptr;
} }
@ -114,7 +115,8 @@ StructuredCloneBlob::ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader
} }
bool bool
StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader) StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader,
StructuredCloneHolder* aHolder)
{ {
uint32_t length; uint32_t length;
uint32_t version; uint32_t version;
@ -122,6 +124,15 @@ StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredClo
return false; return false;
} }
uint32_t blobOffset;
uint32_t blobCount;
if (!JS_ReadUint32Pair(aReader, &blobOffset, &blobCount)) {
return false;
}
if (blobCount) {
BlobImpls().AppendElements(&aHolder->BlobImpls()[blobOffset], blobCount);
}
JSStructuredCloneData data(length, length, 4096); JSStructuredCloneData data(length, length, 4096);
if (!JS_ReadBytes(aReader, data.Start(), length)) { if (!JS_ReadBytes(aReader, data.Start(), length)) {
return false; return false;
@ -136,14 +147,18 @@ StructuredCloneBlob::ReadStructuredCloneInternal(JSContext* aCx, JSStructuredClo
} }
bool bool
StructuredCloneBlob::WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter) StructuredCloneBlob::WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter,
StructuredCloneHolder* aHolder)
{ {
auto& data = mBuffer->data(); auto& data = mBuffer->data();
if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_STRUCTURED_CLONE_HOLDER, 0) || if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_STRUCTURED_CLONE_HOLDER, 0) ||
!JS_WriteUint32Pair(aWriter, data.Size(), JS_STRUCTURED_CLONE_VERSION)) { !JS_WriteUint32Pair(aWriter, data.Size(), JS_STRUCTURED_CLONE_VERSION) ||
!JS_WriteUint32Pair(aWriter, aHolder->BlobImpls().Length(), BlobImpls().Length())) {
return false; return false;
} }
aHolder->BlobImpls().AppendElements(BlobImpls());
auto iter = data.Iter(); auto iter = data.Iter();
while (!iter.Done()) { while (!iter.Done()) {
if (!JS_WriteBytes(aWriter, iter.Data(), iter.RemainingInSegment())) { if (!JS_WriteBytes(aWriter, iter.Data(), iter.RemainingInSegment())) {

Просмотреть файл

@ -26,8 +26,10 @@ public:
explicit StructuredCloneBlob(); explicit StructuredCloneBlob();
static JSObject* ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader); static JSObject* ReadStructuredClone(JSContext* aCx, JSStructuredCloneReader* aReader,
bool WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter); StructuredCloneHolder* aHolder);
bool WriteStructuredClone(JSContext* aCx, JSStructuredCloneWriter* aWriter,
StructuredCloneHolder* aHolder);
static already_AddRefed<StructuredCloneBlob> static already_AddRefed<StructuredCloneBlob>
Constructor(GlobalObject& aGlobal, JS::HandleValue aValue, JS::HandleObject aTargetGlobal, ErrorResult& aRv); Constructor(GlobalObject& aGlobal, JS::HandleValue aValue, JS::HandleObject aTargetGlobal, ErrorResult& aRv);
@ -47,7 +49,8 @@ protected:
~StructuredCloneBlob() = default; ~StructuredCloneBlob() = default;
private: private:
bool ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader); bool ReadStructuredCloneInternal(JSContext* aCx, JSStructuredCloneReader* aReader,
StructuredCloneHolder* aHolder);
}; };
} // namespace dom } // namespace dom

Просмотреть файл

@ -358,10 +358,6 @@ StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx,
return ReadStructuredCloneImageData(aCx, aReader); return ReadStructuredCloneImageData(aCx, aReader);
} }
if (aTag == SCTAG_DOM_STRUCTURED_CLONE_HOLDER) {
return StructuredCloneBlob::ReadStructuredClone(aCx, aReader);
}
if (aTag == SCTAG_DOM_WEBCRYPTO_KEY || aTag == SCTAG_DOM_URLSEARCHPARAMS) { if (aTag == SCTAG_DOM_WEBCRYPTO_KEY || aTag == SCTAG_DOM_URLSEARCHPARAMS) {
nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx)); nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
if (!global) { if (!global) {
@ -458,14 +454,6 @@ StructuredCloneHolder::WriteFullySerializableObjects(JSContext* aCx,
} }
} }
// See if this is a StructuredCloneBlob object.
{
StructuredCloneBlob* holder = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(StructuredCloneHolder, aObj, holder))) {
return holder->WriteStructuredClone(aCx, aWriter);
}
}
// Handle URLSearchParams cloning // Handle URLSearchParams cloning
{ {
URLSearchParams* usp = nullptr; URLSearchParams* usp = nullptr;
@ -999,6 +987,10 @@ StructuredCloneHolder::CustomReadHandler(JSContext* aCx,
parent, GetSurfaces(), aIndex); parent, GetSurfaces(), aIndex);
} }
if (aTag == SCTAG_DOM_STRUCTURED_CLONE_HOLDER) {
return StructuredCloneBlob::ReadStructuredClone(aCx, aReader, this);
}
if (aTag == SCTAG_DOM_WASM) { if (aTag == SCTAG_DOM_WASM) {
return ReadWasmModule(aCx, aIndex, this); return ReadWasmModule(aCx, aIndex, this);
} }
@ -1062,6 +1054,14 @@ StructuredCloneHolder::CustomWriteHandler(JSContext* aCx,
} }
} }
// See if this is a StructuredCloneBlob object.
{
StructuredCloneBlob* holder = nullptr;
if (NS_SUCCEEDED(UNWRAP_OBJECT(StructuredCloneHolder, aObj, holder))) {
return holder->WriteStructuredClone(aCx, aWriter, this);
}
}
// See if this is a WasmModule. // See if this is a WasmModule.
if ((mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread || if ((mStructuredCloneScope == StructuredCloneScope::SameProcessSameThread ||
mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) && mStructuredCloneScope == StructuredCloneScope::SameProcessDifferentThread) &&

Просмотреть файл

@ -54,7 +54,6 @@ Timeout::SetWhenOrTimeRemaining(const TimeStamp& aBaseTime,
if (mWindow->IsFrozen()) { if (mWindow->IsFrozen()) {
mWhen = TimeStamp(); mWhen = TimeStamp();
mTimeRemaining = aDelay; mTimeRemaining = aDelay;
mScheduledDelay = TimeDuration(0);
return; return;
} }
@ -63,7 +62,6 @@ Timeout::SetWhenOrTimeRemaining(const TimeStamp& aBaseTime,
// that it appears time passes while suspended. // that it appears time passes while suspended.
mWhen = aBaseTime + aDelay; mWhen = aBaseTime + aDelay;
mTimeRemaining = TimeDuration(0); mTimeRemaining = TimeDuration(0);
mScheduledDelay = aDelay;
} }
const TimeStamp& const TimeStamp&
@ -84,12 +82,5 @@ Timeout::TimeRemaining() const
return mTimeRemaining; return mTimeRemaining;
} }
const TimeDuration&
Timeout::ScheduledDelay() const
{
MOZ_DIAGNOSTIC_ASSERT(!mWhen.IsNull());
return mScheduledDelay;
}
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -50,9 +50,6 @@ public:
// Can only be called when frozen. // Can only be called when frozen.
const TimeDuration& TimeRemaining() const; const TimeDuration& TimeRemaining() const;
// Can only be called when not frozen.
const TimeDuration& ScheduledDelay() const;
// Window for which this timeout fires // Window for which this timeout fires
RefPtr<nsGlobalWindow> mWindow; RefPtr<nsGlobalWindow> mWindow;
@ -101,10 +98,6 @@ private:
// Remaining time to wait. Used only when timeouts are frozen. // Remaining time to wait. Used only when timeouts are frozen.
TimeDuration mTimeRemaining; TimeDuration mTimeRemaining;
// The actual interval in milliseconds. This may be throttled to
// a longer delay than mInterval for a number of reasons.
TimeDuration mScheduledDelay;
~Timeout() = default; ~Timeout() = default;
}; };

Просмотреть файл

@ -40,11 +40,13 @@ TimeoutExecutor::ScheduleImmediate(const TimeStamp& aDeadline,
nsresult nsresult
TimeoutExecutor::ScheduleDelayed(const TimeStamp& aDeadline, TimeoutExecutor::ScheduleDelayed(const TimeStamp& aDeadline,
const TimeStamp& aNow) const TimeStamp& aNow,
const TimeDuration& aMinDelay)
{ {
MOZ_DIAGNOSTIC_ASSERT(mDeadline.IsNull()); MOZ_DIAGNOSTIC_ASSERT(mDeadline.IsNull());
MOZ_DIAGNOSTIC_ASSERT(mMode == Mode::None); MOZ_DIAGNOSTIC_ASSERT(mMode == Mode::None);
MOZ_DIAGNOSTIC_ASSERT(aDeadline > (aNow + mAllowedEarlyFiringTime)); MOZ_DIAGNOSTIC_ASSERT(!aMinDelay.IsZero() ||
aDeadline > (aNow + mAllowedEarlyFiringTime));
nsresult rv = NS_OK; nsresult rv = NS_OK;
@ -65,6 +67,15 @@ TimeoutExecutor::ScheduleDelayed(const TimeStamp& aDeadline,
rv = mTimer->SetTarget(mOwner->EventTarget()); rv = mTimer->SetTarget(mOwner->EventTarget());
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// Calculate the delay based on the deadline and current time. If we have
// a minimum delay set then clamp to that value.
//
// Note, we don't actually adjust our mDeadline for the minimum delay, just
// the nsITimer value. This is necessary to avoid lots of needless
// rescheduling if more deadlines come in between now and the minimum delay
// firing time.
TimeDuration delay = TimeDuration::Max(aMinDelay, aDeadline - aNow);
// Note, we cannot use the normal nsITimer init methods that take // Note, we cannot use the normal nsITimer init methods that take
// integer milliseconds. We need higher precision. Consider this // integer milliseconds. We need higher precision. Consider this
// situation: // situation:
@ -83,7 +94,7 @@ TimeoutExecutor::ScheduleDelayed(const TimeStamp& aDeadline,
// schedule a new nsITimer for g(). Its only 500us in the future, though. We // schedule a new nsITimer for g(). Its only 500us in the future, though. We
// must be able to pass this fractional value to nsITimer in order to get an // must be able to pass this fractional value to nsITimer in order to get an
// accurate wakeup time. // accurate wakeup time.
rv = mTimer->InitHighResolutionWithCallback(this, aDeadline - aNow, rv = mTimer->InitHighResolutionWithCallback(this, delay,
nsITimer::TYPE_ONE_SHOT); nsITimer::TYPE_ONE_SHOT);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -94,22 +105,24 @@ TimeoutExecutor::ScheduleDelayed(const TimeStamp& aDeadline,
} }
nsresult nsresult
TimeoutExecutor::Schedule(const TimeStamp& aDeadline) TimeoutExecutor::Schedule(const TimeStamp& aDeadline,
const TimeDuration& aMinDelay)
{ {
TimeStamp now(TimeStamp::Now()); TimeStamp now(TimeStamp::Now());
// Schedule an immediate runnable if the desired deadline has passed // Schedule an immediate runnable if the desired deadline has passed
// or is slightly in the future. This is similar to how nsITimer will // or is slightly in the future. This is similar to how nsITimer will
// fire timers early based on the interval resolution. // fire timers early based on the interval resolution.
if (aDeadline <= (now + mAllowedEarlyFiringTime)) { if (aMinDelay.IsZero() && aDeadline <= (now + mAllowedEarlyFiringTime)) {
return ScheduleImmediate(aDeadline, now); return ScheduleImmediate(aDeadline, now);
} }
return ScheduleDelayed(aDeadline, now); return ScheduleDelayed(aDeadline, now, aMinDelay);
} }
nsresult nsresult
TimeoutExecutor::MaybeReschedule(const TimeStamp& aDeadline) TimeoutExecutor::MaybeReschedule(const TimeStamp& aDeadline,
const TimeDuration& aMinDelay)
{ {
MOZ_DIAGNOSTIC_ASSERT(!mDeadline.IsNull()); MOZ_DIAGNOSTIC_ASSERT(!mDeadline.IsNull());
MOZ_DIAGNOSTIC_ASSERT(mMode == Mode::Immediate || MOZ_DIAGNOSTIC_ASSERT(mMode == Mode::Immediate ||
@ -127,7 +140,7 @@ TimeoutExecutor::MaybeReschedule(const TimeStamp& aDeadline)
} }
Cancel(); Cancel();
return Schedule(aDeadline); return Schedule(aDeadline, aMinDelay);
} }
void void
@ -176,7 +189,8 @@ TimeoutExecutor::Shutdown()
} }
nsresult nsresult
TimeoutExecutor::MaybeSchedule(const TimeStamp& aDeadline) TimeoutExecutor::MaybeSchedule(const TimeStamp& aDeadline,
const TimeDuration& aMinDelay)
{ {
MOZ_DIAGNOSTIC_ASSERT(!aDeadline.IsNull()); MOZ_DIAGNOSTIC_ASSERT(!aDeadline.IsNull());
@ -185,10 +199,10 @@ TimeoutExecutor::MaybeSchedule(const TimeStamp& aDeadline)
} }
if (mMode == Mode::Immediate || mMode == Mode::Delayed) { if (mMode == Mode::Immediate || mMode == Mode::Delayed) {
return MaybeReschedule(aDeadline); return MaybeReschedule(aDeadline, aMinDelay);
} }
return Schedule(aDeadline); return Schedule(aDeadline, aMinDelay);
} }
void void

Просмотреть файл

@ -56,13 +56,14 @@ class TimeoutExecutor final : public nsIRunnable
ScheduleImmediate(const TimeStamp& aDeadline, const TimeStamp& aNow); ScheduleImmediate(const TimeStamp& aDeadline, const TimeStamp& aNow);
nsresult nsresult
ScheduleDelayed(const TimeStamp& aDeadline, const TimeStamp& aNow); ScheduleDelayed(const TimeStamp& aDeadline, const TimeStamp& aNow,
const TimeDuration& aMinDelay);
nsresult nsresult
Schedule(const TimeStamp& aDeadline); Schedule(const TimeStamp& aDeadline, const TimeDuration& aMinDelay);
nsresult nsresult
MaybeReschedule(const TimeStamp& aDeadline); MaybeReschedule(const TimeStamp& aDeadline, const TimeDuration& aMinDelay);
void void
MaybeExecute(); MaybeExecute();
@ -74,7 +75,7 @@ public:
Shutdown(); Shutdown();
nsresult nsresult
MaybeSchedule(const TimeStamp& aDeadline); MaybeSchedule(const TimeStamp& aDeadline, const TimeDuration& aMinDelay);
void void
Cancel(); Cancel();

Просмотреть файл

@ -146,6 +146,9 @@ const uint32_t TimeoutManager::InvalidFiringId = 0;
bool bool
TimeoutManager::IsBackground() const TimeoutManager::IsBackground() const
{ {
// Don't use the background timeout value when the tab is playing audio.
// Until bug 1336484 we only used to do this for pages that use Web Audio.
// The original behavior was implemented in bug 11811073.
return !mWindow.AsInner()->IsPlayingAudio() && mWindow.IsBackgroundInternal(); return !mWindow.AsInner()->IsPlayingAudio() && mWindow.IsBackgroundInternal();
} }
@ -177,6 +180,15 @@ TimeoutManager::IsValidFiringId(uint32_t aFiringId) const
return !IsInvalidFiringId(aFiringId); return !IsInvalidFiringId(aFiringId);
} }
TimeDuration
TimeoutManager::MinSchedulingDelay() const
{
if (IsBackground()) {
return TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue);
}
return TimeDuration();
}
bool bool
TimeoutManager::IsInvalidFiringId(uint32_t aFiringId) const TimeoutManager::IsInvalidFiringId(uint32_t aFiringId) const
{ {
@ -218,15 +230,9 @@ TimeoutManager::IsInvalidFiringId(uint32_t aFiringId) const
int32_t int32_t
TimeoutManager::DOMMinTimeoutValue(bool aIsTracking) const { TimeoutManager::DOMMinTimeoutValue(bool aIsTracking) const {
// Don't use the background timeout value when the tab is playing audio.
// Until bug 1336484 we only used to do this for pages that use Web Audio.
// The original behavior was implemented in bug 11811073.
bool isBackground = IsBackground();
bool throttleTracking = aIsTracking && mThrottleTrackingTimeouts; bool throttleTracking = aIsTracking && mThrottleTrackingTimeouts;
auto minValue = throttleTracking ? (isBackground ? gMinTrackingBackgroundTimeoutValue auto minValue = throttleTracking ? gMinTrackingTimeoutValue
: gMinTrackingTimeoutValue) : gMinTimeoutValue;
: (isBackground ? gMinBackgroundTimeoutValue
: gMinTimeoutValue);
return minValue; return minValue;
} }
@ -409,7 +415,6 @@ TimeoutManager::SetTimeout(nsITimeoutHandler* aHandler,
uint32_t nestingLevel = sNestingLevel + 1; uint32_t nestingLevel = sNestingLevel + 1;
uint32_t realInterval = interval; uint32_t realInterval = interval;
if (aIsInterval || nestingLevel >= DOM_CLAMP_TIMEOUT_NESTING_LEVEL || if (aIsInterval || nestingLevel >= DOM_CLAMP_TIMEOUT_NESTING_LEVEL ||
mWindow.IsBackgroundInternal() ||
timeout->mIsTracking) { timeout->mIsTracking) {
// Don't allow timeouts less than DOMMinTimeoutValue() from // Don't allow timeouts less than DOMMinTimeoutValue() from
// now... // now...
@ -424,7 +429,8 @@ TimeoutManager::SetTimeout(nsITimeoutHandler* aHandler,
// If we're not suspended, then set the timer. // If we're not suspended, then set the timer.
if (!mWindow.IsSuspended()) { if (!mWindow.IsSuspended()) {
nsresult rv = mExecutor->MaybeSchedule(timeout->When()); nsresult rv = mExecutor->MaybeSchedule(timeout->When(),
MinSchedulingDelay());
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
} }
@ -476,7 +482,7 @@ TimeoutManager::SetTimeout(nsITimeoutHandler* aHandler,
mThrottleTrackingTimeouts ? "yes" mThrottleTrackingTimeouts ? "yes"
: (mThrottleTrackingTimeoutsTimer ? : (mThrottleTrackingTimeoutsTimer ?
"pending" : "no"), "pending" : "no"),
int(mWindow.IsBackgroundInternal()), realInterval, int(IsBackground()), realInterval,
timeout->mIsTracking ? "" : "non-", timeout->mIsTracking ? "" : "non-",
timeout->mTimeoutId)); timeout->mTimeoutId));
@ -535,7 +541,8 @@ TimeoutManager::ClearTimeout(int32_t aTimerId, Timeout::Reason aReason)
OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts); OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts);
Timeout* nextTimeout = iter.Next(); Timeout* nextTimeout = iter.Next();
if (nextTimeout) { if (nextTimeout) {
MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextTimeout->When())); MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextTimeout->When(),
MinSchedulingDelay()));
} }
} }
@ -653,7 +660,8 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
// method and the window should not have been suspended while // method and the window should not have been suspended while
// executing the loop above since it doesn't call out to js. // executing the loop above since it doesn't call out to js.
MOZ_DIAGNOSTIC_ASSERT(!mWindow.IsSuspended()); MOZ_DIAGNOSTIC_ASSERT(!mWindow.IsSuspended());
MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextDeadline)); MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextDeadline,
MinSchedulingDelay()));
} }
// Maybe the timeout that the event was fired for has been deleted // Maybe the timeout that the event was fired for has been deleted
@ -777,7 +785,8 @@ TimeoutManager::RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadli
if (!mWindow.IsSuspended()) { if (!mWindow.IsSuspended()) {
RefPtr<Timeout> timeout = runIter.Next(); RefPtr<Timeout> timeout = runIter.Next();
if (timeout) { if (timeout) {
MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(timeout->When())); MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(timeout->When(),
MinSchedulingDelay()));
} }
} }
break; break;
@ -818,132 +827,13 @@ TimeoutManager::RescheduleTimeout(Timeout* aTimeout, const TimeStamp& now)
return true; return true;
} }
nsresult rv = mExecutor->MaybeSchedule(aTimeout->When()); nsresult rv = mExecutor->MaybeSchedule(aTimeout->When(),
MinSchedulingDelay());
NS_ENSURE_SUCCESS(rv, false); NS_ENSURE_SUCCESS(rv, false);
return true; return true;
} }
nsresult
TimeoutManager::ResetTimersForThrottleReduction()
{
return ResetTimersForThrottleReduction(gMinBackgroundTimeoutValue);
}
nsresult
TimeoutManager::ResetTimersForThrottleReduction(int32_t aPreviousThrottleDelayMS)
{
MOZ_ASSERT(aPreviousThrottleDelayMS > 0);
MOZ_ASSERT_IF(mWindow.IsFrozen(), mWindow.IsSuspended());
if (mWindow.IsSuspended()) {
return NS_OK;
}
nsresult rv = mNormalTimeouts.ResetTimersForThrottleReduction(aPreviousThrottleDelayMS,
*this,
Timeouts::SortBy::TimeWhen);
NS_ENSURE_SUCCESS(rv, rv);
rv = mTrackingTimeouts.ResetTimersForThrottleReduction(aPreviousThrottleDelayMS,
*this,
Timeouts::SortBy::TimeWhen);
NS_ENSURE_SUCCESS(rv, rv);
OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts);
Timeout* firstTimeout = iter.Next();
if (firstTimeout) {
rv = mExecutor->MaybeSchedule(firstTimeout->When());
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
}
nsresult
TimeoutManager::Timeouts::ResetTimersForThrottleReduction(int32_t aPreviousThrottleDelayMS,
const TimeoutManager& aTimeoutManager,
SortBy aSortBy)
{
TimeStamp now = TimeStamp::Now();
for (RefPtr<Timeout> timeout = GetFirst(); timeout; ) {
// Skip over any Timeout values with a valid FiringId. These are in the
// middle of a RunTimeout and should not be modified. Also, skip any
// timeouts in the past. It's important that this check be <= so that we
// guarantee that taking std::max with |now| won't make a quantity equal to
// timeout->When() below.
if (mManager.IsValidFiringId(timeout->mFiringId) ||
timeout->When() <= now) {
timeout = timeout->getNext();
continue;
}
if (timeout->When() - now >
TimeDuration::FromMilliseconds(aPreviousThrottleDelayMS)) {
// No need to loop further. Timeouts are sorted in When() order
// and the ones after this point were all set up for at least
// gMinBackgroundTimeoutValue ms and hence were not clamped.
break;
}
// We reduced our throttled delay. Re-init the timer appropriately.
// Compute the interval the timer should have had if it had not been set in a
// background window
TimeDuration interval =
TimeDuration::FromMilliseconds(
std::max(timeout->mInterval,
uint32_t(aTimeoutManager.
DOMMinTimeoutValue(timeout->mIsTracking))));
const TimeDuration& oldInterval = timeout->ScheduledDelay();
if (oldInterval > interval) {
// unclamp
TimeStamp firingTime =
std::max(timeout->When() - oldInterval + interval, now);
NS_ASSERTION(firingTime < timeout->When(),
"Our firing time should strictly decrease!");
TimeDuration delay = firingTime - now;
timeout->SetWhenOrTimeRemaining(now, delay);
MOZ_DIAGNOSTIC_ASSERT(timeout->When() == firingTime);
// Since we reset When() we need to move |timeout| to the right
// place in the list so that it remains sorted by When().
// Get the pointer to the next timeout now, before we move the
// current timeout in the list.
Timeout* nextTimeout = timeout->getNext();
// Since we are only reducing intervals in this method we can
// make an optimization here. If the reduction does not cause us
// to fall before our previous timeout then we do not have to
// remove and re-insert the current timeout. This is important
// because re-insertion makes this algorithm O(n^2). Since we
// will typically be shifting a lot of timers at once this
// optimization saves us a lot of work.
Timeout* prevTimeout = timeout->getPrevious();
if (prevTimeout && prevTimeout->When() > timeout->When()) {
// It is safe to remove and re-insert because When() is now
// strictly smaller than it used to be, so we know we'll insert
// |timeout| before nextTimeout.
NS_ASSERTION(!nextTimeout ||
timeout->When() < nextTimeout->When(), "How did that happen?");
timeout->remove();
// Insert() will reset mFiringId. Make sure to undo that.
uint32_t firingId = timeout->mFiringId;
Insert(timeout, aSortBy);
timeout->mFiringId = firingId;
}
timeout = nextTimeout;
} else {
timeout = timeout->getNext();
}
}
return NS_OK;
}
void void
TimeoutManager::ClearAllTimeouts() TimeoutManager::ClearAllTimeouts()
{ {
@ -1112,7 +1002,8 @@ TimeoutManager::Resume()
}); });
if (!nextWakeUp.IsNull()) { if (!nextWakeUp.IsNull()) {
MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextWakeUp)); MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextWakeUp,
MinSchedulingDelay()));
} }
} }
@ -1152,6 +1043,24 @@ TimeoutManager::Thaw()
}); });
} }
void
TimeoutManager::UpdateBackgroundState()
{
// When the window moves to the background or foreground we should
// reschedule the TimeoutExecutor in case the MinSchedulingDelay()
// changed. Only do this if the window is not suspended and we
// actually have a timeout.
if (!mWindow.IsSuspended()) {
OrderedTimeoutIterator iter(mNormalTimeouts, mTrackingTimeouts);
Timeout* nextTimeout = iter.Next();
if (nextTimeout) {
mExecutor->Cancel();
MOZ_ALWAYS_SUCCEEDS(mExecutor->MaybeSchedule(nextTimeout->When(),
MinSchedulingDelay()));
}
}
}
bool bool
TimeoutManager::IsTimeoutTracking(uint32_t aTimeoutId) TimeoutManager::IsTimeoutTracking(uint32_t aTimeoutId)
{ {

Просмотреть файл

@ -55,11 +55,6 @@ public:
void ClearAllTimeouts(); void ClearAllTimeouts();
uint32_t GetTimeoutId(mozilla::dom::Timeout::Reason aReason); uint32_t GetTimeoutId(mozilla::dom::Timeout::Reason aReason);
// When timers are being throttled and we reduce the thottle delay we must
// reschedule. The amount of the old throttle delay must be provided in
// order to bound how many timers must be examined.
nsresult ResetTimersForThrottleReduction();
int32_t DOMMinTimeoutValue(bool aIsTracking) const; int32_t DOMMinTimeoutValue(bool aIsTracking) const;
// aTimeout is the timeout that we're about to start running. This function // aTimeout is the timeout that we're about to start running. This function
@ -77,6 +72,10 @@ public:
void Freeze(); void Freeze();
void Thaw(); void Thaw();
// This should be called by nsGlobalWindow when the window might have moved
// to the background or foreground.
void UpdateBackgroundState();
// Initialize TimeoutManager before the first time it is accessed. // Initialize TimeoutManager before the first time it is accessed.
static void Initialize(); static void Initialize();
@ -116,7 +115,6 @@ public:
static const uint32_t InvalidFiringId; static const uint32_t InvalidFiringId;
private: private:
nsresult ResetTimersForThrottleReduction(int32_t aPreviousThrottleDelayMS);
void MaybeStartThrottleTrackingTimout(); void MaybeStartThrottleTrackingTimout();
bool IsBackground() const; bool IsBackground() const;
@ -133,6 +131,9 @@ private:
bool bool
IsInvalidFiringId(uint32_t aFiringId) const; IsInvalidFiringId(uint32_t aFiringId) const;
TimeDuration
MinSchedulingDelay() const;
private: private:
struct Timeouts { struct Timeouts {
explicit Timeouts(const TimeoutManager& aManager) explicit Timeouts(const TimeoutManager& aManager)
@ -149,9 +150,6 @@ private:
TimeWhen TimeWhen
}; };
void Insert(mozilla::dom::Timeout* aTimeout, SortBy aSortBy); void Insert(mozilla::dom::Timeout* aTimeout, SortBy aSortBy);
nsresult ResetTimersForThrottleReduction(int32_t aPreviousThrottleDelayMS,
const TimeoutManager& aTimeoutManager,
SortBy aSortBy);
const Timeout* GetFirst() const { return mTimeoutList.getFirst(); } const Timeout* GetFirst() const { return mTimeoutList.getFirst(); }
Timeout* GetFirst() { return mTimeoutList.getFirst(); } Timeout* GetFirst() { return mTimeoutList.getFirst(); }

Просмотреть файл

@ -9640,10 +9640,11 @@ nsDocument::MaybePreconnect(nsIURI* aOrigURI, mozilla::CORSMode aCORSMode)
uri->SetPath(NS_LITERAL_CSTRING("/")); uri->SetPath(NS_LITERAL_CSTRING("/"));
} }
if (mPreloadedPreconnects.Contains(uri)) { auto entry = mPreloadedPreconnects.LookupForAdd(uri);
return; if (entry) {
return; // we found an existing entry
} }
mPreloadedPreconnects.Put(uri, true); entry.OrInsert([] () { return true; });
nsCOMPtr<nsISpeculativeConnect> nsCOMPtr<nsISpeculativeConnect>
speculator(do_QueryInterface(nsContentUtils::GetIOService())); speculator(do_QueryInterface(nsContentUtils::GetIOService()));

Просмотреть файл

@ -350,6 +350,45 @@ GK_ATOM(displayMode, "display-mode")
GK_ATOM(distinct, "distinct") GK_ATOM(distinct, "distinct")
GK_ATOM(div, "div") GK_ATOM(div, "div")
GK_ATOM(dl, "dl") GK_ATOM(dl, "dl")
GK_ATOM(docAbstract, "doc-abstract")
GK_ATOM(docAcknowledgments, "doc-acknowledgments")
GK_ATOM(docAfterword, "doc-afterword")
GK_ATOM(docAppendix, "doc-appendix")
GK_ATOM(docBacklink, "doc-backlink")
GK_ATOM(docBiblioentry, "doc-biblioentry")
GK_ATOM(docBibliography, "doc-bibliography")
GK_ATOM(docBiblioref, "doc-biblioref")
GK_ATOM(docChapter, "doc-chapter")
GK_ATOM(docColophon, "doc-colophon")
GK_ATOM(docConclusion, "doc-conclusion")
GK_ATOM(docCover, "doc-cover")
GK_ATOM(docCredit, "doc-credit")
GK_ATOM(docCredits, "doc-credits")
GK_ATOM(docDedication, "doc-dedication")
GK_ATOM(docEndnote, "doc-endnote")
GK_ATOM(docEndnotes, "doc-endnotes")
GK_ATOM(docEpigraph, "doc-epigraph")
GK_ATOM(docEpilogue, "doc-epilogue")
GK_ATOM(docErrata, "doc-errata")
GK_ATOM(docExample, "doc-example")
GK_ATOM(docFootnote, "doc-footnote")
GK_ATOM(docForeword, "doc-foreword")
GK_ATOM(docGlossary, "doc-glossary")
GK_ATOM(docGlossref, "doc-glossref")
GK_ATOM(docIndex, "doc-index")
GK_ATOM(docIntroduction, "doc-introduction")
GK_ATOM(docNoteref, "doc-noteref")
GK_ATOM(docNotice, "doc-notice")
GK_ATOM(docPagebreak, "doc-pagebreak")
GK_ATOM(docPagelist, "doc-pagelist")
GK_ATOM(docPart, "doc-part")
GK_ATOM(docPreface, "doc-preface")
GK_ATOM(docPrologue, "doc-prologue")
GK_ATOM(docPullquote, "doc-pullquote")
GK_ATOM(docQna, "doc-qna")
GK_ATOM(docSubtitle, "doc-subtitle")
GK_ATOM(docTip, "doc-tip")
GK_ATOM(docToc, "doc-toc")
GK_ATOM(doctypePublic, "doctype-public") GK_ATOM(doctypePublic, "doctype-public")
GK_ATOM(doctypeSystem, "doctype-system") GK_ATOM(doctypeSystem, "doctype-system")
GK_ATOM(document, "document") GK_ATOM(document, "document")

Просмотреть файл

@ -10671,13 +10671,16 @@ void nsGlobalWindow::SetIsBackground(bool aIsBackground)
{ {
MOZ_ASSERT(IsOuterWindow()); MOZ_ASSERT(IsOuterWindow());
bool resetTimers = (!aIsBackground && AsOuter()->IsBackground()); bool changed = aIsBackground != AsOuter()->IsBackground();
SetIsBackgroundInternal(aIsBackground); SetIsBackgroundInternal(aIsBackground);
nsGlobalWindow* inner = GetCurrentInnerWindowInternal(); nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
if (inner && changed) {
inner->mTimeoutManager->UpdateBackgroundState();
}
if (aIsBackground) { if (aIsBackground) {
MOZ_ASSERT(!resetTimers);
// Notify gamepadManager we are at the background window, // Notify gamepadManager we are at the background window,
// we need to stop vibrate. // we need to stop vibrate.
if (inner) { if (inner) {
@ -10685,9 +10688,6 @@ void nsGlobalWindow::SetIsBackground(bool aIsBackground)
} }
return; return;
} else if (inner) { } else if (inner) {
if (resetTimers) {
inner->mTimeoutManager->ResetTimersForThrottleReduction();
}
inner->SyncGamepadState(); inner->SyncGamepadState();
} }
} }

Просмотреть файл

@ -9,13 +9,19 @@ var testURLs = [
// We want to ensure that while audio is being played back, a background tab is // We want to ensure that while audio is being played back, a background tab is
// treated the same as a foreground tab as far as timeout throttling is concerned. // treated the same as a foreground tab as far as timeout throttling is concerned.
// So we use a 10ms minimum timeout value for foreground tabs and a 100,000 second // So we use a 100,000 second minimum timeout value for background tabs. This
// minimum timeout value for background tabs. This means that in case the test // means that in case the test fails, it will time out in practice, but just for
// fails, it will time out in practice, but just for sanity the test condition // sanity the test condition ensures that the observed timeout delay falls in
// ensures that the observed timeout delay falls in this range. // this range.
const kMinTimeoutForeground = 10;
const kMinTimeoutBackground = 100 * 1000 * 1000; const kMinTimeoutBackground = 100 * 1000 * 1000;
const kDelay = 10;
// Allow a very generous error range due to debug automation tests running
// very slowly. This is still far below the configured background throttle
// amount.
const kAllowedError = 1000;
Services.scriptloader.loadSubScript(kPluginJS, this); Services.scriptloader.loadSubScript(kPluginJS, this);
function* runTest(url) { function* runTest(url) {
@ -31,19 +37,16 @@ function* runTest(url) {
// Put the tab in the background. // Put the tab in the background.
yield BrowserTestUtils.switchTab(gBrowser, currentTab); yield BrowserTestUtils.switchTab(gBrowser, currentTab);
let timeout = yield ContentTask.spawn(newBrowser, {}, function() { let timeout = yield ContentTask.spawn(newBrowser, kDelay, function(delay) {
return new Promise(resolve => { return new Promise(resolve => {
let before = new Date(); let before = new Date();
content.window.setTimeout(function() { content.window.setTimeout(function() {
let after = new Date(); let after = new Date();
// Sometimes due to rounding errors, we may get a result of 9ms here, so resolve(after - before);
// let's round up by 1 to protect against such intermittent failures. }, delay);
resolve(after - before + 1);
}, 0);
}); });
}); });
ok(timeout >= kMinTimeoutForeground && ok(timeout <= kDelay + kAllowedError, `Got the correct timeout (${timeout}`);
timeout < kMinTimeoutBackground, `Got the correct timeout (${timeout})`);
// All done. // All done.
yield BrowserTestUtils.removeTab(newTab); yield BrowserTestUtils.removeTab(newTab);
@ -51,7 +54,6 @@ function* runTest(url) {
add_task(function* setup() { add_task(function* setup() {
yield SpecialPowers.pushPrefEnv({"set": [ yield SpecialPowers.pushPrefEnv({"set": [
["dom.min_timeout_value", kMinTimeoutForeground],
["dom.min_background_timeout_value", kMinTimeoutBackground], ["dom.min_background_timeout_value", kMinTimeoutBackground],
]}); ]});
}); });

Просмотреть файл

@ -1593,6 +1593,8 @@ EventListenerManager::GetListenerInfo(nsCOMArray<nsIEventListenerInfo>* aList)
nsAutoString eventType; nsAutoString eventType;
if (listener.mAllEvents) { if (listener.mAllEvents) {
eventType.SetIsVoid(true); eventType.SetIsVoid(true);
} else if (listener.mListenerType == Listener::eNoListener) {
continue;
} else { } else {
eventType.Assign(Substring(nsDependentAtomString(listener.mTypeAtom), 2)); eventType.Assign(Substring(nsDependentAtomString(listener.mTypeAtom), 2));
} }

Просмотреть файл

@ -453,14 +453,16 @@ already_AddRefed<ParticularProcessPriorityManager>
ProcessPriorityManagerImpl::GetParticularProcessPriorityManager( ProcessPriorityManagerImpl::GetParticularProcessPriorityManager(
ContentParent* aContentParent) ContentParent* aContentParent)
{ {
RefPtr<ParticularProcessPriorityManager> pppm;
uint64_t cpId = aContentParent->ChildID(); uint64_t cpId = aContentParent->ChildID();
mParticularManagers.Get(cpId, &pppm); auto entry = mParticularManagers.LookupForAdd(cpId);
if (!pppm) { RefPtr<ParticularProcessPriorityManager> pppm = entry.OrInsert(
pppm = new ParticularProcessPriorityManager(aContentParent); [aContentParent]() {
pppm->Init(); return new ParticularProcessPriorityManager(aContentParent);
mParticularManagers.Put(cpId, pppm); });
if (!entry) {
// We created a new entry.
pppm->Init();
FireTestOnlyObserverNotification("process-created", FireTestOnlyObserverNotification("process-created",
nsPrintfCString("%" PRIu64, cpId)); nsPrintfCString("%" PRIu64, cpId));
} }
@ -501,15 +503,12 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID); props->GetPropertyAsUint64(NS_LITERAL_STRING("childID"), &childID);
NS_ENSURE_TRUE_VOID(childID != CONTENT_PROCESS_ID_UNKNOWN); NS_ENSURE_TRUE_VOID(childID != CONTENT_PROCESS_ID_UNKNOWN);
RefPtr<ParticularProcessPriorityManager> pppm; mParticularManagers.LookupRemoveIf(childID,
mParticularManagers.Get(childID, &pppm); [this, childID] (RefPtr<ParticularProcessPriorityManager>& aValue) {
if (pppm) { aValue->ShutDown();
pppm->ShutDown(); mHighPriorityChildIDs.RemoveEntry(childID);
return true; // remove it
mParticularManagers.Remove(childID); });
mHighPriorityChildIDs.RemoveEntry(childID);
}
} }
void void

Просмотреть файл

@ -574,14 +574,14 @@ MediaCacheStream::BlockList::NotifyBlockSwapped(int32_t aBlockIndex1,
if (e1) { if (e1) {
e1Prev = e1->mPrevBlock; e1Prev = e1->mPrevBlock;
e1Next = e1->mNextBlock; e1Next = e1->mNextBlock;
mEntries.RemoveEntry(aBlockIndex1); mEntries.RemoveEntry(e1);
// Refresh pointer after hashtable mutation. // Refresh pointer after hashtable mutation.
e2 = mEntries.GetEntry(aBlockIndex2); e2 = mEntries.GetEntry(aBlockIndex2);
} }
if (e2) { if (e2) {
e2Prev = e2->mPrevBlock; e2Prev = e2->mPrevBlock;
e2Next = e2->mNextBlock; e2Next = e2->mNextBlock;
mEntries.RemoveEntry(aBlockIndex2); mEntries.RemoveEntry(e2);
} }
// Put new entries back. // Put new entries back.
if (e1) { if (e1) {

Просмотреть файл

@ -8,6 +8,7 @@
#define VideoUtils_h #define VideoUtils_h
#include "MediaInfo.h" #include "MediaInfo.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/CheckedInt.h" #include "mozilla/CheckedInt.h"
#include "mozilla/MozPromise.h" #include "mozilla/MozPromise.h"

Просмотреть файл

@ -19,7 +19,6 @@ UNIFIED_SOURCES += [
'TestMediaDataDecoder.cpp', 'TestMediaDataDecoder.cpp',
'TestMediaEventSource.cpp', 'TestMediaEventSource.cpp',
'TestMediaMIMETypes.cpp', 'TestMediaMIMETypes.cpp',
'TestMozPromise.cpp',
'TestMP3Demuxer.cpp', 'TestMP3Demuxer.cpp',
'TestMP4Demuxer.cpp', 'TestMP4Demuxer.cpp',
'TestRust.cpp', 'TestRust.cpp',

Просмотреть файл

@ -42,6 +42,9 @@ public:
mTaskQueue->Dispatch(Move(aRunnable), aFailureHandling, aReason); mTaskQueue->Dispatch(Move(aRunnable), aFailureHandling, aReason);
} }
// Prevent a GCC warning about the other overload of Dispatch being hidden.
using AbstractThread::Dispatch;
// Blocks until all tasks finish executing. // Blocks until all tasks finish executing.
void AwaitIdle() { mTaskQueue->AwaitIdle(); } void AwaitIdle() { mTaskQueue->AwaitIdle(); }

Просмотреть файл

@ -57,6 +57,7 @@
#include "mozilla/dom/EncodingUtils.h" #include "mozilla/dom/EncodingUtils.h"
#include "mozilla/ConsoleReportCollector.h" #include "mozilla/ConsoleReportCollector.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/AsyncEventDispatcher.h" #include "mozilla/AsyncEventDispatcher.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"

Просмотреть файл

@ -228,6 +228,11 @@
stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan" stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan"
clip-path="url('#circle7')" marker-mid="url(#m_atr)"/> clip-path="url('#circle7')" marker-mid="url(#m_atr)"/>
<path id="path13" d="M50,0 C 130,0 50,0 100,50
C 100,130 100,50 50,100
C -30,100 50,100 0,50
C 0,-30 0,50 50,0Z" />
<!-- use --> <!-- use -->
<use id="use1" xlink:href="#rect-10" x="50" y="50" clip-path="url('#circle8')"/> <use id="use1" xlink:href="#rect-10" x="50" y="50" clip-path="url('#circle8')"/>
<use id="use2" xlink:href="#rect-11" x="50" y="50" clip-path="url('#circle9')"/> <use id="use2" xlink:href="#rect-11" x="50" y="50" clip-path="url('#circle9')"/>

До

Ширина:  |  Высота:  |  Размер: 20 KiB

После

Ширина:  |  Высота:  |  Размер: 20 KiB

Просмотреть файл

@ -162,6 +162,7 @@ function run()
checkBBox("path10", opt, 10,25,100,75, 0); checkBBox("path10", opt, 10,25,100,75, 0);
checkBBox("path11", opt, 160,25,100,75, 0); checkBBox("path11", opt, 160,25,100,75, 0);
checkBBox("path12", opt, 10,125,100,75, 0); checkBBox("path12", opt, 10,125,100,75, 0);
checkBBox("path13", opt, 0,0,100,100, 0);
opt = { fill: false, stroke: true, markers: false, clipped: false }; opt = { fill: false, stroke: true, markers: false, clipped: false };
checkBBox("path1", opt, 2,17,116,91, 0); checkBBox("path1", opt, 2,17,116,91, 0);

Просмотреть файл

@ -51,8 +51,8 @@ SimpleTest.waitForFocus(runTest);
<div id="closure"> <div id="closure">
<div style="transform-style: preserve-3d;"> <div style="transform-style: preserve-3d;">
<div style="transform-style: preserve-3d; background-color: blue;"> <div style="transform-style: preserve-3d; background-color: blue;">
<ul> <ul style="transform-style: preserve-3d;">
<li><div id="target" class="panel"></div> <li style="transform-style:preserve-3d;"><div id="target" class="panel"></div>
</li> </li>
</ul> </ul>
</div> </div>

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "hasht.h" #include "hasht.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/dom/CallbackFunction.h" #include "mozilla/dom/CallbackFunction.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/CryptoBuffer.h" #include "mozilla/dom/CryptoBuffer.h"

Просмотреть файл

@ -6,6 +6,7 @@
#include "mozilla/dom/U2FSoftTokenManager.h" #include "mozilla/dom/U2FSoftTokenManager.h"
#include "CryptoBuffer.h" #include "CryptoBuffer.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Base64.h" #include "mozilla/Base64.h"
#include "mozilla/Casting.h" #include "mozilla/Casting.h"
#include "nsNSSComponent.h" #include "nsNSSComponent.h"

Просмотреть файл

@ -7,6 +7,7 @@
#include "hasht.h" #include "hasht.h"
#include "nsNetCID.h" #include "nsNetCID.h"
#include "nsICryptoHash.h" #include "nsICryptoHash.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/dom/AuthenticatorAttestationResponse.h" #include "mozilla/dom/AuthenticatorAttestationResponse.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"

Просмотреть файл

@ -2727,9 +2727,8 @@ nsWebBrowserPersist::MakeAndStoreLocalFilenameInURIMap(
// Create a sensibly named filename for the URI and store in the URI map // Create a sensibly named filename for the URI and store in the URI map
URIData *data; URIData *data;
if (mURIMap.Contains(spec)) if (mURIMap.Get(spec, &data))
{ {
data = mURIMap.Get(spec);
if (aNeedsPersisting) if (aNeedsPersisting)
{ {
data->mNeedsPersisting = true; data->mNeedsPersisting = true;

Просмотреть файл

@ -1641,17 +1641,16 @@ ServiceWorkerManager::GetOrCreateJobQueue(const nsACString& aKey,
{ {
MOZ_ASSERT(!aKey.IsEmpty()); MOZ_ASSERT(!aKey.IsEmpty());
ServiceWorkerManager::RegistrationDataPerPrincipal* data; ServiceWorkerManager::RegistrationDataPerPrincipal* data;
// XXX we could use LookupForAdd here to avoid a hashtable lookup, except that
// leads to a false positive assertion, see bug 1370674 comment 7.
if (!mRegistrationInfos.Get(aKey, &data)) { if (!mRegistrationInfos.Get(aKey, &data)) {
data = new RegistrationDataPerPrincipal(); data = new RegistrationDataPerPrincipal();
mRegistrationInfos.Put(aKey, data); mRegistrationInfos.Put(aKey, data);
} }
RefPtr<ServiceWorkerJobQueue> queue; RefPtr<ServiceWorkerJobQueue> queue =
if (!data->mJobQueues.Get(aScope, getter_AddRefs(queue))) { data->mJobQueues.LookupForAdd(aScope).OrInsert(
RefPtr<ServiceWorkerJobQueue> newQueue = new ServiceWorkerJobQueue(); []() { return new ServiceWorkerJobQueue(); });
queue = newQueue;
data->mJobQueues.Put(aScope, newQueue.forget());
}
return queue.forget(); return queue.forget();
} }
@ -2245,11 +2244,9 @@ ServiceWorkerManager::AddScopeAndRegistration(const nsACString& aScope,
MOZ_ASSERT(!scopeKey.IsEmpty()); MOZ_ASSERT(!scopeKey.IsEmpty());
RegistrationDataPerPrincipal* data; RegistrationDataPerPrincipal* data =
if (!swm->mRegistrationInfos.Get(scopeKey, &data)) { swm->mRegistrationInfos.LookupForAdd(scopeKey).OrInsert(
data = new RegistrationDataPerPrincipal(); []() { return new RegistrationDataPerPrincipal(); });
swm->mRegistrationInfos.Put(scopeKey, data);
}
for (uint32_t i = 0; i < data->mOrderedScopes.Length(); ++i) { for (uint32_t i = 0; i < data->mOrderedScopes.Length(); ++i) {
const nsCString& current = data->mOrderedScopes[i]; const nsCString& current = data->mOrderedScopes[i];
@ -2344,11 +2341,11 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
return; return;
} }
nsCOMPtr<nsITimer> timer = data->mUpdateTimers.Get(aRegistration->mScope); data->mUpdateTimers.LookupRemoveIf(aRegistration->mScope,
if (timer) { [] (nsCOMPtr<nsITimer>& aTimer) {
timer->Cancel(); aTimer->Cancel();
data->mUpdateTimers.Remove(aRegistration->mScope); return true; // remove it
} });
// The registration should generally only be removed if there are no controlled // The registration should generally only be removed if there are no controlled
// documents, but mControlledDocuments can contain references to potentially // documents, but mControlledDocuments can contain references to potentially
@ -2363,9 +2360,7 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
} }
RefPtr<ServiceWorkerRegistrationInfo> info; RefPtr<ServiceWorkerRegistrationInfo> info;
data->mInfos.Get(aRegistration->mScope, getter_AddRefs(info)); data->mInfos.Remove(aRegistration->mScope, getter_AddRefs(info));
data->mInfos.Remove(aRegistration->mScope);
data->mOrderedScopes.RemoveElement(aRegistration->mScope); data->mOrderedScopes.RemoveElement(aRegistration->mScope);
swm->NotifyListenersOnUnregister(info); swm->NotifyListenersOnUnregister(info);
@ -2376,14 +2371,12 @@ ServiceWorkerManager::RemoveScopeAndRegistration(ServiceWorkerRegistrationInfo*
void void
ServiceWorkerManager::MaybeRemoveRegistrationInfo(const nsACString& aScopeKey) ServiceWorkerManager::MaybeRemoveRegistrationInfo(const nsACString& aScopeKey)
{ {
RegistrationDataPerPrincipal* data; mRegistrationInfos.LookupRemoveIf(aScopeKey,
if (!mRegistrationInfos.Get(aScopeKey, &data)) { [] (RegistrationDataPerPrincipal* aData) {
return; bool remove = aData->mOrderedScopes.IsEmpty() &&
} aData->mJobQueues.Count() == 0;
return remove;
if (data->mOrderedScopes.IsEmpty() && data->mJobQueues.Count() == 0) { });
mRegistrationInfos.Remove(aScopeKey);
}
} }
void void
@ -3679,12 +3672,11 @@ ServiceWorkerManager::ForceUnregister(RegistrationDataPerPrincipal* aRegistratio
queue->CancelAll(); queue->CancelAll();
} }
nsCOMPtr<nsITimer> timer = aRegistrationData->mUpdateTimers.LookupRemoveIf(aRegistration->mScope,
aRegistrationData->mUpdateTimers.Get(aRegistration->mScope); [] (nsCOMPtr<nsITimer>& aTimer) {
if (timer) { aTimer->Cancel();
timer->Cancel(); return true; // remove it
aRegistrationData->mUpdateTimers.Remove(aRegistration->mScope); });
}
// Since Unregister is async, it is ok to call it in an enumeration. // Since Unregister is async, it is ok to call it in an enumeration.
Unregister(aRegistration->mPrincipal, nullptr, NS_ConvertUTF8toUTF16(aRegistration->mScope)); Unregister(aRegistration->mPrincipal, nullptr, NS_ConvertUTF8toUTF16(aRegistration->mScope));
@ -4250,7 +4242,7 @@ ServiceWorkerManager::ScheduleUpdateTimer(nsIPrincipal* aPrincipal,
return; return;
} }
nsCOMPtr<nsITimer> timer = data->mUpdateTimers.Get(aScope); nsCOMPtr<nsITimer>& timer = data->mUpdateTimers.GetOrInsert(aScope);
if (timer) { if (timer) {
// There is already a timer scheduled. In this case just use the original // There is already a timer scheduled. In this case just use the original
// schedule time. We don't want to push it out to a later time since that // schedule time. We don't want to push it out to a later time since that
@ -4261,6 +4253,7 @@ ServiceWorkerManager::ScheduleUpdateTimer(nsIPrincipal* aPrincipal,
timer = do_CreateInstance("@mozilla.org/timer;1", &rv); timer = do_CreateInstance("@mozilla.org/timer;1", &rv);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
data->mUpdateTimers.Remove(aScope); // another lookup, but very rare
return; return;
} }
@ -4272,10 +4265,9 @@ ServiceWorkerManager::ScheduleUpdateTimer(nsIPrincipal* aPrincipal,
rv = timer->InitWithCallback(callback, UPDATE_DELAY_MS, rv = timer->InitWithCallback(callback, UPDATE_DELAY_MS,
nsITimer::TYPE_ONE_SHOT); nsITimer::TYPE_ONE_SHOT);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
data->mUpdateTimers.Remove(aScope); // another lookup, but very rare
return; return;
} }
data->mUpdateTimers.Put(aScope, timer);
} }
void void
@ -4302,11 +4294,11 @@ ServiceWorkerManager::UpdateTimerFired(nsIPrincipal* aPrincipal,
return; return;
} }
nsCOMPtr<nsITimer> timer = data->mUpdateTimers.Get(aScope); data->mUpdateTimers.LookupRemoveIf(aScope,
if (timer) { [] (nsCOMPtr<nsITimer>& aTimer) {
timer->Cancel(); aTimer->Cancel();
data->mUpdateTimers.Remove(aScope); return true; // remove it
} });
RefPtr<ServiceWorkerRegistrationInfo> registration; RefPtr<ServiceWorkerRegistrationInfo> registration;
data->mInfos.Get(aScope, getter_AddRefs(registration)); data->mInfos.Get(aScope, getter_AddRefs(registration));

Просмотреть файл

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */ * You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ServiceWorkerUpdaterChild.h" #include "ServiceWorkerUpdaterChild.h"
#include "mozilla/AbstractThread.h"
namespace mozilla { namespace mozilla {
namespace dom { namespace dom {

Просмотреть файл

@ -6,6 +6,7 @@
#include <stdlib.h> // for getenv #include <stdlib.h> // for getenv
#include "mozilla/AbstractThread.h" // for AbstractThread
#include "mozilla/Attributes.h" // for final #include "mozilla/Attributes.h" // for final
#include "mozilla/Preferences.h" // for Preferences #include "mozilla/Preferences.h" // for Preferences
#include "mozilla/dom/Element.h" // for Element #include "mozilla/dom/Element.h" // for Element

Просмотреть файл

@ -175,7 +175,7 @@ PathSkia::GetBounds(const Matrix &aTransform) const
return Rect(); return Rect();
} }
Rect bounds = SkRectToRect(mPath.getBounds()); Rect bounds = SkRectToRect(mPath.computeTightBounds());
return aTransform.TransformBounds(bounds); return aTransform.TransformBounds(bounds);
} }
@ -195,7 +195,7 @@ PathSkia::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
SkPath result; SkPath result;
paint.getFillPath(mPath, &result); paint.getFillPath(mPath, &result);
Rect bounds = SkRectToRect(result.getBounds()); Rect bounds = SkRectToRect(result.computeTightBounds());
return aTransform.TransformBounds(bounds); return aTransform.TransformBounds(bounds);
} }

Просмотреть файл

@ -237,6 +237,27 @@ LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget, const
mTargetBounds = aRect; mTargetBounds = aRect;
} }
void
LayerManagerComposite::PostProcessLayers(nsIntRegion& aOpaqueRegion)
{
LayerIntRegion visible;
PostProcessLayers(mRoot, aOpaqueRegion, visible, Nothing());
}
// We want to skip directly through ContainerLayers that don't have an intermediate
// surface. We compute occlusions for leaves and intermediate surfaces against
// the layer that they actually composite into so that we can use the final (snapped)
// effective transform.
bool ShouldProcessLayer(Layer* aLayer)
{
if (!aLayer->GetParent() ||
!aLayer->AsContainerLayer()) {
return true;
}
return aLayer->AsContainerLayer()->UseIntermediateSurface();
}
/** /**
* Get accumulated transform of from the context creating layer to the * Get accumulated transform of from the context creating layer to the
* given layer. * given layer.
@ -258,20 +279,52 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
LayerIntRegion& aVisibleRegion, LayerIntRegion& aVisibleRegion,
const Maybe<ParentLayerIntRect>& aClipFromAncestors) const Maybe<ParentLayerIntRect>& aClipFromAncestors)
{ {
// Compute a clip that's the combination of our layer clip with the clip
// from our ancestors.
LayerComposite* composite = static_cast<LayerComposite*>(aLayer->AsHostLayer());
Maybe<ParentLayerIntRect> layerClip = composite->GetShadowClipRect();
MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(),
"The layer with a clip should not participate "
"a 3D rendering context");
Maybe<ParentLayerIntRect> outsideClip =
IntersectMaybeRects(layerClip, aClipFromAncestors);
Maybe<LayerIntRect> insideClip;
if (aLayer->Extend3DContext()) { if (aLayer->Extend3DContext()) {
// If we're preserve-3d just pass the clip rect down directly, and we'll do the
// conversion at the preserve-3d leaf Layer.
insideClip = Some(ViewAs<LayerPixel>(*outsideClip, PixelCastJustification::MovingDownToChildren));
} else if (outsideClip) {
// Convert the combined clip into our pre-transform coordinate space, so
// that it can later be intersected with our visible region.
// If our transform is a perspective, there's no meaningful insideClip rect
// we can compute (it would need to be a cone).
Matrix4x4 localTransform = GetAccTransformIn3DContext(aLayer);
if (!localTransform.HasPerspectiveComponent() && localTransform.Invert()) {
LayerRect insideClipFloat =
UntransformBy(ViewAs<ParentLayerToLayerMatrix4x4>(localTransform),
ParentLayerRect(*outsideClip),
LayerRect::MaxIntRect()).valueOr(LayerRect());
insideClipFloat.RoundOut();
LayerIntRect insideClipInt;
if (insideClipFloat.ToIntRect(&insideClipInt)) {
insideClip = Some(insideClipInt);
}
}
}
Maybe<ParentLayerIntRect> ancestorClipForChildren;
if (insideClip) {
ancestorClipForChildren =
Some(ViewAs<ParentLayerPixel>(*insideClip, PixelCastJustification::MovingDownToChildren));
}
if (!ShouldProcessLayer(aLayer)) {
MOZ_ASSERT(!aLayer->AsContainerLayer() || !aLayer->AsContainerLayer()->UseIntermediateSurface());
// For layers participating 3D rendering context, their visible // For layers participating 3D rendering context, their visible
// region should be empty (invisible), so we pass through them // region should be empty (invisible), so we pass through them
// without doing anything. // without doing anything.
// Direct children of the establisher may have a clip, becaue the
// item containing it; ex. of nsHTMLScrollFrame, may give it one.
Maybe<ParentLayerIntRect> layerClip =
aLayer->AsHostLayer()->GetShadowClipRect();
Maybe<ParentLayerIntRect> ancestorClipForChildren =
IntersectMaybeRects(layerClip, aClipFromAncestors);
MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(),
"Only direct children of the establisher could have a clip");
for (Layer* child = aLayer->GetLastChild(); for (Layer* child = aLayer->GetLastChild();
child; child;
child = child->GetPrevSibling()) { child = child->GetPrevSibling()) {
@ -284,7 +337,7 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
nsIntRegion localOpaque; nsIntRegion localOpaque;
// Treat layers on the path to the root of the 3D rendering context as // Treat layers on the path to the root of the 3D rendering context as
// a giant layer if it is a leaf. // a giant layer if it is a leaf.
Matrix4x4 transform = GetAccTransformIn3DContext(aLayer); Matrix4x4 transform = aLayer->GetEffectiveTransform();
Matrix transform2d; Matrix transform2d;
Maybe<IntPoint> integerTranslation; Maybe<IntPoint> integerTranslation;
// If aLayer has a simple transform (only an integer translation) then we // If aLayer has a simple transform (only an integer translation) then we
@ -298,44 +351,6 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
} }
} }
// Compute a clip that's the combination of our layer clip with the clip
// from our ancestors.
LayerComposite* composite = static_cast<LayerComposite*>(aLayer->AsHostLayer());
Maybe<ParentLayerIntRect> layerClip = composite->GetShadowClipRect();
MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(),
"The layer with a clip should not participate "
"a 3D rendering context");
Maybe<ParentLayerIntRect> outsideClip =
IntersectMaybeRects(layerClip, aClipFromAncestors);
// Convert the combined clip into our pre-transform coordinate space, so
// that it can later be intersected with our visible region.
// If our transform is a perspective, there's no meaningful insideClip rect
// we can compute (it would need to be a cone).
Maybe<LayerIntRect> insideClip;
if (outsideClip && !transform.HasPerspectiveComponent()) {
Matrix4x4 inverse = transform;
if (inverse.Invert()) {
Maybe<LayerRect> insideClipFloat =
UntransformBy(ViewAs<ParentLayerToLayerMatrix4x4>(inverse),
ParentLayerRect(*outsideClip),
LayerRect::MaxIntRect());
if (insideClipFloat) {
insideClipFloat->RoundOut();
LayerIntRect insideClipInt;
if (insideClipFloat->ToIntRect(&insideClipInt)) {
insideClip = Some(insideClipInt);
}
}
}
}
Maybe<ParentLayerIntRect> ancestorClipForChildren;
if (insideClip) {
ancestorClipForChildren =
Some(ViewAs<ParentLayerPixel>(*insideClip, PixelCastJustification::MovingDownToChildren));
}
// Save the value of localOpaque, which currently stores the region obscured // Save the value of localOpaque, which currently stores the region obscured
// by siblings (and uncles and such), before our descendants contribute to it. // by siblings (and uncles and such), before our descendants contribute to it.
nsIntRegion obscured = localOpaque; nsIntRegion obscured = localOpaque;
@ -345,6 +360,7 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
// - They recalculate their visible regions, taking ancestorClipForChildren // - They recalculate their visible regions, taking ancestorClipForChildren
// into account, and accumulate them into descendantsVisibleRegion. // into account, and accumulate them into descendantsVisibleRegion.
LayerIntRegion descendantsVisibleRegion; LayerIntRegion descendantsVisibleRegion;
bool hasPreserve3DChild = false; bool hasPreserve3DChild = false;
for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) { for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
PostProcessLayers(child, localOpaque, descendantsVisibleRegion, ancestorClipForChildren); PostProcessLayers(child, localOpaque, descendantsVisibleRegion, ancestorClipForChildren);
@ -378,9 +394,6 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
// for the caller to use. // for the caller to use.
ParentLayerIntRegion visibleParentSpace = TransformBy( ParentLayerIntRegion visibleParentSpace = TransformBy(
ViewAs<LayerToParentLayerMatrix4x4>(transform), visible); ViewAs<LayerToParentLayerMatrix4x4>(transform), visible);
if (const Maybe<ParentLayerIntRect>& clipRect = composite->GetShadowClipRect()) {
visibleParentSpace.AndWith(*clipRect);
}
aVisibleRegion.OrWith(ViewAs<LayerPixel>(visibleParentSpace, aVisibleRegion.OrWith(ViewAs<LayerPixel>(visibleParentSpace,
PixelCastJustification::MovingDownToChildren)); PixelCastJustification::MovingDownToChildren));
@ -392,10 +405,10 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
if (aLayer->IsOpaque()) { if (aLayer->IsOpaque()) {
localOpaque.OrWith(composite->GetFullyRenderedRegion()); localOpaque.OrWith(composite->GetFullyRenderedRegion());
} }
localOpaque.MoveBy(*integerTranslation); if (insideClip) {
if (layerClip) { localOpaque.AndWith(insideClip->ToUnknownRect());
localOpaque.AndWith(layerClip->ToUnknownRect());
} }
localOpaque.MoveBy(*integerTranslation);
aOpaqueRegion.OrWith(localOpaque); aOpaqueRegion.OrWith(localOpaque);
} }
} }
@ -449,17 +462,14 @@ void
LayerManagerComposite::UpdateAndRender() LayerManagerComposite::UpdateAndRender()
{ {
nsIntRegion invalid; nsIntRegion invalid;
bool didEffectiveTransforms = false; // The results of our drawing always go directly into a pixel buffer,
// so we don't need to pass any global transform here.
mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
nsIntRegion opaque; nsIntRegion opaque;
LayerIntRegion visible; PostProcessLayers(opaque);
PostProcessLayers(mRoot, opaque, visible, Nothing());
if (mClonedLayerTreeProperties) { if (mClonedLayerTreeProperties) {
// Effective transforms are needed by ComputeDifferences().
mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
didEffectiveTransforms = true;
// We need to compute layer tree differences even if we're not going to // We need to compute layer tree differences even if we're not going to
// immediately use the resulting damage area, since ComputeDifferences // immediately use the resulting damage area, since ComputeDifferences
// is also responsible for invalidates intermediate surfaces in // is also responsible for invalidates intermediate surfaces in
@ -502,12 +512,6 @@ LayerManagerComposite::UpdateAndRender()
// so we will invalidate after we've decided if something changed. // so we will invalidate after we've decided if something changed.
InvalidateDebugOverlay(invalid, mRenderBounds); InvalidateDebugOverlay(invalid, mRenderBounds);
if (!didEffectiveTransforms) {
// The results of our drawing always go directly into a pixel buffer,
// so we don't need to pass any global transform here.
mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4());
}
Render(invalid, opaque); Render(invalid, opaque);
#if defined(MOZ_WIDGET_ANDROID) #if defined(MOZ_WIDGET_ANDROID)
RenderToPresentationSurface(); RenderToPresentationSurface();
@ -1109,8 +1113,7 @@ LayerManagerComposite::RenderToPresentationSurface()
mRoot->ComputeEffectiveTransforms(matrix); mRoot->ComputeEffectiveTransforms(matrix);
nsIntRegion opaque; nsIntRegion opaque;
LayerIntRegion visible; PostProcessLayers(opaque);
PostProcessLayers(mRoot, opaque, visible, Nothing());
nsIntRegion invalid; nsIntRegion invalid;
IntRect bounds = IntRect::Truncate(0, 0, scale * pageWidth, actualHeight); IntRect bounds = IntRect::Truncate(0, 0, scale * pageWidth, actualHeight);

Просмотреть файл

@ -305,6 +305,7 @@ public:
* Each layer accumulates into |aVisibleRegion| its post-transform * Each layer accumulates into |aVisibleRegion| its post-transform
* (including async transforms) visible region. * (including async transforms) visible region.
*/ */
void PostProcessLayers(nsIntRegion& aOpaqueRegion);
void PostProcessLayers(Layer* aLayer, void PostProcessLayers(Layer* aLayer,
nsIntRegion& aOpaqueRegion, nsIntRegion& aOpaqueRegion,
LayerIntRegion& aVisibleRegion, LayerIntRegion& aVisibleRegion,

Просмотреть файл

@ -159,7 +159,8 @@ D3D11Checks::DoesDeviceWork()
return false; return false;
} }
if (displayLinkModuleVersion <= V(8,6,1,36484)) { if (displayLinkModuleVersion <= V(8,6,1,36484)) {
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DisplayLink: too old version " << displayLinkModuleVersionString.get(); NS_ConvertUTF16toUTF8 version(displayLinkModuleVersionString);
gfxCriticalError(CriticalLog::DefaultOptions(false)) << "DisplayLink: too old version " << version.get();
return false; return false;
} }
} }

Просмотреть файл

@ -1904,9 +1904,8 @@ imgLoader::RemoveFromCache(const ImageCacheKey& aKey)
imgCacheQueue& queue = GetCacheQueue(aKey); imgCacheQueue& queue = GetCacheQueue(aKey);
RefPtr<imgCacheEntry> entry; RefPtr<imgCacheEntry> entry;
if (cache.Get(aKey, getter_AddRefs(entry)) && entry) { cache.Remove(aKey, getter_AddRefs(entry));
cache.Remove(aKey); if (entry) {
MOZ_ASSERT(!entry->Evicted(), "Evicting an already-evicted cache entry!"); MOZ_ASSERT(!entry->Evicted(), "Evicting an already-evicted cache entry!");
// Entries with no proxies are in the tracker. // Entries with no proxies are in the tracker.

Просмотреть файл

@ -29,6 +29,7 @@
#ifdef ANDROID #ifdef ANDROID
#include "base/message_pump_android.h" #include "base/message_pump_android.h"
#endif #endif
#include "nsISerialEventTarget.h"
#ifdef MOZ_TASK_TRACER #ifdef MOZ_TASK_TRACER
#include "GeckoTaskTracer.h" #include "GeckoTaskTracer.h"
#include "TracedTaskCommon.h" #include "TracedTaskCommon.h"
@ -84,6 +85,84 @@ static LPTOP_LEVEL_EXCEPTION_FILTER GetTopSEHFilter() {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
class MessageLoop::EventTarget
: public nsISerialEventTarget
, public MessageLoop::DestructionObserver
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIEVENTTARGET_FULL
explicit EventTarget(MessageLoop* aLoop) : mLoop(aLoop) {
aLoop->AddDestructionObserver(this);
}
private:
virtual ~EventTarget() {
if (mLoop) {
mLoop->RemoveDestructionObserver(this);
}
}
void WillDestroyCurrentMessageLoop() override {
mLoop->RemoveDestructionObserver(this);
mLoop = nullptr;
}
MessageLoop* mLoop;
};
NS_IMPL_ISUPPORTS(MessageLoop::EventTarget, nsIEventTarget, nsISerialEventTarget)
NS_IMETHODIMP_(bool)
MessageLoop::EventTarget::IsOnCurrentThreadInfallible()
{
return mLoop == MessageLoop::current();
}
NS_IMETHODIMP
MessageLoop::EventTarget::IsOnCurrentThread(bool* aResult)
{
*aResult = IsOnCurrentThreadInfallible();
return NS_OK;
}
NS_IMETHODIMP
MessageLoop::EventTarget::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
{
nsCOMPtr<nsIRunnable> event(aEvent);
return Dispatch(event.forget(), aFlags);
}
NS_IMETHODIMP
MessageLoop::EventTarget::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
{
if (!mLoop) {
return NS_ERROR_NOT_INITIALIZED;
}
if (aFlags != NS_DISPATCH_NORMAL) {
return NS_ERROR_NOT_IMPLEMENTED;
}
mLoop->PostTask(Move(aEvent));
return NS_OK;
}
NS_IMETHODIMP
MessageLoop::EventTarget::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent,
uint32_t aDelayMs)
{
if (!mLoop) {
return NS_ERROR_NOT_INITIALIZED;
}
mLoop->PostDelayedTask(Move(aEvent), aDelayMs);
return NS_OK;
}
//------------------------------------------------------------------------------
// static // static
MessageLoop* MessageLoop::current() { MessageLoop* MessageLoop::current() {
return get_tls_ptr().Get(); return get_tls_ptr().Get();
@ -103,7 +182,8 @@ MessageLoop::MessageLoop(Type type, nsIThread* aThread)
#endif // OS_WIN #endif // OS_WIN
transient_hang_timeout_(0), transient_hang_timeout_(0),
permanent_hang_timeout_(0), permanent_hang_timeout_(0),
next_sequence_num_(0) { next_sequence_num_(0),
mEventTarget(new EventTarget(this)) {
DCHECK(!current()) << "should only have one message loop per thread"; DCHECK(!current()) << "should only have one message loop per thread";
get_tls_ptr().Set(this); get_tls_ptr().Set(this);
@ -248,7 +328,7 @@ bool MessageLoop::ProcessNextDelayedNonNestableTask() {
if (deferred_non_nestable_work_queue_.empty()) if (deferred_non_nestable_work_queue_.empty())
return false; return false;
RefPtr<Runnable> task = deferred_non_nestable_work_queue_.front().task.forget(); nsCOMPtr<nsIRunnable> task = deferred_non_nestable_work_queue_.front().task.forget();
deferred_non_nestable_work_queue_.pop(); deferred_non_nestable_work_queue_.pop();
RunTask(task.forget()); RunTask(task.forget());
@ -266,15 +346,15 @@ void MessageLoop::Quit() {
} }
} }
void MessageLoop::PostTask(already_AddRefed<Runnable> task) { void MessageLoop::PostTask(already_AddRefed<nsIRunnable> task) {
PostTask_Helper(Move(task), 0); PostTask_Helper(Move(task), 0);
} }
void MessageLoop::PostDelayedTask(already_AddRefed<Runnable> task, int delay_ms) { void MessageLoop::PostDelayedTask(already_AddRefed<nsIRunnable> task, int delay_ms) {
PostTask_Helper(Move(task), delay_ms); PostTask_Helper(Move(task), delay_ms);
} }
void MessageLoop::PostIdleTask(already_AddRefed<Runnable> task) { void MessageLoop::PostIdleTask(already_AddRefed<nsIRunnable> task) {
DCHECK(current() == this); DCHECK(current() == this);
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
@ -283,7 +363,7 @@ void MessageLoop::PostIdleTask(already_AddRefed<Runnable> task) {
} }
// Possibly called on a background thread! // Possibly called on a background thread!
void MessageLoop::PostTask_Helper(already_AddRefed<Runnable> task, int delay_ms) { void MessageLoop::PostTask_Helper(already_AddRefed<nsIRunnable> task, int delay_ms) {
if (nsIEventTarget* target = pump_->GetXPCOMThread()) { if (nsIEventTarget* target = pump_->GetXPCOMThread()) {
nsresult rv; nsresult rv;
if (delay_ms) { if (delay_ms) {
@ -296,7 +376,7 @@ void MessageLoop::PostTask_Helper(already_AddRefed<Runnable> task, int delay_ms)
} }
#ifdef MOZ_TASK_TRACER #ifdef MOZ_TASK_TRACER
RefPtr<Runnable> tracedTask = task; nsCOMPtr<nsIRunnable> tracedTask = task;
if (mozilla::tasktracer::IsStartLogging()) { if (mozilla::tasktracer::IsStartLogging()) {
tracedTask = mozilla::tasktracer::CreateTracedRunnable(Move(task)); tracedTask = mozilla::tasktracer::CreateTracedRunnable(Move(task));
(static_cast<mozilla::tasktracer::TracedRunnable*>(tracedTask.get()))->DispatchTask(); (static_cast<mozilla::tasktracer::TracedRunnable*>(tracedTask.get()))->DispatchTask();
@ -352,12 +432,12 @@ bool MessageLoop::NestableTasksAllowed() const {
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void MessageLoop::RunTask(already_AddRefed<Runnable> aTask) { void MessageLoop::RunTask(already_AddRefed<nsIRunnable> aTask) {
DCHECK(nestable_tasks_allowed_); DCHECK(nestable_tasks_allowed_);
// Execute the task and assume the worst: It is probably not reentrant. // Execute the task and assume the worst: It is probably not reentrant.
nestable_tasks_allowed_ = false; nestable_tasks_allowed_ = false;
RefPtr<Runnable> task = aTask; nsCOMPtr<nsIRunnable> task = aTask;
task->Run(); task->Run();
task = nullptr; task = nullptr;
@ -524,6 +604,13 @@ bool MessageLoop::PendingTask::operator<(const PendingTask& other) const {
return (sequence_num - other.sequence_num) > 0; return (sequence_num - other.sequence_num) > 0;
} }
//------------------------------------------------------------------------------
// MessageLoop::SerialEventTarget
nsISerialEventTarget* MessageLoop::SerialEventTarget() {
return mEventTarget;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// MessageLoopForUI // MessageLoopForUI

Просмотреть файл

@ -26,8 +26,11 @@
#endif #endif
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsIRunnable.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
class nsISerialEventTarget;
class nsIThread; class nsIThread;
namespace mozilla { namespace mozilla {
@ -112,12 +115,12 @@ public:
// NOTE: These methods may be called on any thread. The Task will be invoked // NOTE: These methods may be called on any thread. The Task will be invoked
// on the thread that executes MessageLoop::Run(). // on the thread that executes MessageLoop::Run().
void PostTask(already_AddRefed<mozilla::Runnable> task); void PostTask(already_AddRefed<nsIRunnable> task);
void PostDelayedTask(already_AddRefed<mozilla::Runnable> task, int delay_ms); void PostDelayedTask(already_AddRefed<nsIRunnable> task, int delay_ms);
// PostIdleTask is not thread safe and should be called on this thread // PostIdleTask is not thread safe and should be called on this thread
void PostIdleTask(already_AddRefed<mozilla::Runnable> task); void PostIdleTask(already_AddRefed<nsIRunnable> task);
// Run the message loop. // Run the message loop.
void Run(); void Run();
@ -143,6 +146,9 @@ public:
} }
}; };
// Return an XPCOM-compatible event target for this thread.
nsISerialEventTarget* SerialEventTarget();
// A MessageLoop has a particular type, which indicates the set of // A MessageLoop has a particular type, which indicates the set of
// asynchronous events it may process in addition to tasks and timers. // asynchronous events it may process in addition to tasks and timers.
// //
@ -282,12 +288,12 @@ public:
// This structure is copied around by value. // This structure is copied around by value.
struct PendingTask { struct PendingTask {
RefPtr<mozilla::Runnable> task; // The task to run. nsCOMPtr<nsIRunnable> task; // The task to run.
base::TimeTicks delayed_run_time; // The time when the task should be run. base::TimeTicks delayed_run_time; // The time when the task should be run.
int sequence_num; // Secondary sort key for run time. int sequence_num; // Secondary sort key for run time.
bool nestable; // OK to dispatch from a nested loop. bool nestable; // OK to dispatch from a nested loop.
PendingTask(already_AddRefed<mozilla::Runnable> aTask, bool aNestable) PendingTask(already_AddRefed<nsIRunnable> aTask, bool aNestable)
: task(aTask), sequence_num(0), nestable(aNestable) { : task(aTask), sequence_num(0), nestable(aNestable) {
} }
@ -355,10 +361,10 @@ public:
// appended to the list work_queue_. Such re-entrancy generally happens when // appended to the list work_queue_. Such re-entrancy generally happens when
// an unrequested message pump (typical of a native dialog) is executing in // an unrequested message pump (typical of a native dialog) is executing in
// the context of a task. // the context of a task.
bool QueueOrRunTask(already_AddRefed<mozilla::Runnable> new_task); bool QueueOrRunTask(already_AddRefed<nsIRunnable> new_task);
// Runs the specified task and deletes it. // Runs the specified task and deletes it.
void RunTask(already_AddRefed<mozilla::Runnable> task); void RunTask(already_AddRefed<nsIRunnable> task);
// Calls RunTask or queues the pending_task on the deferred task list if it // Calls RunTask or queues the pending_task on the deferred task list if it
// cannot be run right now. Returns true if the task was run. // cannot be run right now. Returns true if the task was run.
@ -378,7 +384,7 @@ public:
bool DeletePendingTasks(); bool DeletePendingTasks();
// Post a task to our incomming queue. // Post a task to our incomming queue.
void PostTask_Helper(already_AddRefed<mozilla::Runnable> task, int delay_ms); void PostTask_Helper(already_AddRefed<nsIRunnable> task, int delay_ms);
// base::MessagePump::Delegate methods: // base::MessagePump::Delegate methods:
virtual bool DoWork() override; virtual bool DoWork() override;
@ -436,6 +442,9 @@ public:
// The next sequence number to use for delayed tasks. // The next sequence number to use for delayed tasks.
int next_sequence_num_; int next_sequence_num_;
class EventTarget;
RefPtr<EventTarget> mEventTarget;
DISALLOW_COPY_AND_ASSIGN(MessageLoop); DISALLOW_COPY_AND_ASSIGN(MessageLoop);
}; };

Просмотреть файл

@ -7,8 +7,6 @@
#include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/MessageChannel.h"
#include "MessageLoopAbstractThreadWrapper.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"
@ -750,23 +748,6 @@ MessageChannel::Clear()
} }
} }
class AbstractThreadWrapperCleanup : public MessageLoop::DestructionObserver
{
public:
explicit AbstractThreadWrapperCleanup(already_AddRefed<AbstractThread> aWrapper)
: mWrapper(aWrapper)
{}
virtual ~AbstractThreadWrapperCleanup() override {}
virtual void WillDestroyCurrentMessageLoop() override
{
mWrapper = nullptr;
MessageLoop::current()->RemoveDestructionObserver(this);
delete this;
}
private:
RefPtr<AbstractThread> mWrapper;
};
bool bool
MessageChannel::Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide) MessageChannel::Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide)
{ {
@ -778,13 +759,6 @@ MessageChannel::Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide)
mWorkerLoop->AddDestructionObserver(this); mWorkerLoop->AddDestructionObserver(this);
mListener->SetIsMainThreadProtocol(); mListener->SetIsMainThreadProtocol();
if (!AbstractThread::GetCurrent()) {
mWorkerLoop->AddDestructionObserver(
new AbstractThreadWrapperCleanup(
MessageLoopAbstractThreadWrapper::Create(mWorkerLoop)));
}
ProcessLink *link = new ProcessLink(this); ProcessLink *link = new ProcessLink(this);
link->Open(aTransport, aIOLoop, aSide); // :TODO: n.b.: sets mChild link->Open(aTransport, aIOLoop, aSide); // :TODO: n.b.: sets mChild
mLink = link; mLink = link;
@ -864,12 +838,6 @@ MessageChannel::CommonThreadOpenInit(MessageChannel *aTargetChan, Side aSide)
mWorkerLoop->AddDestructionObserver(this); mWorkerLoop->AddDestructionObserver(this);
mListener->SetIsMainThreadProtocol(); mListener->SetIsMainThreadProtocol();
if (!AbstractThread::GetCurrent()) {
mWorkerLoop->AddDestructionObserver(
new AbstractThreadWrapperCleanup(
MessageLoopAbstractThreadWrapper::Create(mWorkerLoop)));
}
mLink = new ThreadLink(this, aTargetChan); mLink = new ThreadLink(this, aTargetChan);
mSide = aSide; mSide = aSide;
} }

Просмотреть файл

@ -1,159 +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_ipc_glue_MessageLoopAbstractThreadWrapper_h
#define mozilla_ipc_glue_MessageLoopAbstractThreadWrapper_h
#include "mozilla/AbstractThread.h"
#include "base/message_loop.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace ipc {
class MessageLoopAbstractThreadWrapper : public AbstractThread
{
public:
static already_AddRefed<AbstractThread>
Create(MessageLoop* aMessageLoop)
{
RefPtr<MessageLoopAbstractThreadWrapper> wrapper =
new MessageLoopAbstractThreadWrapper(aMessageLoop);
bool onCurrentThread = (aMessageLoop == MessageLoop::current());
if (onCurrentThread) {
sCurrentThreadTLS.set(wrapper);
return wrapper.forget();
}
// Set the thread-local sCurrentThreadTLS to point to the wrapper on the
// target thread. This ensures that sCurrentThreadTLS is as expected by
// AbstractThread::GetCurrent() on the target thread.
RefPtr<Runnable> r =
NS_NewRunnableFunction([wrapper]() { sCurrentThreadTLS.set(wrapper); });
aMessageLoop->PostTask(r.forget());
return wrapper.forget();
}
virtual void Dispatch(already_AddRefed<nsIRunnable> aRunnable,
DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
DispatchReason aReason = NormalDispatch) override
{
MOZ_RELEASE_ASSERT(aReason == NormalDispatch, "Only supports NormalDispatch");
RefPtr<Runnable> runner(new Runner(this, Move(aRunnable)));
mMessageLoop->PostTask(runner.forget());
}
virtual bool IsCurrentThreadIn() override
{
MessageLoop* messageLoop = MessageLoop::current();
bool in = (mMessageLoop == messageLoop);
return in;
}
virtual TaskDispatcher& TailDispatcher() override
{
MOZ_CRASH("Not supported!");
TaskDispatcher* dispatcher = nullptr;
return *dispatcher;
}
virtual bool MightHaveTailTasks() override
{
return false;
}
private:
explicit MessageLoopAbstractThreadWrapper(MessageLoop* aMessageLoop)
: AbstractThread(false)
, mMessageLoop(aMessageLoop)
{
}
MessageLoop* mMessageLoop;
class Runner : public CancelableRunnable {
class MOZ_STACK_CLASS AutoTaskGuard final {
public:
explicit AutoTaskGuard(MessageLoopAbstractThreadWrapper* aThread)
: mLastCurrentThread(nullptr)
{
MOZ_ASSERT(aThread);
mLastCurrentThread = sCurrentThreadTLS.get();
sCurrentThreadTLS.set(aThread);
}
~AutoTaskGuard()
{
sCurrentThreadTLS.set(mLastCurrentThread);
}
private:
AbstractThread* mLastCurrentThread;
};
public:
explicit Runner(MessageLoopAbstractThreadWrapper* aThread,
already_AddRefed<nsIRunnable> aRunnable)
: mThread(aThread)
, mRunnable(aRunnable)
{
}
NS_IMETHOD Run() override
{
AutoTaskGuard taskGuard(mThread);
MOZ_ASSERT(mThread == AbstractThread::GetCurrent());
MOZ_ASSERT(mThread->IsCurrentThreadIn());
nsresult rv = mRunnable->Run();
return rv;
}
nsresult Cancel() override
{
// Set the TLS during Cancel() just in case it calls Run().
AutoTaskGuard taskGuard(mThread);
nsresult rv = NS_OK;
// Try to cancel the runnable if it implements the right interface.
// Otherwise just skip the runnable.
nsCOMPtr<nsICancelableRunnable> cr = do_QueryInterface(mRunnable);
if (cr) {
rv = cr->Cancel();
}
return rv;
}
NS_IMETHOD GetName(nsACString& aName) override
{
aName.AssignLiteral("AbstractThread::Runner");
if (nsCOMPtr<nsINamed> named = do_QueryInterface(mRunnable)) {
nsAutoCString name;
named->GetName(name);
if (!name.IsEmpty()) {
aName.AppendLiteral(" for ");
aName.Append(name);
}
}
return NS_OK;
}
private:
RefPtr<MessageLoopAbstractThreadWrapper> mThread;
RefPtr<nsIRunnable> mRunnable;
};
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_glue_MessageLoopAbstractThreadWrapper_h

Просмотреть файл

@ -2,6 +2,7 @@
#include "IPDLUnitTests.h" // fail etc. #include "IPDLUnitTests.h" // fail etc.
#include "mozilla/AbstractThread.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
namespace mozilla { namespace mozilla {
@ -26,10 +27,7 @@ TestAsyncReturnsParent::~TestAsyncReturnsParent()
void void
TestAsyncReturnsParent::Main() TestAsyncReturnsParent::Main()
{ {
if (!AbstractThread::MainThread()) { SendNoReturn()->Then(MessageLoop::current()->SerialEventTarget(), __func__,
fail("AbstractThread not initalized");
}
SendNoReturn()->Then(AbstractThread::MainThread(), __func__,
[](bool unused) { [](bool unused) {
fail("resolve handler should not be called"); fail("resolve handler should not be called");
}, },
@ -41,7 +39,7 @@ TestAsyncReturnsParent::Main()
} }
passed("reject handler called on channel close"); passed("reject handler called on channel close");
}); });
SendPing()->Then(AbstractThread::MainThread(), __func__, SendPing()->Then(MessageLoop::current()->SerialEventTarget(), __func__,
[this](bool one) { [this](bool one) {
if (one) { if (one) {
passed("take one argument"); passed("take one argument");
@ -87,10 +85,7 @@ TestAsyncReturnsChild::RecvNoReturn(NoReturnResolver&& aResolve)
mozilla::ipc::IPCResult mozilla::ipc::IPCResult
TestAsyncReturnsChild::RecvPing(PingResolver&& aResolve) TestAsyncReturnsChild::RecvPing(PingResolver&& aResolve)
{ {
if (!AbstractThread::MainThread()) { SendPong()->Then(MessageLoop::current()->SerialEventTarget(), __func__,
fail("AbstractThread not initalized");
}
SendPong()->Then(AbstractThread::MainThread(), __func__,
[aResolve](const Tuple<uint32_t, uint32_t>& aParam) { [aResolve](const Tuple<uint32_t, uint32_t>& aParam) {
if (Get<0>(aParam) == sMagic1 && Get<1>(aParam) == sMagic2) { if (Get<0>(aParam) == sMagic1 && Get<1>(aParam) == sMagic2) {
passed("take two arguments"); passed("take two arguments");

Просмотреть файл

@ -85,7 +85,7 @@ GUIDToString(REFGUID aGuid, nsAString& aOutString)
// to include curly braces and dashes. // to include curly braces and dashes.
const int kBufLenWithNul = 39; const int kBufLenWithNul = 39;
aOutString.SetLength(kBufLenWithNul); aOutString.SetLength(kBufLenWithNul);
int result = StringFromGUID2(aGuid, wwc(aOutString.BeginWriting()), kBufLenWithNul); int result = StringFromGUID2(aGuid, char16ptr_t(aOutString.BeginWriting()), kBufLenWithNul);
MOZ_ASSERT(result); MOZ_ASSERT(result);
if (result) { if (result) {
// Truncate the terminator // Truncate the terminator

Просмотреть файл

@ -2006,9 +2006,7 @@ nsPresContext::ForceCacheLang(nsIAtom *aLanguage)
{ {
// force it to be cached // force it to be cached
GetDefaultFont(kPresContext_DefaultVariableFont_ID, aLanguage); GetDefaultFont(kPresContext_DefaultVariableFont_ID, aLanguage);
if (!mLanguagesUsed.Contains(aLanguage)) { mLanguagesUsed.PutEntry(aLanguage);
mLanguagesUsed.PutEntry(aLanguage);
}
} }
void void

Просмотреть файл

@ -1392,7 +1392,8 @@ nsIFrame::Combines3DTransformWithAncestors(const nsStyleDisplay* aStyleDisplay,
EffectSet* aEffectSet) const EffectSet* aEffectSet) const
{ {
MOZ_ASSERT(aStyleDisplay == StyleDisplay()); MOZ_ASSERT(aStyleDisplay == StyleDisplay());
if (!GetParent() || !GetParent()->Extend3DContext(aEffectSet)) { nsIFrame* parent = GetFlattenedTreeParentPrimaryFrame();
if (!parent || !parent->Extend3DContext()) {
return false; return false;
} }
return IsTransformed(aStyleDisplay,aEffectSet) || return IsTransformed(aStyleDisplay,aEffectSet) ||
@ -2320,9 +2321,9 @@ FrameParticipatesIn3DContext(nsIFrame* aAncestor, nsIFrame* aDescendant) {
MOZ_ASSERT(aAncestor != aDescendant); MOZ_ASSERT(aAncestor != aDescendant);
MOZ_ASSERT(aAncestor->Extend3DContext()); MOZ_ASSERT(aAncestor->Extend3DContext());
nsIFrame* frame; nsIFrame* frame;
for (frame = nsLayoutUtils::GetCrossDocParentFrame(aDescendant); for (frame = aDescendant->GetFlattenedTreeParentPrimaryFrame();
frame && aAncestor != frame; frame && aAncestor != frame;
frame = nsLayoutUtils::GetCrossDocParentFrame(frame)) { frame = frame->GetFlattenedTreeParentPrimaryFrame()) {
if (!frame->Extend3DContext()) { if (!frame->Extend3DContext()) {
return false; return false;
} }
@ -6277,6 +6278,16 @@ nsIFrame::GetNearestWidget(nsPoint& aOffset) const
return widget; return widget;
} }
nsIFrame*
nsIFrame::GetFlattenedTreeParentPrimaryFrame() const
{
if (!GetContent()) {
return nullptr;
}
nsIContent* parent = GetContent()->GetFlattenedTreeParent();
return parent ? parent->GetPrimaryFrame() : nullptr;
}
Matrix4x4 Matrix4x4
nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor, nsIFrame::GetTransformMatrix(const nsIFrame* aStopAtAncestor,
nsIFrame** aOutAncestor, nsIFrame** aOutAncestor,

Просмотреть файл

@ -836,6 +836,12 @@ public:
*/ */
inline nsContainerFrame* GetInFlowParent(); inline nsContainerFrame* GetInFlowParent();
/**
* Gets the primary frame of the Content's flattened tree
* parent, if one exists.
*/
inline nsIFrame* GetFlattenedTreeParentPrimaryFrame() const;
/** /**
* Return the placeholder for this frame (which must be out-of-flow). * Return the placeholder for this frame (which must be out-of-flow).
* @note this will only return non-null if |this| is the first-in-flow * @note this will only return non-null if |this| is the first-in-flow

Просмотреть файл

@ -4383,6 +4383,13 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
layerState == LAYER_ACTIVE_FORCE) { layerState == LAYER_ACTIVE_FORCE) {
newLayerEntry->mPropagateComponentAlphaFlattening = false; newLayerEntry->mPropagateComponentAlphaFlattening = false;
} }
float contentXScale = 1.0f;
float contentYScale = 1.0f;
if (ContainerLayer* ownContainer = ownLayer->AsContainerLayer()) {
contentXScale = 1 / ownContainer->GetPreXScale();
contentYScale = 1 / ownContainer->GetPreYScale();
}
// nsDisplayTransform::BuildLayer must set layerContentsVisibleRect. // nsDisplayTransform::BuildLayer must set layerContentsVisibleRect.
// We rely on this to ensure 3D transforms compute a reasonable // We rely on this to ensure 3D transforms compute a reasonable
// layer visible region. // layer visible region.
@ -4400,7 +4407,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
// to avoid failure caused by singular transforms. // to avoid failure caused by singular transforms.
newLayerEntry->mUntransformedVisibleRegion = true; newLayerEntry->mUntransformedVisibleRegion = true;
newLayerEntry->mVisibleRegion = newLayerEntry->mVisibleRegion =
item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel); item->GetVisibleRectForChildren().ScaleToOutsidePixels(contentXScale, contentYScale, mAppUnitsPerDevPixel);
} else { } else {
newLayerEntry->mVisibleRegion = itemVisibleRegion; newLayerEntry->mVisibleRegion = itemVisibleRegion;
} }
@ -4414,7 +4421,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
(item->Frame()->IsPreserve3DLeaf() || (item->Frame()->IsPreserve3DLeaf() ||
item->Frame()->HasPerspective()); item->Frame()->HasPerspective());
const nsIntRegion &visible = useChildrenVisible ? const nsIntRegion &visible = useChildrenVisible ?
item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel): item->GetVisibleRectForChildren().ScaleToOutsidePixels(contentXScale, contentYScale, mAppUnitsPerDevPixel):
itemVisibleRegion; itemVisibleRegion;
SetOuterVisibleRegionForLayer(ownLayer, visible, SetOuterVisibleRegionForLayer(ownLayer, visible,

Просмотреть файл

@ -1719,12 +1719,15 @@ nsDisplayListBuilder::AddToWillChangeBudget(nsIFrame* aFrame,
} }
nsPresContext* key = aFrame->PresContext(); nsPresContext* key = aFrame->PresContext();
if (!mWillChangeBudget.Contains(key)) {
mWillChangeBudget.Put(key, DocumentWillChangeBudget());
}
DocumentWillChangeBudget budget; DocumentWillChangeBudget budget;
mWillChangeBudget.Get(key, &budget); auto willChangeBudgetEntry = mWillChangeBudget.LookupForAdd(key);
if (willChangeBudgetEntry) {
// We have an existing entry.
budget = willChangeBudgetEntry.Data();
} else {
budget = DocumentWillChangeBudget();
willChangeBudgetEntry.OrInsert([&budget] () { return budget; });
}
nsRect area = aFrame->PresContext()->GetVisibleArea(); nsRect area = aFrame->PresContext()->GetVisibleArea();
uint32_t budgetLimit = nsPresContext::AppUnitsToIntCSSPixels(area.width) * uint32_t budgetLimit = nsPresContext::AppUnitsToIntCSSPixels(area.width) *
@ -1736,7 +1739,7 @@ nsDisplayListBuilder::AddToWillChangeBudget(nsIFrame* aFrame,
if (onBudget) { if (onBudget) {
budget.mBudget += cost; budget.mBudget += cost;
mWillChangeBudget.Put(key, budget); willChangeBudgetEntry.Data() = budget;
mWillChangeBudgetSet.PutEntry(aFrame); mWillChangeBudgetSet.PutEntry(aFrame);
} }

Просмотреть файл

@ -73,7 +73,7 @@ fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-parent.html animate-preserve3d
fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac fuzzy-if(cocoaWidget,128,9) == animate-preserve3d-child.html animate-preserve3d-ref.html # intermittently fuzzy on Mac
== animate-backface-hidden.html about:blank == animate-backface-hidden.html about:blank
fails-if(webrender) == 1245450-1.html green-rect.html fails-if(webrender) == 1245450-1.html green-rect.html
fuzzy(1,2000) fails-if(webrender) == opacity-preserve3d-1.html opacity-preserve3d-1-ref.html fuzzy(1,2000) == opacity-preserve3d-1.html opacity-preserve3d-1-ref.html
fuzzy(1,15000) == opacity-preserve3d-2.html opacity-preserve3d-2-ref.html fuzzy(1,15000) == opacity-preserve3d-2.html opacity-preserve3d-2-ref.html
fuzzy(1,10000) == opacity-preserve3d-3.html opacity-preserve3d-3-ref.html fuzzy(1,10000) == opacity-preserve3d-3.html opacity-preserve3d-3-ref.html
fuzzy(1,10000) == opacity-preserve3d-4.html opacity-preserve3d-4-ref.html fuzzy(1,10000) == opacity-preserve3d-4.html opacity-preserve3d-4-ref.html

Просмотреть файл

@ -139,9 +139,8 @@ CSSVariableDeclarations::MapRuleInfoInto(nsRuleData* aRuleData)
nsDataHashtable<nsStringHashKey, nsString>& variables = nsDataHashtable<nsStringHashKey, nsString>& variables =
aRuleData->mVariables->mVariables; aRuleData->mVariables->mVariables;
const nsAString& aName = iter.Key(); const nsAString& aName = iter.Key();
if (!variables.Contains(aName)) { variables.LookupForAdd(aName).OrInsert(
variables.Put(aName, iter.UserData()); [&iter] () { return iter.UserData(); });
}
} }
} }
} }

Просмотреть файл

@ -98,13 +98,6 @@ if CONFIG['CLANG_CL'] or not CONFIG['_MSC_VER']:
elif f.endswith('avx2.c'): elif f.endswith('avx2.c'):
SOURCES[f].flags += ['-mavx2'] SOURCES[f].flags += ['-mavx2']
if CONFIG['_MSC_VER'] and not config['CLANG_CL']:
for f in SOURCES:
if f.endswith('avx.c'):
SOURCES[f].flags += ['-arch:AVX']
if f.endswith('avx2.c'):
SOURCES[f].flags += ['-arch:AVX2']
# Suppress warnings in third-party code. # Suppress warnings in third-party code.
if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']: if CONFIG['GNU_CC'] or CONFIG['CLANG_CL']:
CFLAGS += [ CFLAGS += [

Просмотреть файл

@ -56,6 +56,12 @@ public:
{ {
return reinterpret_cast<const wchar_t*>(mPtr); return reinterpret_cast<const wchar_t*>(mPtr);
} }
operator wchar_t*()
{
return const_cast<wchar_t*>(reinterpret_cast<const wchar_t*>(mPtr));
}
operator const void*() const operator const void*() const
{ {
return mPtr; return mPtr;

Просмотреть файл

@ -781,6 +781,37 @@ continue_loading:
return stub_LdrLoadDll(filePath, flags, moduleFileName, handle); return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
} }
#ifdef _M_AMD64
typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
static LdrUnloadDll_func stub_LdrUnloadDll;
static NTSTATUS NTAPI
patched_LdrUnloadDll(HMODULE module)
{
// Prevent the stack walker from suspending this thread when LdrUnloadDll
// holds the RtlLookupFunctionEntry lock.
AutoSuppressStackWalking suppress;
return stub_LdrUnloadDll(module);
}
// These pointers are disguised as PVOID to avoid pulling in obscure headers
typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
PVOID ThunkAddress, ULONG Flags);
static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
static PVOID WINAPI patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
PVOID ThunkAddress, ULONG Flags)
{
// Prevent the stack walker from suspending this thread when
// LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
AutoSuppressStackWalking suppress;
return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
FailureDllHook, FailureSystemHook,
ThunkAddress, Flags);
}
#endif
#ifdef _M_IX86 #ifdef _M_IX86
static bool static bool
@ -861,6 +892,14 @@ DllBlocklist_Initialize(uint32_t aInitFlags)
Kernel32Intercept.Init("kernel32.dll"); Kernel32Intercept.Init("kernel32.dll");
#ifdef _M_AMD64 #ifdef _M_AMD64
NtDllIntercept.AddHook("LdrUnloadDll",
reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
(void**)&stub_LdrUnloadDll);
if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI",
reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
(void**)&stub_LdrResolveDelayLoadedAPI);
}
if (!IsWin8OrLater()) { if (!IsWin8OrLater()) {
// The crash that this hook works around is only seen on Win7. // The crash that this hook works around is only seen on Win7.
Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback", Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback",

Просмотреть файл

@ -192,11 +192,6 @@ StackWalkInitCriticalAddress()
#include "mozilla/StackWalk_windows.h" #include "mozilla/StackWalk_windows.h"
#include "mozilla/WindowsVersion.h" #include "mozilla/WindowsVersion.h"
#ifdef MOZ_STATIC_JS // The standalone SM build lacks the interceptor headers.
#include "nsWindowsDllInterceptor.h"
#define STACKWALK_HAS_DLL_INTERCEPTOR
#endif
#include <imagehlp.h> #include <imagehlp.h>
// We need a way to know if we are building for WXP (or later), as if we are, we // We need a way to know if we are building for WXP (or later), as if we are, we
// need to use the newer 64-bit APIs. API_VERSION_NUMBER seems to fit the bill. // need to use the newer 64-bit APIs. API_VERSION_NUMBER seems to fit the bill.
@ -285,39 +280,6 @@ UnregisterJitCodeRegion(uint8_t* aStart, size_t aSize)
sJitCodeRegionSize = 0; sJitCodeRegionSize = 0;
} }
#ifdef STACKWALK_HAS_DLL_INTERCEPTOR
static WindowsDllInterceptor NtDllInterceptor;
typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module);
static LdrUnloadDll_func stub_LdrUnloadDll;
static NTSTATUS NTAPI
patched_LdrUnloadDll(HMODULE module)
{
// Prevent the stack walker from suspending this thread when LdrUnloadDll
// holds the RtlLookupFunctionEntry lock.
AutoSuppressStackWalking suppress;
return stub_LdrUnloadDll(module);
}
// These pointers are disguised as PVOID to avoid pulling in obscure headers
typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase,
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
PVOID ThunkAddress, ULONG Flags);
static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI;
static PVOID WINAPI patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase,
PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook,
PVOID ThunkAddress, ULONG Flags)
{
// Prevent the stack walker from suspending this thread when
// LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock.
AutoSuppressStackWalking suppress;
return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor,
FailureDllHook, FailureSystemHook,
ThunkAddress, Flags);
}
#endif // STACKWALK_HAS_DLL_INTERCEPTOR
#endif // _M_AMD64 #endif // _M_AMD64
// Routine to print an error message to standard error. // Routine to print an error message to standard error.
@ -404,20 +366,6 @@ EnsureWalkThreadReady()
stackWalkThread = nullptr; stackWalkThread = nullptr;
readyEvent = nullptr; readyEvent = nullptr;
#if defined(_M_AMD64) && defined(STACKWALK_HAS_DLL_INTERCEPTOR)
NtDllInterceptor.Init("ntdll.dll");
NtDllInterceptor.AddHook("LdrUnloadDll",
reinterpret_cast<intptr_t>(patched_LdrUnloadDll),
(void**)&stub_LdrUnloadDll);
if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8
NtDllInterceptor.AddHook("LdrResolveDelayLoadedAPI",
reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI),
(void**)&stub_LdrResolveDelayLoadedAPI);
}
#endif
InitializeDbgHelpCriticalSection();
return walkThreadReady = true; return walkThreadReady = true;
} }
@ -675,7 +623,11 @@ MozStackWalk(MozWalkStackCallback aCallback, uint32_t aSkipFrames,
DWORD walkerReturn; DWORD walkerReturn;
struct WalkStackData data; struct WalkStackData data;
if (!EnsureWalkThreadReady()) { InitializeDbgHelpCriticalSection();
// EnsureWalkThreadReady's _beginthreadex takes a heap lock and must be
// avoided if we're walking another (i.e. suspended) thread.
if (!aThread && !EnsureWalkThreadReady()) {
return false; return false;
} }

Просмотреть файл

@ -7,6 +7,7 @@
// HttpLog.h should generally be included first // HttpLog.h should generally be included first
#include "HttpLog.h" #include "HttpLog.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/ipc/FileDescriptorSetParent.h" #include "mozilla/ipc/FileDescriptorSetParent.h"
#include "mozilla/ipc/IPCStreamUtils.h" #include "mozilla/ipc/IPCStreamUtils.h"
#include "mozilla/net/HttpChannelParent.h" #include "mozilla/net/HttpChannelParent.h"

Просмотреть файл

@ -223,6 +223,11 @@ extern "C" {
* @Since: ATK-2.16. * @Since: ATK-2.16.
*@ATK_ROLE_MATH_ROOT: An object that represents a mathematical expression *@ATK_ROLE_MATH_ROOT: An object that represents a mathematical expression
* displayed with a radical. @Since: ATK-2.16. * displayed with a radical. @Since: ATK-2.16.
*@ATK_ROLE_SUBSCRIPT: An object that contains text that is displayed as a
* subscript. @Since: ATK-2.16.
*@ATK_ROLE_SUPERSCRIPT: An object that contains text that is displayed as a
* superscript. @Since: ATK-2.16.
*@ATK_ROLE_FOOTNOTE: An object that contains the text of a footnote. @Since: ATK-2.26.
*@ATK_ROLE_LAST_DEFINED: not a valid role, used for finding end of the enumeration *@ATK_ROLE_LAST_DEFINED: not a valid role, used for finding end of the enumeration
* *
* Describes the role of an object * Describes the role of an object
@ -353,6 +358,9 @@ typedef enum
ATK_ROLE_STATIC, ATK_ROLE_STATIC,
ATK_ROLE_MATH_FRACTION, ATK_ROLE_MATH_FRACTION,
ATK_ROLE_MATH_ROOT, ATK_ROLE_MATH_ROOT,
ATK_ROLE_SUBSCRIPT,
ATK_ROLE_SUPERSCRIPT,
ATK_ROLE_FOOTNOTE,
ATK_ROLE_LAST_DEFINED ATK_ROLE_LAST_DEFINED
} AtkRole; } AtkRole;

Просмотреть файл

@ -290,6 +290,12 @@ enum IA2Role {
to the main content. If the complementary content is completely separable main to the main content. If the complementary content is completely separable main
content, it may be appropriate to use a more general role. content, it may be appropriate to use a more general role.
*/ */
IA2_ROLE_COMPLEMENTARY_CONTENT IA2_ROLE_COMPLEMENTARY_CONTENT,
/** An object representing a navigational landmark, a region on a page to
which the user may want quick access, such as navigating, searching,
perusing the primary content.
*/
IA2_ROLE_LANDMARK
}; };

Просмотреть файл

@ -46,8 +46,13 @@ class SigningMixin(BaseSigningMixin):
token = os.path.join(dirs['base_work_dir'], 'token') token = os.path.join(dirs['base_work_dir'], 'token')
nonce = os.path.join(dirs['base_work_dir'], 'nonce') nonce = os.path.join(dirs['base_work_dir'], 'nonce')
host_cert = os.path.join(signing_dir, 'host.cert') host_cert = os.path.join(signing_dir, 'host.cert')
python = sys.executable
# A mock environment is a special case, the system python isn't
# available there
if 'mock_target' in self.config:
python = 'python2.7'
cmd = [ cmd = [
sys.executable, python,
os.path.join(signing_dir, 'signtool.py'), os.path.join(signing_dir, 'signtool.py'),
'--cachedir', cache_dir, '--cachedir', cache_dir,
'-t', token, '-t', token,

Просмотреть файл

@ -7,6 +7,7 @@ from mozharness.base.log import INFO
# BalrogMixin {{{1 # BalrogMixin {{{1
class BalrogMixin(object): class BalrogMixin(object):
@staticmethod @staticmethod
def _query_balrog_username(server_config, product=None): def _query_balrog_username(server_config, product=None):
username = server_config["balrog_usernames"].get(product) username = server_config["balrog_usernames"].get(product)
@ -15,6 +16,15 @@ class BalrogMixin(object):
else: else:
raise KeyError("Couldn't find balrog username.") raise KeyError("Couldn't find balrog username.")
def query_python(self):
python = sys.executable
# A mock environment is a special case, the system python isn't
# available there
if 'mock_target' in self.config:
python = 'python2.7'
return python
def generate_balrog_props(self, props_path): def generate_balrog_props(self, props_path):
self.set_buildbot_property( self.set_buildbot_property(
"hashType", self.config.get("hash_type", "sha512"), write_to_file=True "hashType", self.config.get("hash_type", "sha512"), write_to_file=True
@ -57,7 +67,7 @@ class BalrogMixin(object):
self.generate_balrog_props(props_path) self.generate_balrog_props(props_path)
cmd = [ cmd = [
sys.executable, self.query_python(),
submitter_script, submitter_script,
"--build-properties", props_path, "--build-properties", props_path,
"-t", release_type, "-t", release_type,
@ -91,7 +101,10 @@ class BalrogMixin(object):
def submit_balrog_release_pusher(self, dirs): def submit_balrog_release_pusher(self, dirs):
product = self.buildbot_config["properties"]["product"] product = self.buildbot_config["properties"]["product"]
cmd = [sys.executable, os.path.join(os.path.join(dirs['abs_tools_dir'], "scripts/updates/balrog-release-pusher.py"))] cmd = [
self.query_python(),
os.path.join(os.path.join(dirs['abs_tools_dir'], "scripts/updates/balrog-release-pusher.py"))
]
cmd.extend(["--build-properties", os.path.join(dirs["base_work_dir"], "balrog_props.json")]) cmd.extend(["--build-properties", os.path.join(dirs["base_work_dir"], "balrog_props.json")])
cmd.extend(["--buildbot-configs", "https://hg.mozilla.org/build/buildbot-configs"]) cmd.extend(["--buildbot-configs", "https://hg.mozilla.org/build/buildbot-configs"])
cmd.extend(["--release-config", os.path.join(dirs['build_dir'], self.config.get("release_config_file"))]) cmd.extend(["--release-config", os.path.join(dirs['build_dir'], self.config.get("release_config_file"))])
@ -131,7 +144,7 @@ class BalrogMixin(object):
) )
cmd = [ cmd = [
sys.executable, self.query_python(),
submitter_script, submitter_script,
"--credentials-file", credentials_file, "--credentials-file", credentials_file,
"--api-root", c["balrog_api_root"], "--api-root", c["balrog_api_root"],

Просмотреть файл

@ -698,7 +698,12 @@ class DesktopSingleLocale(LocalesMixin, ReleaseMixin, MockMixin, BuildbotMixin,
return self._mach(target=target, env=env) return self._mach(target=target, env=env)
def _get_mach_executable(self): def _get_mach_executable(self):
return [sys.executable, 'mach'] python = sys.executable
# A mock environment is a special case, the system python isn't
# available there
if 'mock_target' in self.config:
python = 'python2.7'
return [python, 'mach']
def _get_make_executable(self): def _get_make_executable(self):
config = self.config config = self.config
@ -1042,8 +1047,14 @@ class DesktopSingleLocale(LocalesMixin, ReleaseMixin, MockMixin, BuildbotMixin,
return self.warning(ERROR_MSGS['tooltool_manifest_undetermined']) return self.warning(ERROR_MSGS['tooltool_manifest_undetermined'])
tooltool_manifest_path = os.path.join(dirs['abs_mozilla_dir'], tooltool_manifest_path = os.path.join(dirs['abs_mozilla_dir'],
manifest_src) manifest_src)
python = sys.executable
# A mock environment is a special case, the system python isn't
# available there
if 'mock_target' in self.config:
python = 'python2.7'
cmd = [ cmd = [
sys.executable, '-u', python, '-u',
os.path.join(dirs['abs_mozilla_dir'], 'mach'), os.path.join(dirs['abs_mozilla_dir'], 'mach'),
'artifact', 'artifact',
'toolchain', 'toolchain',

Просмотреть файл

@ -77,3 +77,35 @@ add_task(async function tabsSendMessageReply() {
await extension.awaitFinish("sendMessage"); await extension.awaitFinish("sendMessage");
await extension.unload(); await extension.unload();
}); });
add_task(async function tabsSendMessageBlob() {
function background() {
browser.runtime.onMessage.addListener(msg => {
browser.test.assertTrue(msg.blob instanceof Blob, "Message is a blob");
return Promise.resolve(msg);
});
let childFrame = document.createElement("iframe");
childFrame.src = "extensionpage.html";
document.body.appendChild(childFrame);
}
function senderScript() {
browser.runtime.sendMessage({blob: new Blob(["hello"])}).then(response => {
browser.test.assertTrue(response.blob instanceof Blob, "Response is a blob");
browser.test.notifyPass("sendBlob");
});
}
let extension = ExtensionTestUtils.loadExtension({
background,
files: {
"senderScript.js": senderScript,
"extensionpage.html": `<!DOCTYPE html><meta charset="utf-8"><script src="senderScript.js"></script>`,
},
});
await extension.startup();
await extension.awaitFinish("sendBlob");
await extension.unload();
});

Просмотреть файл

@ -0,0 +1,66 @@
/* 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/. */
/* eslint-env mozilla/chrome-worker */
"use strict";
importScripts("resource://gre/modules/osfile.jsm");
const FILE_ENTRY = "201: ";
onmessage = async function(msg) {
try {
let extractedPaths = [];
let jarPath = "jar:file://" + msg.data.zipPath + "!/";
let jarResponse = await fetch(jarPath);
let dirListing = await jarResponse.text();
let lines = dirListing.split("\n");
let reader = new FileReader();
for (let line of lines) {
if (!line.startsWith(FILE_ENTRY)) {
// Not a file entry, skip.
continue;
}
let lineSplits = line.split(" ");
let fileName = lineSplits[1];
// We don't need these types of files.
if (fileName == "verified_contents.json" ||
fileName == "icon-128x128.png") {
continue;
}
let filePath = jarPath + fileName;
let filePathResponse = await fetch(filePath);
let fileContents = await filePathResponse.blob();
let fileData = await new Promise(resolve => {
reader.onloadend = function() { resolve(reader.result) };
reader.readAsArrayBuffer(fileContents);
});
let profileDirPath = OS.Constants.Path.profileDir;
let installToDirPath = OS.Path.join(profileDirPath,
msg.data.relativeInstallPath);
await OS.File.makeDir(installToDirPath, {ignoreExisting: true,
unixMode: 0o755,
from: profileDirPath});
// Do not extract into directories. Extract all files to the same
// directory.
let destPath = OS.Path.join(installToDirPath, fileName);
await OS.File.writeAtomic(destPath, new Uint8Array(fileData),
{tmpPath: destPath + ".tmp"});
// Ensure files are writable and executable. Otherwise, we may be
// unable to execute or uninstall them.
await OS.File.setPermissions(destPath, {unixMode: 0o700});
extractedPaths.push(destPath);
}
postMessage({
"result": "success",
extractedPaths
});
} catch (e) {
postMessage({
"result": "fail",
"exception": e.message
});
}
}

Просмотреть файл

@ -369,27 +369,11 @@ GMPAddon.prototype = {
* into the specified location. (Which typically leties per platform) * into the specified location. (Which typically leties per platform)
* @param zipPath The path on disk of the zip file to extract * @param zipPath The path on disk of the zip file to extract
*/ */
function GMPExtractor(zipPath, installToDirPath) { function GMPExtractor(zipPath, relativeInstallPath) {
this.zipPath = zipPath; this.zipPath = zipPath;
this.installToDirPath = installToDirPath; this.relativeInstallPath = relativeInstallPath;
} }
GMPExtractor.prototype = { GMPExtractor.prototype = {
/**
* Obtains a list of all the entries in a zipfile in the format of *.*.
* This also includes files inside directories.
*
* @param zipReader the nsIZipReader to check
* @return An array of string name entries which can be used
* in nsIZipReader.extract
*/
_getZipEntries(zipReader) {
let entries = [];
let enumerator = zipReader.findEntries("*.*");
while (enumerator.hasMore()) {
entries.push(enumerator.getNext());
}
return entries;
},
/** /**
* Installs the this.zipPath contents into the directory used to store GMP * Installs the this.zipPath contents into the directory used to store GMP
* addons for the current platform. * addons for the current platform.
@ -398,70 +382,26 @@ GMPExtractor.prototype = {
* See GMPInstallManager.installAddon for resolve/rejected info * See GMPInstallManager.installAddon for resolve/rejected info
*/ */
install() { install() {
try { this._deferred = Promise.defer();
let log = getScopedLogger("GMPExtractor.install"); let deferredPromise = this._deferred;
this._deferred = Promise.defer(); let {zipPath, relativeInstallPath} = this;
log.info("Installing " + this.zipPath + "..."); let worker =
// Get the input zip file new ChromeWorker("resource://gre/modules/GMPExtractorWorker.js");
let zipFile = Cc["@mozilla.org/file/local;1"]. worker.onmessage = function(msg) {
createInstance(Ci.nsIFile); let log = getScopedLogger("GMPExtractor");
zipFile.initWithPath(this.zipPath); worker.terminate();
if (msg.data.result != "success") {
// Initialize a zipReader and obtain the entries log.error("Failed to extract zip file: " + zipPath);
var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]. return deferredPromise.reject({
createInstance(Ci.nsIZipReader); target: this,
zipReader.open(zipFile) status: msg.data.exception,
let entries = this._getZipEntries(zipReader); type: "exception"
let extractedPaths = []; });
let destDir = Cc["@mozilla.org/file/local;1"].
createInstance(Ci.nsILocalFile);
destDir.initWithPath(this.installToDirPath);
// Make sure the destination exists
if (!destDir.exists()) {
destDir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0755", 8));
} }
log.info("Successfully extracted zip file: " + zipPath);
// Extract each of the entries return deferredPromise.resolve(msg.data.extractedPaths);
entries.forEach(entry => {
// We don't need these types of files
if (entry.includes("__MACOSX") ||
entry == "_metadata/verified_contents.json" ||
entry == "imgs/icon-128x128.png") {
return;
}
let outFile = destDir.clone();
// Do not extract into directories. Extract all files to the same
// directory. DO NOT use |OS.Path.basename()| here, as in Windows it
// does not work properly with forward slashes (which we must use here).
let outBaseName = entry.slice(entry.lastIndexOf("/") + 1);
outFile.appendRelativePath(outBaseName);
zipReader.extract(entry, outFile);
extractedPaths.push(outFile.path);
// Ensure files are writable and executable. Otherwise we may be unable to
// execute or uninstall them.
outFile.permissions |= parseInt("0700", 8);
log.info(entry + " was successfully extracted to: " +
outFile.path);
});
zipReader.close();
if (!GMPInstallManager.overrideLeaveDownloadedZip) {
zipFile.remove(false);
}
log.info(this.zipPath + " was installed successfully");
this._deferred.resolve(extractedPaths);
} catch (e) {
if (zipReader) {
zipReader.close();
}
this._deferred.reject({
target: this,
status: e,
type: "exception"
});
} }
worker.postMessage({zipPath, relativeInstallPath});
return this._deferred.promise; return this._deferred.promise;
} }
}; };
@ -496,11 +436,10 @@ GMPDownloader.prototype = {
} }
return ProductAddonChecker.downloadAddon(gmpAddon).then((zipPath) => { return ProductAddonChecker.downloadAddon(gmpAddon).then((zipPath) => {
let path = OS.Path.join(OS.Constants.Path.profileDir, let relativePath = OS.Path.join(gmpAddon.id,
gmpAddon.id, gmpAddon.version);
gmpAddon.version); log.info("install to directory path: " + relativePath);
log.info("install to directory path: " + path); let gmpInstaller = new GMPExtractor(zipPath, relativePath);
let gmpInstaller = new GMPExtractor(zipPath, path);
let installPromise = gmpInstaller.install(); let installPromise = gmpInstaller.install();
return installPromise.then(extractedPaths => { return installPromise.then(extractedPaths => {
// Success, set the prefs // Success, set the prefs

Просмотреть файл

@ -196,6 +196,7 @@ EXTRA_JS_MODULES += [
'FinderIterator.jsm', 'FinderIterator.jsm',
'FormLikeFactory.jsm', 'FormLikeFactory.jsm',
'Geometry.jsm', 'Geometry.jsm',
'GMPExtractorWorker.js',
'GMPInstallManager.jsm', 'GMPInstallManager.jsm',
'GMPUtils.jsm', 'GMPUtils.jsm',
'HiddenFrame.jsm', 'HiddenFrame.jsm',

Просмотреть файл

@ -20,6 +20,7 @@
#include "nsIInterfaceRequestorUtils.h" #include "nsIInterfaceRequestorUtils.h"
#include "shared-libraries.h" #include "shared-libraries.h"
#include "js/Value.h" #include "js/Value.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/ErrorResult.h" #include "mozilla/ErrorResult.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
#include "mozilla/dom/TypedArray.h" #include "mozilla/dom/TypedArray.h"

Просмотреть файл

@ -344,7 +344,7 @@ IMMHandler::InitKeyboardLayout(nsWindow* aWindow,
// Add room for the terminating null character // Add room for the terminating null character
sIMEName.SetLength(++IMENameLength); sIMEName.SetLength(++IMENameLength);
IMENameLength = IMENameLength =
::ImmGetDescriptionW(aKeyboardLayout, wwc(sIMEName.BeginWriting()), ::ImmGetDescriptionW(aKeyboardLayout, sIMEName.get(),
IMENameLength); IMENameLength);
// Adjust the length to ignore the terminating null character // Adjust the length to ignore the terminating null character
sIMEName.SetLength(IMENameLength); sIMEName.SetLength(IMENameLength);

Просмотреть файл

@ -7,6 +7,8 @@
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
using namespace mozilla;
nsresult NS_FASTCALL nsresult NS_FASTCALL
NS_TableDrivenQI(void* aThis, REFNSIID aIID, void** aInstancePtr, NS_TableDrivenQI(void* aThis, REFNSIID aIID, void** aInstancePtr,
const QITableEntry* aEntries) const QITableEntry* aEntries)
@ -28,10 +30,15 @@ NS_TableDrivenQI(void* aThis, REFNSIID aIID, void** aInstancePtr,
} }
#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
nsAutoOwningThread::nsAutoOwningThread()
: mThread(GetCurrentVirtualThread())
{
}
void void
nsAutoOwningThread::AssertCurrentThreadOwnsMe(const char* msg) const nsAutoOwningThread::AssertCurrentThreadOwnsMe(const char* msg) const
{ {
if (MOZ_UNLIKELY(mThread != PR_GetCurrentThread())) { if (MOZ_UNLIKELY(mThread != GetCurrentVirtualThread())) {
// `msg` is a string literal by construction. // `msg` is a string literal by construction.
MOZ_CRASH_UNSAFE_OOL(msg); MOZ_CRASH_UNSAFE_OOL(msg);
} }

Просмотреть файл

@ -55,7 +55,7 @@ ToCanonicalSupports(nsISupports* aSupports)
class nsAutoOwningThread class nsAutoOwningThread
{ {
public: public:
nsAutoOwningThread() { mThread = PR_GetCurrentThread(); } nsAutoOwningThread();
// We move the actual assertion checks out-of-line to minimize code bloat, // We move the actual assertion checks out-of-line to minimize code bloat,
// but that means we have to pass a non-literal string to // but that means we have to pass a non-literal string to

Просмотреть файл

@ -229,7 +229,7 @@ nsresult GetCountryCode(nsAString& aCountryCode)
} }
// Now get the string for real // Now get the string for real
aCountryCode.SetLength(numChars); aCountryCode.SetLength(numChars);
numChars = GetGeoInfoW(geoid, GEO_ISO2, wwc(aCountryCode.BeginWriting()), numChars = GetGeoInfoW(geoid, GEO_ISO2, char16ptr_t(aCountryCode.BeginWriting()),
aCountryCode.Length(), 0); aCountryCode.Length(), 0);
if (!numChars) { if (!numChars) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;

Просмотреть файл

@ -194,6 +194,92 @@ public:
} }
} }
struct EntryPtr {
private:
EntryType& mEntry;
bool mExistingEntry;
// For debugging purposes
#ifdef DEBUG
nsBaseHashtable& mTable;
uint32_t mTableGeneration;
bool mDidInitNewEntry;
#endif
public:
EntryPtr(nsBaseHashtable& aTable, EntryType* aEntry, bool aExistingEntry)
: mEntry(*aEntry)
, mExistingEntry(aExistingEntry)
#ifdef DEBUG
, mTable(aTable)
, mTableGeneration(aTable.GetGeneration())
, mDidInitNewEntry(false)
#endif
{}
~EntryPtr()
{
MOZ_ASSERT(mExistingEntry || mDidInitNewEntry,
"Forgot to call OrInsert() on a new entry");
}
// Is there something stored in the table already?
explicit operator bool() const
{
MOZ_ASSERT(mTableGeneration == mTable.GetGeneration());
return mExistingEntry;
}
template <class F>
UserDataType OrInsert(F func)
{
MOZ_ASSERT(mTableGeneration == mTable.GetGeneration());
if (!mExistingEntry) {
mEntry.mData = func();
#ifdef DEBUG
mDidInitNewEntry = true;
#endif
}
return mEntry.mData;
}
MOZ_MUST_USE DataType& Data()
{
MOZ_ASSERT(mTableGeneration == mTable.GetGeneration());
return mEntry.mData;
}
};
/**
* Looks up aKey in the hashtable and returns an object that allows you to
* insert a new entry into the hashtable for that key if an existing entry
* isn't found for it.
*
* A typical usage of this API looks like this:
*
* auto insertedValue = table.LookupForAdd(key).OrInsert([]() {
* return newValue;
* });
*
* auto p = table.LookupForAdd(key);
* if (p) {
* // The entry already existed in the table.
* DoSomething(p.Data());
* } else {
* // An existing entry wasn't found, store a new entry in the hashtable.
* p.OrInsert([]() { return newValue; });
* }
*
* We ensure that the hashtable isn't modified before EntryPtr method calls.
* This is useful for cases where you want to insert a new entry into the
* hashtable if one doesn't exist before but would like to avoid two hashtable
* lookups.
*/
MOZ_MUST_USE EntryPtr LookupForAdd(KeyType aKey)
{
auto count = Count();
EntryType* ent = this->PutEntry(aKey);
return EntryPtr(*this, ent, count == Count());
}
// This is an iterator that also allows entry removal. Example usage: // This is an iterator that also allows entry removal. Example usage:
// //
// for (auto iter = table.Iter(); !iter.Done(); iter.Next()) { // for (auto iter = table.Iter(); !iter.Done(); iter.Next()) {

Просмотреть файл

@ -68,74 +68,6 @@ public:
* @param aKey the key to get and remove from the hashtable * @param aKey the key to get and remove from the hashtable
*/ */
void RemoveAndForget(KeyType aKey, nsAutoPtr<T>& aOut); void RemoveAndForget(KeyType aKey, nsAutoPtr<T>& aOut);
struct EntryPtr {
private:
typename base_type::EntryType& mEntry;
// For debugging purposes
#ifdef DEBUG
base_type& mTable;
uint32_t mTableGeneration;
#endif
public:
EntryPtr(base_type& aTable, typename base_type::EntryType* aEntry)
: mEntry(*aEntry)
#ifdef DEBUG
, mTable(aTable)
, mTableGeneration(aTable.GetGeneration())
#endif
{
}
~EntryPtr()
{
MOZ_ASSERT(mEntry.mData, "Entry should have been added by now");
}
explicit operator bool() const
{
// Is there something stored in the table already?
MOZ_ASSERT(mTableGeneration == mTable.GetGeneration());
return !!mEntry.mData;
}
template <class F>
T* OrInsert(F func)
{
MOZ_ASSERT(mTableGeneration == mTable.GetGeneration());
if (!mEntry.mData) {
mEntry.mData = func();
}
return mEntry.mData;
}
};
/**
* Looks up aKey in the hashtable and returns an object that allows you to
* insert a new entry into the hashtable for that key if an existing entry
* isn't found for it.
*
* A typical usage of this API looks like this:
*
* auto insertedValue = table.LookupForAdd(key).OrInsert([]() {
* return newValue;
* });
*
* auto p = table.LookupForAdd(key);
* if (p) {
* // The entry already existed in the table.
* DoSomething();
* } else {
* // An existing entry wasn't found, store a new entry in the hashtable.
* p.OrInsert([]() { return newValue; });
* }
*
* We ensure that the hashtable isn't modified before OrInsert() is called.
* This is useful for cases where you want to insert a new entry into the
* hashtable if one doesn't exist before but would like to avoid two hashtable
* lookups.
*/
MOZ_MUST_USE EntryPtr LookupForAdd(KeyType aKey);
}; };
// //
@ -148,21 +80,14 @@ T*
nsClassHashtable<KeyClass, T>::LookupOrAdd(KeyType aKey, nsClassHashtable<KeyClass, T>::LookupOrAdd(KeyType aKey,
Args&&... aConstructionArgs) Args&&... aConstructionArgs)
{ {
auto count = this->Count();
typename base_type::EntryType* ent = this->PutEntry(aKey); typename base_type::EntryType* ent = this->PutEntry(aKey);
if (!ent->mData) { if (count != this->Count()) {
ent->mData = new T(mozilla::Forward<Args>(aConstructionArgs)...); ent->mData = new T(mozilla::Forward<Args>(aConstructionArgs)...);
} }
return ent->mData; return ent->mData;
} }
template<class KeyClass, class T>
typename nsClassHashtable<KeyClass, T>::EntryPtr
nsClassHashtable<KeyClass, T>::LookupForAdd(KeyType aKey)
{
typename base_type::EntryType* ent = this->PutEntry(aKey);
return EntryPtr(*this, ent);
}
template<class KeyClass, class T> template<class KeyClass, class T>
bool bool
nsClassHashtable<KeyClass, T>::Get(KeyType aKey, T** aRetVal) const nsClassHashtable<KeyClass, T>::Get(KeyType aKey, T** aRetVal) const

Просмотреть файл

@ -354,11 +354,8 @@ nsWindowsRegKey::ReadStringValue(const nsAString& aName, nsAString& aResult)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
nsAString::iterator begin;
expandedResult.BeginWriting(begin);
resultLen = ExpandEnvironmentStringsW(flatSource.get(), resultLen = ExpandEnvironmentStringsW(flatSource.get(),
wwc(begin.get()), expandedResult.get(),
resultLen + 1); resultLen + 1);
if (resultLen <= 0) { if (resultLen <= 0) {
rv = ERROR_UNKNOWN_FEATURE; rv = ERROR_UNKNOWN_FEATURE;

Просмотреть файл

@ -61,7 +61,7 @@ HandleToFilename(HANDLE aHandle, const LARGE_INTEGER& aOffset,
do { do {
mappedFilename.SetLength(mappedFilename.Length() + MAX_PATH); mappedFilename.SetLength(mappedFilename.Length() + MAX_PATH);
len = GetMappedFileNameW(GetCurrentProcess(), view, len = GetMappedFileNameW(GetCurrentProcess(), view,
wwc(mappedFilename.BeginWriting()), mappedFilename.get(),
mappedFilename.Length()); mappedFilename.Length());
} while (!len && GetLastError() == ERROR_INSUFFICIENT_BUFFER); } while (!len && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
if (!len) { if (!len) {

Просмотреть файл

@ -995,7 +995,7 @@ nsLocalFile::ResolveShortcut()
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
wchar_t* resolvedPath = wwc(mResolvedPath.BeginWriting()); wchar_t* resolvedPath = mResolvedPath.get();
// resolve this shortcut // resolve this shortcut
nsresult rv = gResolver->Resolve(mWorkingPath.get(), resolvedPath); nsresult rv = gResolver->Resolve(mWorkingPath.get(), resolvedPath);
@ -1365,7 +1365,7 @@ nsLocalFile::Create(uint32_t aType, uint32_t aAttributes)
// Skip the first 'X:\' for the first form, and skip the first full // Skip the first 'X:\' for the first form, and skip the first full
// '\\machine\volume\' segment for the second form. // '\\machine\volume\' segment for the second form.
wchar_t* path = wwc(mResolvedPath.BeginWriting()); wchar_t* path = char16ptr_t(mResolvedPath.BeginWriting());
if (path[0] == L'\\' && path[1] == L'\\') { if (path[0] == L'\\' && path[1] == L'\\') {
// dealing with a UNC path here; skip past '\\machine\' // dealing with a UNC path here; skip past '\\machine\'
@ -3743,7 +3743,7 @@ nsDriveEnumerator::Init()
if (!mDrives.SetLength(length + 1, fallible)) { if (!mDrives.SetLength(length + 1, fallible)) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
if (!GetLogicalDriveStringsW(length, wwc(mDrives.BeginWriting()))) { if (!GetLogicalDriveStringsW(length, mDrives.get())) {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
mDrives.BeginReading(mStartOfCurrentDrive); mDrives.BeginReading(mStartOfCurrentDrive);

Просмотреть файл

@ -929,12 +929,8 @@ NS_CopyNativeToUnicode(const nsACString& aInput, nsAString& aOutput)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
if (resultLen > 0) { if (resultLen > 0) {
nsAString::iterator out_iter; char16ptr_t result = aOutput.BeginWriting();
aOutput.BeginWriting(out_iter); ::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, result, resultLen);
char16_t* result = out_iter.get();
::MultiByteToWideChar(CP_ACP, 0, buf, inputLen, wwc(result), resultLen);
} }
return NS_OK; return NS_OK;
} }
@ -978,41 +974,6 @@ NS_CopyUnicodeToNative(const nsAString& aInput, nsACString& aOutput)
return NS_OK; return NS_OK;
} }
// moved from widget/windows/nsToolkit.cpp
int32_t
NS_ConvertAtoW(const char* aStrInA, int aBufferSize, char16_t* aStrOutW)
{
return MultiByteToWideChar(CP_ACP, 0, aStrInA, -1, wwc(aStrOutW), aBufferSize);
}
int32_t
NS_ConvertWtoA(const char16_t* aStrInW, int aBufferSizeOut,
char* aStrOutA, const char* aDefault)
{
if ((!aStrInW) || (!aStrOutA) || (aBufferSizeOut <= 0)) {
return 0;
}
int numCharsConverted = WideCharToMultiByte(CP_ACP, 0, char16ptr_t(aStrInW), -1,
aStrOutA, aBufferSizeOut,
aDefault, nullptr);
if (!numCharsConverted) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
// Overflow, add missing null termination but return 0
aStrOutA[aBufferSizeOut - 1] = '\0';
} else {
// Other error, clear string and return 0
aStrOutA[0] = '\0';
}
} else if (numCharsConverted < aBufferSizeOut) {
// Add 2nd null (really necessary?)
aStrOutA[numCharsConverted] = '\0';
}
return numCharsConverted;
}
#else #else
#include "nsReadableUtils.h" #include "nsReadableUtils.h"

Просмотреть файл

@ -148,49 +148,6 @@ private:
NS_ConvertUTF8toUTF16(char16_t) = delete; NS_ConvertUTF8toUTF16(char16_t) = delete;
}; };
#ifdef MOZ_USE_CHAR16_WRAPPER
inline char16_t*
wwc(wchar_t* aStr)
{
return reinterpret_cast<char16_t*>(aStr);
}
inline wchar_t*
wwc(char16_t* aStr)
{
return reinterpret_cast<wchar_t*>(aStr);
}
inline const char16_t*
wwc(const wchar_t* aStr)
{
return reinterpret_cast<const char16_t*>(aStr);
}
inline const wchar_t*
wwc(const char16_t* aStr)
{
return reinterpret_cast<const wchar_t*>(aStr);
}
#else
inline char16_t*
wwc(char16_t* aStr)
{
return aStr;
}
inline const char16_t*
wwc(const char16_t* aStr)
{
return aStr;
}
#endif
// the following are included/declared for backwards compatibility // the following are included/declared for backwards compatibility
typedef nsAutoString nsVoidableString; typedef nsAutoString nsVoidableString;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше