mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central to fx-team
This commit is contained in:
commit
b5371fc820
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Merge day clobber
|
||||
Bug 1214058 New xpcshell test not getting picked up
|
||||
|
@ -1238,11 +1238,13 @@ Accessible::ApplyARIAState(uint64_t* aState) const
|
||||
*aState &= ~states::READONLY;
|
||||
|
||||
if (mContent->HasID()) {
|
||||
// If has a role & ID and aria-activedescendant on the container, assume focusable
|
||||
nsIContent *ancestorContent = mContent;
|
||||
while ((ancestorContent = ancestorContent->GetParent()) != nullptr) {
|
||||
if (ancestorContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant)) {
|
||||
// ancestor has activedescendant property, this content could be active
|
||||
// If has a role & ID and aria-activedescendant on the container, assume
|
||||
// focusable.
|
||||
const Accessible* ancestor = this;
|
||||
while ((ancestor = ancestor->Parent()) && !ancestor->IsDoc()) {
|
||||
dom::Element* el = ancestor->Elm();
|
||||
if (el &&
|
||||
el->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant)) {
|
||||
*aState |= states::FOCUSABLE;
|
||||
break;
|
||||
}
|
||||
@ -1251,12 +1253,12 @@ Accessible::ApplyARIAState(uint64_t* aState) const
|
||||
}
|
||||
|
||||
if (*aState & states::FOCUSABLE) {
|
||||
// Special case: aria-disabled propagates from ancestors down to any focusable descendant
|
||||
nsIContent *ancestorContent = mContent;
|
||||
while ((ancestorContent = ancestorContent->GetParent()) != nullptr) {
|
||||
if (ancestorContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_disabled,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
// ancestor has aria-disabled property, this is disabled
|
||||
// Propogate aria-disabled from ancestors down to any focusable descendant.
|
||||
const Accessible* ancestor = this;
|
||||
while ((ancestor = ancestor->Parent()) && !ancestor->IsDoc()) {
|
||||
dom::Element* el = ancestor->Elm();
|
||||
if (el && el->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_disabled,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
*aState |= states::UNAVAILABLE;
|
||||
break;
|
||||
}
|
||||
|
@ -191,6 +191,12 @@
|
||||
testGroupAttrs("table_cell", 3, 4);
|
||||
testGroupAttrs("table_row", 2, 2);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// ARIA list constructed by ARIA owns
|
||||
testGroupAttrs("t1_li1", 1, 3);
|
||||
testGroupAttrs("t1_li2", 2, 3);
|
||||
testGroupAttrs("t1_li3", 3, 3);
|
||||
|
||||
// Test that group position information updates after deleting node.
|
||||
testGroupAttrs("tree4_ti1", 1, 2, 1);
|
||||
testGroupAttrs("tree4_ti2", 2, 2, 1);
|
||||
@ -453,5 +459,11 @@
|
||||
<div role="cell" id="table_cell" aria-colindex="3">cell</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role="list" aria-owns="t1_li1 t1_li2 t1_li3">
|
||||
<div role="listitem" id="t1_li2">Apples</div>
|
||||
<div role="listitem" id="t1_li1">Oranges</div>
|
||||
</span>
|
||||
<div role="listitem" id="t1_li3">Bananas</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -51,7 +51,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
|
||||
var container = getNode(aID);
|
||||
var itemNode = document.createElement("div");
|
||||
itemNode.setAttribute("id", aNewItemID);
|
||||
itemNode.textContent = "item3";
|
||||
itemNode.textContent = aNewItemID;
|
||||
container.appendChild(itemNode);
|
||||
|
||||
container.setAttribute("aria-activedescendant", aNewItemID);
|
||||
@ -68,14 +68,15 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new synthFocus("container", new focusChecker("item1")));
|
||||
gQueue.push(new changeARIAActiveDescendant("container", "item2"));
|
||||
gQueue.push(new synthFocus("listbox", new focusChecker("item1")));
|
||||
gQueue.push(new changeARIAActiveDescendant("listbox", "item2"));
|
||||
gQueue.push(new changeARIAActiveDescendant("listbox", "item3"));
|
||||
|
||||
gQueue.push(new synthFocus("combobox_entry", new focusChecker("combobox_entry")));
|
||||
gQueue.push(new changeARIAActiveDescendant("combobox", "combobox_option2"));
|
||||
|
||||
todo(false, "No focus for inserted element, bug 687011");
|
||||
//gQueue.push(new insertItemNFocus("container", "item3"));
|
||||
//gQueue.push(new insertItemNFocus("listbox", "item4"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
@ -101,10 +102,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=429547
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div role="listbox" aria-activedescendant="item1" id="container" tabindex="1">
|
||||
<div role="listbox" aria-activedescendant="item1" id="listbox" tabindex="1"
|
||||
aria-owns="item3">
|
||||
<div role="listitem" id="item1">item1</div>
|
||||
<div role="listitem" id="item2">item2</div>
|
||||
</div>
|
||||
<div role="listitem" id="item3">item3</div>
|
||||
|
||||
<div role="combobox" id="combobox">
|
||||
<input id="combobox_entry">
|
||||
|
@ -500,7 +500,8 @@
|
||||
<!-- Test that aria-disabled state gets propagated to all descendants -->
|
||||
<div id="group" role="group" aria-disabled="true">
|
||||
<button>hi</button>
|
||||
<div tabindex="0" role="listbox" aria-activedescendant="item1">
|
||||
<div tabindex="0" role="listbox" aria-activedescendant="item1"
|
||||
aria-owns="item5">
|
||||
<div role="option" id="item1">Item 1</div>
|
||||
<div role="option" id="item2">Item 2</div>
|
||||
<div role="option" id="item3">Item 3</div>
|
||||
@ -508,6 +509,7 @@
|
||||
</div>
|
||||
<div role="slider" tabindex="0">A slider</div>
|
||||
</div>
|
||||
<div role="option" id="item5">Item 5</div>
|
||||
|
||||
<!-- Test active state -->
|
||||
<div id="as_listbox" tabindex="0" role="listbox"
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="38934e434c6c49ffdf7492f20f7258e7c3934b49"/>
|
||||
@ -31,7 +31,7 @@
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="1342fd7b4b000ac3e76a5dfe111a0de9d710b4c8"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" revision="a356cc4cab8b8e6b4642525b689c72de35dc6d12"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" revision="812c0404c93290459f7be7870702480ceea9f5d7"/>
|
||||
<project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="1b26ad444462ccbd97f6319565b4735f7bd779e5"/>
|
||||
<project name="device/common" path="device/common" revision="4e1a38704dcfadef60ed2da3cfeba02a56b069d2"/>
|
||||
<project name="device/sample" path="device/sample" revision="b045905b46c8b4ee630d0c2aee7db63eaec722d9"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "06de78d2c61c084956640c480280ba518b2fe29f",
|
||||
"git_revision": "47da49f8206788d70d834c3a63d9245d50c89103",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "53578330b30736e8fef30dee4eccf296e2d53ca3",
|
||||
"revision": "44029d7d66e6ed745dd19fc6378d1a986382fc84",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -18,7 +18,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="38934e434c6c49ffdf7492f20f7258e7c3934b49"/>
|
||||
@ -32,7 +32,7 @@
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="1342fd7b4b000ac3e76a5dfe111a0de9d710b4c8"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" revision="a356cc4cab8b8e6b4642525b689c72de35dc6d12"/>
|
||||
<project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9" revision="812c0404c93290459f7be7870702480ceea9f5d7"/>
|
||||
<project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="1b26ad444462ccbd97f6319565b4735f7bd779e5"/>
|
||||
<project name="device/common" path="device/common" revision="4e1a38704dcfadef60ed2da3cfeba02a56b069d2"/>
|
||||
<project name="device/sample" path="device/sample" revision="b045905b46c8b4ee630d0c2aee7db63eaec722d9"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="06de78d2c61c084956640c480280ba518b2fe29f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="47da49f8206788d70d834c3a63d9245d50c89103"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
|
||||
|
@ -2934,8 +2934,8 @@ var SessionStoreInternal = {
|
||||
// In case we didn't collect/receive data for any tabs yet we'll have to
|
||||
// fill the array with at least empty tabData objects until |_tPos| or
|
||||
// we'll end up with |null| entries.
|
||||
for (let tab of Array.slice(tabbrowser.tabs, 0, tab._tPos)) {
|
||||
let emptyState = {entries: [], lastAccessed: tab.lastAccessed};
|
||||
for (let otherTab of Array.slice(tabbrowser.tabs, 0, tab._tPos)) {
|
||||
let emptyState = {entries: [], lastAccessed: otherTab.lastAccessed};
|
||||
this._windows[window.__SSi].tabs.push(emptyState);
|
||||
}
|
||||
|
||||
|
@ -2162,8 +2162,8 @@ if (AppConstants.MOZ_SERVICES_HEALTHREPORT) {
|
||||
_serializeJSONDaily: function(data) {
|
||||
let result = {_v: this.version };
|
||||
|
||||
for (let [field, data] of data) {
|
||||
result[field] = data;
|
||||
for (let [field, value] of data) {
|
||||
result[field] = value;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -8,5 +8,13 @@
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
},
|
||||
{
|
||||
"size": 12057960,
|
||||
"digest": "6105d6432943141cffb40020dc5ba3a793650bdeb3af9bd5e56d3796c5f03df9962a73e521646cd71fbfb5e266c1e74716ad722fb6055589dfb7d35175bca89e",
|
||||
"algorithm": "sha512",
|
||||
"filename": "gtk3.tar.xz",
|
||||
"setup": "setup.sh",
|
||||
"unpack": true
|
||||
}
|
||||
]
|
||||
|
@ -109,6 +109,7 @@ leak:libdricore.so
|
||||
leak:libGL.so
|
||||
leak:libglib-2.0.so
|
||||
leak:libp11-kit.so
|
||||
leak:libpixman-1.so
|
||||
leak:libpulse.so
|
||||
leak:libpulsecommon-1.1.so
|
||||
leak:libresolv.so
|
||||
|
@ -1,30 +1,29 @@
|
||||
# To do try builds with Gtk+2, uncomment the following line, and remove
|
||||
# everything after that.
|
||||
#ac_add_options --enable-default-toolkit=cairo-gtk2
|
||||
|
||||
TOOLTOOL_DIR=${TOOLTOOL_DIR:-$topsrcdir}
|
||||
|
||||
# $TOOLTOOL_DIR/gtk3 comes from tooltool, when the tooltool manifest contains it.
|
||||
if [ -d "$TOOLTOOL_DIR/gtk3" ]; then
|
||||
if [ -z "$PKG_CONFIG_LIBDIR" ]; then
|
||||
echo PKG_CONFIG_LIBDIR must be set >&2
|
||||
exit 1
|
||||
fi
|
||||
export PKG_CONFIG_SYSROOT_DIR="$TOOLTOOL_DIR/gtk3"
|
||||
export PKG_CONFIG_PATH="$TOOLTOOL_DIR/gtk3/usr/local/lib/pkgconfig"
|
||||
PKG_CONFIG="$TOOLTOOL_DIR/gtk3/usr/local/bin/pkg-config"
|
||||
export PATH="$TOOLTOOL_DIR/gtk3/usr/local/bin:${PATH}"
|
||||
# Ensure cairo, gdk-pixbuf, etc. are not taken from the system installed packages.
|
||||
LDFLAGS="-L$TOOLTOOL_DIR/gtk3/usr/local/lib ${LDFLAGS}"
|
||||
ac_add_options --enable-default-toolkit=cairo-gtk3
|
||||
|
||||
# Set things up to use Gtk+3 from the tooltool package
|
||||
mk_add_options "export FONTCONFIG_PATH=$TOOLTOOL_DIR/gtk3/usr/local/etc/fonts"
|
||||
mk_add_options "export PANGO_SYSCONFDIR=$TOOLTOOL_DIR/gtk3/usr/local/etc"
|
||||
mk_add_options "export PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
|
||||
mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||
mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
|
||||
# Until a tooltool with bug 1188571 landed is available everywhere
|
||||
$TOOLTOOL_DIR/gtk3/setup.sh
|
||||
else
|
||||
PKG_CONFIG=pkg-config
|
||||
ac_add_options --enable-default-toolkit=cairo-gtk2
|
||||
# $TOOLTOOL_DIR/gtk3 comes from tooltool, and must be included in the tooltool manifest.
|
||||
if [ -z "$PKG_CONFIG_LIBDIR" ]; then
|
||||
echo PKG_CONFIG_LIBDIR must be set >&2
|
||||
exit 1
|
||||
fi
|
||||
export PKG_CONFIG_SYSROOT_DIR="$TOOLTOOL_DIR/gtk3"
|
||||
export PKG_CONFIG_PATH="$TOOLTOOL_DIR/gtk3/usr/local/lib/pkgconfig"
|
||||
PKG_CONFIG="$TOOLTOOL_DIR/gtk3/usr/local/bin/pkg-config"
|
||||
export PATH="$TOOLTOOL_DIR/gtk3/usr/local/bin:${PATH}"
|
||||
# Ensure cairo, gdk-pixbuf, etc. are not taken from the system installed packages.
|
||||
LDFLAGS="-L$TOOLTOOL_DIR/gtk3/usr/local/lib ${LDFLAGS}"
|
||||
ac_add_options --enable-default-toolkit=cairo-gtk3
|
||||
|
||||
# Set things up to use Gtk+3 from the tooltool package
|
||||
mk_add_options "export FONTCONFIG_PATH=$TOOLTOOL_DIR/gtk3/usr/local/etc/fonts"
|
||||
mk_add_options "export PANGO_SYSCONFDIR=$TOOLTOOL_DIR/gtk3/usr/local/etc"
|
||||
mk_add_options "export PANGO_LIBDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
mk_add_options "export GDK_PIXBUF_MODULE_FILE=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
|
||||
mk_add_options "export GDK_PIXBUF_MODULEDIR=$TOOLTOOL_DIR/gtk3/usr/local/lib/gdk-pixbuf-2.0/2.10.0/loaders"
|
||||
mk_add_options "export LD_LIBRARY_PATH=$TOOLTOOL_DIR/gtk3/usr/local/lib"
|
||||
|
||||
# Until a tooltool with bug 1188571 landed is available everywhere
|
||||
$TOOLTOOL_DIR/gtk3/setup.sh
|
||||
|
@ -1341,7 +1341,7 @@ endif
|
||||
# it.
|
||||
|
||||
ifneq (,$(filter-out all chrome default export realchrome clean clobber clobber_all distclean realclean,$(MAKECMDGOALS)))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES) $(addsuffix .pp,$(notdir $(sort $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)))))))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(addsuffix .pp,$(notdir $(sort $(OBJS) $(PROGOBJS) $(HOST_OBJS) $(HOST_PROGOBJS)))))))
|
||||
|
||||
ifneq (,$(MDDEPEND_FILES))
|
||||
$(call include_deps,$(MDDEPEND_FILES))
|
||||
@ -1349,16 +1349,12 @@ endif
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifneq (,$(filter export,$(MAKECMDGOALS)))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(EXTRA_EXPORT_MDDEPEND_FILES))))
|
||||
MDDEPEND_FILES := $(strip $(wildcard $(addprefix $(MDDEPDIR)/,$(EXTRA_MDDEPEND_FILES))))
|
||||
|
||||
ifneq (,$(MDDEPEND_FILES))
|
||||
$(call include_deps,$(MDDEPEND_FILES))
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
#############################################################################
|
||||
|
||||
-include $(topsrcdir)/$(MOZ_BUILD_APP)/app-rules.mk
|
||||
|
@ -265,7 +265,8 @@ self.random = {
|
||||
{
|
||||
let h, n = 0xefc8249d;
|
||||
|
||||
for (let i = 0, data = data.toString(), len = data.length; i < len; i++) {
|
||||
data = data.toString();
|
||||
for (let i = 0, len = data.length; i < len; i++) {
|
||||
n += data.charCodeAt(i);
|
||||
h = 0.02519603282416938 * n;
|
||||
n = h >>> 0;
|
||||
|
@ -126,8 +126,8 @@ function recursiveWalk(breakdown, edge, report, visitor) {
|
||||
visitor.exit(breakdown, report, edge);
|
||||
} else {
|
||||
visitor.enter(breakdown, report, edge);
|
||||
for (let { edge, referent, breakdown } of getReportEdges(breakdown, report)) {
|
||||
recursiveWalk(breakdown, edge, referent, visitor);
|
||||
for (let { edge, referent, breakdown: subBreakdown } of getReportEdges(breakdown, report)) {
|
||||
recursiveWalk(subBreakdown, edge, referent, visitor);
|
||||
}
|
||||
visitor.exit(breakdown, report, edge);
|
||||
}
|
||||
|
@ -79,6 +79,27 @@ ConsoleReportCollector::FlushConsoleReports(nsIDocument* aDocument)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ConsoleReportCollector::FlushConsoleReports(nsIConsoleReportCollector* aCollector)
|
||||
{
|
||||
MOZ_ASSERT(aCollector);
|
||||
|
||||
nsTArray<PendingReport> reports;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
mPendingReports.SwapElements(reports);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < reports.Length(); ++i) {
|
||||
PendingReport& report = reports[i];
|
||||
aCollector->AddConsoleReport(report.mErrorFlags, report.mCategory,
|
||||
report.mPropertiesFile, report.mSourceFileURI,
|
||||
report.mLineNumber, report.mColumnNumber,
|
||||
report.mMessageName, report.mStringParams);
|
||||
}
|
||||
}
|
||||
|
||||
ConsoleReportCollector::~ConsoleReportCollector()
|
||||
{
|
||||
}
|
||||
|
@ -29,6 +29,9 @@ public:
|
||||
void
|
||||
FlushConsoleReports(nsIDocument* aDocument) override;
|
||||
|
||||
void
|
||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) override;
|
||||
|
||||
private:
|
||||
~ConsoleReportCollector();
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsWeakPtr.h"
|
||||
#include "ScriptSettings.h"
|
||||
|
||||
using mozilla::Unused; // <snicker>
|
||||
using namespace mozilla::dom;
|
||||
@ -650,7 +651,10 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
||||
for (uint32_t i = 0; i < mPermissionRequests.Length(); ++i) {
|
||||
nsCString type = mPermissionRequests[i].type();
|
||||
|
||||
mozilla::AutoSafeJSContext cx;
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
|
||||
JSAutoCompartment ac(cx, obj);
|
||||
|
||||
@ -658,10 +662,12 @@ nsContentPermissionRequestProxy::Allow(JS::HandleValue aChoices)
|
||||
|
||||
if (!JS_GetProperty(cx, obj, type.BeginReading(), &val) ||
|
||||
!val.isString()) {
|
||||
// no setting for the permission type, skip it
|
||||
// no setting for the permission type, clear exception and skip it
|
||||
jsapi.ClearException();
|
||||
} else {
|
||||
nsAutoJSString choice;
|
||||
if (!choice.init(cx, val)) {
|
||||
jsapi.ClearException();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
choices.AppendElement(PermissionChoice(type, choice));
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
aLineNumber, aColumnNumber, aMessageName, params);
|
||||
}
|
||||
|
||||
// Flush all pending reports to the console.
|
||||
// Flush all pending reports to the console. Main thread only.
|
||||
//
|
||||
// aDocument An optional document representing where to flush the
|
||||
// reports. If provided, then the corresponding window's
|
||||
@ -74,6 +74,14 @@ public:
|
||||
// go to the browser console.
|
||||
virtual void
|
||||
FlushConsoleReports(nsIDocument* aDocument) = 0;
|
||||
|
||||
// Flush all pending reports to another collector. May be called from any
|
||||
// thread.
|
||||
//
|
||||
// aCollector A required collector object that will effectively take
|
||||
// ownership of our currently console reports.
|
||||
virtual void
|
||||
FlushConsoleReports(nsIConsoleReportCollector* aCollector) = 0;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIConsoleReportCollector, NS_NSICONSOLEREPORTCOLLECTOR_IID)
|
||||
|
@ -329,6 +329,12 @@ JSObject* GetDefaultScopeFromJSContext(JSContext *cx)
|
||||
|
||||
bool nsAutoJSString::init(const JS::Value &v)
|
||||
{
|
||||
return init(nsContentUtils::RootingCxForThread(), v);
|
||||
JSContext* cx = nsContentUtils::RootingCxForThread();
|
||||
if (!init(nsContentUtils::RootingCxForThread(), v)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1318,7 +1318,7 @@ BluetoothAdapter::HandlePullVCardListingReq(const BluetoothValue& aValue)
|
||||
} else if (name.EqualsLiteral("searchKey")) {
|
||||
init.mSearchKey = static_cast<vCardSearchKeyType>(value.get_uint32_t());
|
||||
} else if (name.EqualsLiteral("searchText")) {
|
||||
init.mSearchValue = value.get_nsString();
|
||||
init.mSearchValue = NS_ConvertUTF8toUTF16(value.get_nsCString());
|
||||
} else if (name.EqualsLiteral("maxListCount")) {
|
||||
init.mMaxListCount = value.get_uint32_t();
|
||||
} else if (name.EqualsLiteral("listStartOffset")) {
|
||||
|
@ -102,6 +102,8 @@ skip-if = (toolkit == 'gonk' && !debug)
|
||||
[test_browserElement_oop_VisibilityChange.html]
|
||||
[test_browserElement_oop_XFrameOptions.html]
|
||||
[test_browserElement_oop_XFrameOptionsAllowFrom.html]
|
||||
# bug 1189592
|
||||
skip-if = asan
|
||||
[test_browserElement_oop_XFrameOptionsDeny.html]
|
||||
[test_browserElement_oop_XFrameOptionsSameOrigin.html]
|
||||
# Disabled until bug 930449 makes it stop timing out
|
||||
|
@ -21,10 +21,16 @@ using namespace dom;
|
||||
using namespace gfx;
|
||||
|
||||
struct ImageCacheKey {
|
||||
ImageCacheKey(Element* aImage, HTMLCanvasElement* aCanvas)
|
||||
: mImage(aImage), mCanvas(aCanvas) {}
|
||||
ImageCacheKey(Element* aImage,
|
||||
HTMLCanvasElement* aCanvas,
|
||||
bool aIsAccelerated)
|
||||
: mImage(aImage)
|
||||
, mCanvas(aCanvas)
|
||||
, mIsAccelerated(aIsAccelerated)
|
||||
{}
|
||||
Element* mImage;
|
||||
HTMLCanvasElement* mCanvas;
|
||||
bool mIsAccelerated;
|
||||
};
|
||||
|
||||
struct ImageCacheEntryData {
|
||||
@ -32,6 +38,7 @@ struct ImageCacheEntryData {
|
||||
: mImage(aOther.mImage)
|
||||
, mILC(aOther.mILC)
|
||||
, mCanvas(aOther.mCanvas)
|
||||
, mIsAccelerated(aOther.mIsAccelerated)
|
||||
, mRequest(aOther.mRequest)
|
||||
, mSourceSurface(aOther.mSourceSurface)
|
||||
, mSize(aOther.mSize)
|
||||
@ -40,6 +47,7 @@ struct ImageCacheEntryData {
|
||||
: mImage(aKey.mImage)
|
||||
, mILC(nullptr)
|
||||
, mCanvas(aKey.mCanvas)
|
||||
, mIsAccelerated(aKey.mIsAccelerated)
|
||||
{}
|
||||
|
||||
nsExpirationState* GetExpirationState() { return &mState; }
|
||||
@ -50,6 +58,7 @@ struct ImageCacheEntryData {
|
||||
RefPtr<Element> mImage;
|
||||
nsIImageLoadingContent* mILC;
|
||||
RefPtr<HTMLCanvasElement> mCanvas;
|
||||
bool mIsAccelerated;
|
||||
// Value
|
||||
nsCOMPtr<imgIRequest> mRequest;
|
||||
RefPtr<SourceSurface> mSourceSurface;
|
||||
@ -70,46 +79,61 @@ public:
|
||||
|
||||
bool KeyEquals(KeyTypePointer key) const
|
||||
{
|
||||
return mData->mImage == key->mImage && mData->mCanvas == key->mCanvas;
|
||||
return mData->mImage == key->mImage &&
|
||||
mData->mCanvas == key->mCanvas &&
|
||||
mData->mIsAccelerated == key->mIsAccelerated;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType& key) { return &key; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer key)
|
||||
{
|
||||
return HashGeneric(key->mImage, key->mCanvas);
|
||||
return HashGeneric(key->mImage, key->mCanvas, key->mIsAccelerated);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
nsAutoPtr<ImageCacheEntryData> mData;
|
||||
};
|
||||
|
||||
struct SimpleImageCacheKey {
|
||||
SimpleImageCacheKey(const imgIRequest* aImage,
|
||||
bool aIsAccelerated)
|
||||
: mImage(aImage)
|
||||
, mIsAccelerated(aIsAccelerated)
|
||||
{}
|
||||
const imgIRequest* mImage;
|
||||
bool mIsAccelerated;
|
||||
};
|
||||
|
||||
class SimpleImageCacheEntry : public PLDHashEntryHdr {
|
||||
public:
|
||||
typedef imgIRequest& KeyType;
|
||||
typedef const imgIRequest* KeyTypePointer;
|
||||
typedef SimpleImageCacheKey KeyType;
|
||||
typedef const SimpleImageCacheKey* KeyTypePointer;
|
||||
|
||||
explicit SimpleImageCacheEntry(KeyTypePointer aKey)
|
||||
: mRequest(const_cast<imgIRequest*>(aKey))
|
||||
: mRequest(const_cast<imgIRequest*>(aKey->mImage))
|
||||
, mIsAccelerated(aKey->mIsAccelerated)
|
||||
{}
|
||||
SimpleImageCacheEntry(const SimpleImageCacheEntry &toCopy)
|
||||
: mRequest(toCopy.mRequest)
|
||||
, mIsAccelerated(toCopy.mIsAccelerated)
|
||||
, mSourceSurface(toCopy.mSourceSurface)
|
||||
{}
|
||||
~SimpleImageCacheEntry() {}
|
||||
|
||||
bool KeyEquals(KeyTypePointer key) const
|
||||
{
|
||||
return key == mRequest;
|
||||
return key->mImage == mRequest && key->mIsAccelerated == mIsAccelerated;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType key) { return &key; }
|
||||
static KeyTypePointer KeyToPointer(KeyType& key) { return &key; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer key)
|
||||
{
|
||||
return NS_PTR_TO_UINT32(key) >> 2;
|
||||
return HashGeneric(key->mImage, key->mIsAccelerated);
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
nsCOMPtr<imgIRequest> mRequest;
|
||||
bool mIsAccelerated;
|
||||
RefPtr<SourceSurface> mSourceSurface;
|
||||
};
|
||||
|
||||
@ -130,8 +154,8 @@ public:
|
||||
mTotal -= aObject->SizeInBytes();
|
||||
RemoveObject(aObject);
|
||||
// Deleting the entry will delete aObject since the entry owns aObject
|
||||
mSimpleCache.RemoveEntry(*aObject->mRequest);
|
||||
mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas));
|
||||
mSimpleCache.RemoveEntry(SimpleImageCacheKey(aObject->mRequest, aObject->mIsAccelerated));
|
||||
mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas, aObject->mIsAccelerated));
|
||||
}
|
||||
|
||||
nsTHashtable<ImageCacheEntry> mCache;
|
||||
@ -237,20 +261,22 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||
HTMLCanvasElement* aCanvas,
|
||||
imgIRequest* aRequest,
|
||||
SourceSurface* aSource,
|
||||
const IntSize& aSize)
|
||||
const IntSize& aSize,
|
||||
bool aIsAccelerated)
|
||||
{
|
||||
if (!gImageCache) {
|
||||
gImageCache = new ImageCache();
|
||||
nsContentUtils::RegisterShutdownObserver(new CanvasImageCacheShutdownObserver());
|
||||
}
|
||||
|
||||
ImageCacheEntry* entry = gImageCache->mCache.PutEntry(ImageCacheKey(aImage, aCanvas));
|
||||
ImageCacheEntry* entry =
|
||||
gImageCache->mCache.PutEntry(ImageCacheKey(aImage, aCanvas, aIsAccelerated));
|
||||
if (entry) {
|
||||
if (entry->mData->mSourceSurface) {
|
||||
// We are overwriting an existing entry.
|
||||
gImageCache->mTotal -= entry->mData->SizeInBytes();
|
||||
gImageCache->RemoveObject(entry->mData);
|
||||
gImageCache->mSimpleCache.RemoveEntry(*entry->mData->mRequest);
|
||||
gImageCache->mSimpleCache.RemoveEntry(SimpleImageCacheKey(entry->mData->mRequest, entry->mData->mIsAccelerated));
|
||||
}
|
||||
gImageCache->AddObject(entry->mData);
|
||||
|
||||
@ -267,7 +293,7 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||
|
||||
if (entry->mData->mRequest) {
|
||||
SimpleImageCacheEntry* simpleentry =
|
||||
gImageCache->mSimpleCache.PutEntry(*entry->mData->mRequest);
|
||||
gImageCache->mSimpleCache.PutEntry(SimpleImageCacheKey(entry->mData->mRequest, aIsAccelerated));
|
||||
simpleentry->mSourceSurface = aSource;
|
||||
}
|
||||
}
|
||||
@ -283,12 +309,14 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||
SourceSurface*
|
||||
CanvasImageCache::Lookup(Element* aImage,
|
||||
HTMLCanvasElement* aCanvas,
|
||||
gfx::IntSize* aSize)
|
||||
gfx::IntSize* aSize,
|
||||
bool aIsAccelerated)
|
||||
{
|
||||
if (!gImageCache)
|
||||
return nullptr;
|
||||
|
||||
ImageCacheEntry* entry = gImageCache->mCache.GetEntry(ImageCacheKey(aImage, aCanvas));
|
||||
ImageCacheEntry* entry =
|
||||
gImageCache->mCache.GetEntry(ImageCacheKey(aImage, aCanvas, aIsAccelerated));
|
||||
if (!entry || !entry->mData->mILC)
|
||||
return nullptr;
|
||||
|
||||
@ -304,7 +332,8 @@ CanvasImageCache::Lookup(Element* aImage,
|
||||
}
|
||||
|
||||
SourceSurface*
|
||||
CanvasImageCache::SimpleLookup(Element* aImage)
|
||||
CanvasImageCache::SimpleLookup(Element* aImage,
|
||||
bool aIsAccelerated)
|
||||
{
|
||||
if (!gImageCache)
|
||||
return nullptr;
|
||||
@ -319,7 +348,7 @@ CanvasImageCache::SimpleLookup(Element* aImage)
|
||||
if (!request)
|
||||
return nullptr;
|
||||
|
||||
SimpleImageCacheEntry* entry = gImageCache->mSimpleCache.GetEntry(*request);
|
||||
SimpleImageCacheEntry* entry = gImageCache->mSimpleCache.GetEntry(SimpleImageCacheKey(request, aIsAccelerated));
|
||||
if (!entry)
|
||||
return nullptr;
|
||||
|
||||
|
@ -33,7 +33,8 @@ public:
|
||||
dom::HTMLCanvasElement* aCanvas,
|
||||
imgIRequest* aRequest,
|
||||
SourceSurface* aSource,
|
||||
const gfx::IntSize& aSize);
|
||||
const gfx::IntSize& aSize,
|
||||
bool aIsAccelerated);
|
||||
|
||||
/**
|
||||
* Check whether aImage has recently been drawn into aCanvas. If we return
|
||||
@ -43,14 +44,16 @@ public:
|
||||
*/
|
||||
static SourceSurface* Lookup(dom::Element* aImage,
|
||||
dom::HTMLCanvasElement* aCanvas,
|
||||
gfx::IntSize* aSize);
|
||||
gfx::IntSize* aSize,
|
||||
bool aIsAccelerated);
|
||||
|
||||
/**
|
||||
* This is the same as Lookup, except it works on any image recently drawn
|
||||
* into any canvas. Security checks need to be done again if using the
|
||||
* results from this.
|
||||
*/
|
||||
static SourceSurface* SimpleLookup(dom::Element* aImage);
|
||||
static SourceSurface* SimpleLookup(dom::Element* aImage,
|
||||
bool aIsAccelerated);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -4312,7 +4312,8 @@ CanvasRenderingContext2D::CachedSurfaceFromElement(Element* aElement)
|
||||
return res;
|
||||
}
|
||||
|
||||
res.mSourceSurface = CanvasImageCache::SimpleLookup(aElement);
|
||||
res.mSourceSurface =
|
||||
CanvasImageCache::SimpleLookup(aElement, mIsSkiaGL);
|
||||
if (!res.mSourceSurface) {
|
||||
return res;
|
||||
}
|
||||
@ -4418,7 +4419,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
||||
}
|
||||
|
||||
srcSurf =
|
||||
CanvasImageCache::Lookup(element, mCanvasElement, &imgSize);
|
||||
CanvasImageCache::Lookup(element, mCanvasElement, &imgSize, mIsSkiaGL);
|
||||
}
|
||||
|
||||
nsLayoutUtils::DirectDrawInfo drawInfo;
|
||||
@ -4566,7 +4567,7 @@ CanvasRenderingContext2D::DrawImage(const CanvasImageSource& image,
|
||||
if (res.mSourceSurface) {
|
||||
if (res.mImageRequest) {
|
||||
CanvasImageCache::NotifyDrawImage(element, mCanvasElement, res.mImageRequest,
|
||||
res.mSourceSurface, imgSize);
|
||||
res.mSourceSurface, imgSize, mIsSkiaGL);
|
||||
}
|
||||
|
||||
srcSurf = res.mSourceSurface;
|
||||
|
@ -508,6 +508,7 @@ skip-if = os == 'android'
|
||||
skip-if = os == 'mac'
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__drawingbuffer-test.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__canvas__viewport-unchanged-upon-resize.html]
|
||||
skip-if = os == 'mac'
|
||||
[webgl-conformance/_wrappers/test_conformance__context__constants.html]
|
||||
[webgl-conformance/_wrappers/test_conformance__context__context-attributes-alpha-depth-stencil-antialias.html]
|
||||
skip-if = (os == 'b2g')
|
||||
|
@ -108,6 +108,9 @@ fail-if = (os == 'linux')
|
||||
[_wrappers/test_conformance__canvas__drawingbuffer-static-canvas-test.html]
|
||||
# Intermittent crash on OSX.
|
||||
skip-if = os == 'mac'
|
||||
[_wrappers/test_conformance__canvas__viewport-unchanged-upon-resize.html]
|
||||
# New OSX r7 machines and 10.10.5 is causing perma failure (bug 1216549)
|
||||
skip-if = os == 'mac'
|
||||
|
||||
########################################################################
|
||||
# Win
|
||||
|
@ -2557,6 +2557,8 @@ EventStateManager::DoScrollText(nsIScrollableFrame* aScrollableFrame,
|
||||
case WidgetWheelEvent::SCROLL_DEFAULT:
|
||||
if (isDeltaModePixel) {
|
||||
mode = nsIScrollableFrame::NORMAL;
|
||||
} else if (aEvent->mFlags.mHandledByAPZ) {
|
||||
mode = nsIScrollableFrame::SMOOTH_MSD;
|
||||
} else {
|
||||
mode = nsIScrollableFrame::SMOOTH;
|
||||
}
|
||||
@ -3119,6 +3121,14 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
||||
if (pluginFrame) {
|
||||
MOZ_ASSERT(pluginFrame->WantsToHandleWheelEventAsDefaultAction());
|
||||
action = WheelPrefs::ACTION_SEND_TO_PLUGIN;
|
||||
} else if (nsLayoutUtils::IsScrollFrameWithSnapping(frameToScroll)) {
|
||||
// If the target has scroll-snapping points then we want to handle
|
||||
// the wheel event on the main thread even if we have APZ enabled. Do
|
||||
// so and let the APZ know that it should ignore this event.
|
||||
if (wheelEvent->mFlags.mHandledByAPZ) {
|
||||
wheelEvent->mFlags.mDefaultPrevented = true;
|
||||
}
|
||||
action = WheelPrefs::GetInstance()->ComputeActionFor(wheelEvent);
|
||||
} else if (wheelEvent->mFlags.mHandledByAPZ) {
|
||||
action = WheelPrefs::ACTION_NONE;
|
||||
} else {
|
||||
|
@ -44,22 +44,6 @@ function testAddContact(aIcc, aType, aMozContact, aPin2) {
|
||||
// We only support SIM in emulator, so we don't have anr and email field.
|
||||
ok(aResult.tel.length == 1);
|
||||
ok(!aResult.email);
|
||||
|
||||
// Get ICC contact for checking new contact
|
||||
return aIcc.readContacts(aType)
|
||||
.then((aResult) => {
|
||||
let contact = aResult[aResult.length - 1];
|
||||
is(contact.name[0], aMozContact.name[0]);
|
||||
// Maximum digits of the Dialling Number is 20, and maximum digits of Extension is 20.
|
||||
is(contact.tel[0].value, aMozContact.tel[0].value.substring(0, 40));
|
||||
is(contact.id.substring(0, aIcc.iccInfo.iccid.length), aIcc.iccInfo.iccid);
|
||||
|
||||
return contact.id;
|
||||
})
|
||||
.then((aContactId) => {
|
||||
// Clean up contact
|
||||
return removeContact(aIcc, aContactId, aType, aPin2);
|
||||
});
|
||||
}, (aError) => {
|
||||
if (aType === "fdn" && aPin2 === undefined) {
|
||||
ok(aError.name === "SimPin2",
|
||||
@ -67,31 +51,61 @@ function testAddContact(aIcc, aType, aMozContact, aPin2) {
|
||||
} else {
|
||||
ok(false, "Cannot add " + aType + " contact: " + aError.name);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function removeContact(aIcc, aContactId, aType, aPin2) {
|
||||
log("removeContact: contactId=" + aContactId +
|
||||
", type=" + aType + ", pin2=" + aPin2);
|
||||
function removeContacts(aIcc, aContacts, aType, aPin2) {
|
||||
log("removeContacts: type=" + aType + ", pin2=" + aPin2);
|
||||
let promise = Promise.resolve();
|
||||
|
||||
let contact = new mozContact({});
|
||||
contact.id = aContactId;
|
||||
// Clean up contacts
|
||||
for (let i = 0; i < aContacts.length ; i++) {
|
||||
let contact = new mozContact({});
|
||||
contact.id = aContacts[i].id;
|
||||
promise = promise.then(() => aIcc.updateContact(aType, contact, aPin2));
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
return aIcc.updateContact(aType, contact, aPin2);
|
||||
function testAddContacts(aIcc, aType, aPin2) {
|
||||
let promise = Promise.resolve();
|
||||
|
||||
for (let i = 0; i < TEST_ADD_DATA.length; i++) {
|
||||
let test_data = TEST_ADD_DATA[i];
|
||||
|
||||
promise = promise.then(() => testAddContact(aIcc, aType, test_data, aPin2));
|
||||
}
|
||||
|
||||
// Get ICC contact for checking new contacts
|
||||
promise = promise.then(() => aIcc.readContacts(aType))
|
||||
.then((aResult) => {
|
||||
aResult = aResult.slice(aResult.length - TEST_ADD_DATA.length);
|
||||
|
||||
for (let i = 0; i < aResult.length ; i++) {
|
||||
let contact = aResult[i];
|
||||
let expectedResult = TEST_ADD_DATA[i];
|
||||
|
||||
is(contact.name[0], expectedResult.name[0]);
|
||||
// Maximum digits of the Dialling Number is 20, and maximum digits of Extension is 20.
|
||||
is(contact.tel[0].value, expectedResult.tel[0].value.substring(0, 40));
|
||||
is(contact.id.substring(0, aIcc.iccInfo.iccid.length), aIcc.iccInfo.iccid);
|
||||
}
|
||||
return removeContacts(aIcc, aResult, aType, aPin2);
|
||||
});
|
||||
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Start tests
|
||||
startTestCommon(function() {
|
||||
let icc = getMozIcc();
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < TEST_ADD_DATA.length; i++) {
|
||||
let test_data = TEST_ADD_DATA[i];
|
||||
|
||||
return Promise.resolve()
|
||||
// Test add adn contacts
|
||||
promise = promise.then(() => testAddContact(icc, "adn", test_data))
|
||||
// Test add fdn contacts
|
||||
.then(() => testAddContact(icc, "fdn", test_data, "0000"))
|
||||
// Test add fdn contacts without passing pin2
|
||||
.then(() => testAddContact(icc, "fdn", test_data));
|
||||
}
|
||||
return promise;
|
||||
.then(() => testAddContacts(icc, "adn"))
|
||||
// Test add fdn contacts
|
||||
.then(() => testAddContacts(icc, "fdn", "0000"))
|
||||
// Test one fdn contact without passing pin2
|
||||
.then(() => testAddContact(icc, "fdn", TEST_ADD_DATA[0]));
|
||||
});
|
||||
|
@ -52,36 +52,65 @@ function testUpdateContact(aIcc, aType, aContactId, aMozContact, aExpect, aPin2)
|
||||
|
||||
return aIcc.updateContact(aType, contact, aPin2)
|
||||
.then((aResult) => {
|
||||
// Get ICC contact for checking expect contact
|
||||
return aIcc.readContacts(aType)
|
||||
.then((aResult) => {
|
||||
let contact = aResult[aContactId - 1];
|
||||
|
||||
is(contact.name[0], aMozContact.name[0]);
|
||||
|
||||
if (aExpect.number == null) {
|
||||
is(contact.tel, null);
|
||||
} else {
|
||||
is(contact.tel[0].value, aExpect.number);
|
||||
}
|
||||
|
||||
is(contact.id, aIcc.iccInfo.iccid + aContactId);
|
||||
});
|
||||
}, (aError) => {
|
||||
if (aType === "fdn" && aPin2 === undefined) {
|
||||
ok(aError.name === "SimPin2",
|
||||
"expected error when pin2 is not provided");
|
||||
} else {
|
||||
ok(false, "Cannot update " + aType + " contact: " + aError.name);
|
||||
}
|
||||
});
|
||||
if (aExpect.number === null) {
|
||||
is(aResult.tel, null);
|
||||
} else {
|
||||
is(aResult.tel[0].value, aExpect.number);
|
||||
ok(aResult.tel.length == 1);
|
||||
}
|
||||
// We only support SIM in emulator, so we don't have anr and email field.
|
||||
ok(!aResult.email);
|
||||
is(contact.id, aIcc.iccInfo.iccid + aContactId);
|
||||
}, (aError) => {
|
||||
if (aType === "fdn" && aPin2 === undefined) {
|
||||
ok(aError.name === "SimPin2",
|
||||
"expected error when pin2 is not provided");
|
||||
} else {
|
||||
ok(false, "Cannot update " + aType + " contact: " + aError.name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function revertContact(aIcc, aContact, aType, aPin2) {
|
||||
log("revertContact: contact:" + JSON.stringify(aContact) +
|
||||
", type=" + aType + ", pin2=" + aPin2);
|
||||
function revertContacts(aIcc, aContacts, aType, aPin2) {
|
||||
log("revertContacts type=" + aType + ", pin2=" + aPin2);
|
||||
let promise = Promise.resolve();
|
||||
|
||||
return aIcc.updateContact(aType, aContact, aPin2);
|
||||
for (let i = 0; i < aContacts.length; i++) {
|
||||
let aContact = aContacts[i];
|
||||
promise = promise.then(() => aIcc.updateContact(aType, aContact, aPin2));
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
|
||||
function testUpdateContacts(aIcc, aType, aCacheContacts, aPin2) {
|
||||
let promise = Promise.resolve();
|
||||
|
||||
for (let i = 0; i < TEST_UPDATE_DATA.length; i++) {
|
||||
let test_data = TEST_UPDATE_DATA[i];
|
||||
promise = promise.then(() => testUpdateContact(aIcc, aType, test_data.id,
|
||||
test_data.data, test_data.expect,
|
||||
aPin2));
|
||||
}
|
||||
|
||||
// Get ICC contact for checking expect contacts
|
||||
promise = promise.then(() => aIcc.readContacts(aType))
|
||||
.then((aResult) => {
|
||||
for (let i = 0; i < TEST_UPDATE_DATA.length; i++) {
|
||||
let expectedResult = TEST_UPDATE_DATA[i];
|
||||
let contact = aResult[expectedResult.id - 1];
|
||||
|
||||
is(contact.name[0], expectedResult.data.name[0]);
|
||||
is(contact.id, aIcc.iccInfo.iccid + expectedResult.id);
|
||||
if (expectedResult.expect.number === null) {
|
||||
is(contact.tel, null);
|
||||
} else {
|
||||
is(contact.tel[0].value, expectedResult.expect.number);
|
||||
}
|
||||
}
|
||||
return revertContacts(aIcc, aCacheContacts, aType, aPin2);
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Start tests
|
||||
@ -98,25 +127,12 @@ startTestCommon(function() {
|
||||
.then((aResult) => {
|
||||
fdnContacts = aResult;
|
||||
})
|
||||
.then(() => {
|
||||
let promise = Promise.resolve();
|
||||
for (let i = 0; i < TEST_UPDATE_DATA.length; i++) {
|
||||
let test_data = TEST_UPDATE_DATA[i];
|
||||
let adnContact = adnContacts[test_data.id - 1];
|
||||
let fdnContact = fdnContacts[test_data.id - 1];
|
||||
|
||||
// Test update adn contacts
|
||||
promise = promise.then(() => testUpdateContact(icc, "adn", test_data.id,
|
||||
test_data.data, test_data.expect))
|
||||
// Test update fdn contacts
|
||||
.then(() => testUpdateContact(icc, "fdn", test_data.id, test_data.data,
|
||||
test_data.expect))
|
||||
// Test update fdn contacts without passing pin2
|
||||
.then(() => testUpdateContact(icc, "fdn", test_data.id, test_data.data,
|
||||
test_data.expect, "0000"))
|
||||
.then(() => revertContact(icc, adnContact, "adn"))
|
||||
.then(() => revertContact(icc, fdnContact, "fdn", "0000"));
|
||||
}
|
||||
return promise;
|
||||
});
|
||||
// Test update adn contacts
|
||||
.then(() => testUpdateContacts(icc, "adn", adnContacts))
|
||||
// Test update fdn contacts
|
||||
.then(() => testUpdateContacts(icc, "fdn", fdnContacts, "0000"))
|
||||
// Test one fdn contact without passing pin2
|
||||
.then(() => testUpdateContact(icc, "fdn", TEST_UPDATE_DATA[0].id,
|
||||
TEST_UPDATE_DATA[0].data,
|
||||
TEST_UPDATE_DATA[0].expect));
|
||||
});
|
||||
|
@ -459,25 +459,22 @@ HangMonitorParent::HangMonitorParent(ProcessHangMonitor* aMonitor)
|
||||
mReportHangs = mozilla::Preferences::GetBool("dom.ipc.reportProcessHangs", false);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteMinidump(const uint32_t& aPluginId, nsString aCrashId, void* aUserData)
|
||||
{
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
if (!aCrashId.IsEmpty()) {
|
||||
CrashReporter::DeleteMinidumpFilesForID(aCrashId);
|
||||
}
|
||||
#endif
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
HangMonitorParent::~HangMonitorParent()
|
||||
{
|
||||
// For some reason IPDL doesn't automatically delete the channel for a
|
||||
// bridged protocol (bug 1090570). So we have to do it ourselves.
|
||||
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, new DeleteTask<Transport>(GetTransport()));
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER
|
||||
MutexAutoLock lock(mBrowserCrashDumpHashLock);
|
||||
mBrowserCrashDumpIds.EnumerateRead(DeleteMinidump, nullptr);
|
||||
|
||||
for (auto iter = mBrowserCrashDumpIds.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsString crashId = iter.UserData();
|
||||
if (!crashId.IsEmpty()) {
|
||||
CrashReporter::DeleteMinidumpFilesForID(crashId);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -599,37 +599,19 @@ ProcessPriorityManagerImpl::ObserveContentParentDestroyed(nsISupports* aSubject)
|
||||
}
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
FreezeParticularProcessPriorityManagers(
|
||||
const uint64_t& aKey,
|
||||
RefPtr<ParticularProcessPriorityManager> aValue,
|
||||
void* aUserData)
|
||||
{
|
||||
aValue->Freeze();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
UnfreezeParticularProcessPriorityManagers(
|
||||
const uint64_t& aKey,
|
||||
RefPtr<ParticularProcessPriorityManager> aValue,
|
||||
void* aUserData)
|
||||
{
|
||||
aValue->Unfreeze();
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
ProcessPriorityManagerImpl::ObserveScreenStateChanged(const char16_t* aData)
|
||||
{
|
||||
if (NS_LITERAL_STRING("on").Equals(aData)) {
|
||||
sFrozen = false;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&UnfreezeParticularProcessPriorityManagers, nullptr);
|
||||
for (auto iter = mParticularManagers.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.UserData()->Unfreeze();
|
||||
}
|
||||
} else {
|
||||
sFrozen = true;
|
||||
mParticularManagers.EnumerateRead(
|
||||
&FreezeParticularProcessPriorityManagers, nullptr);
|
||||
for (auto iter = mParticularManagers.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.UserData()->Freeze();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,14 +198,14 @@ VideoData::ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther,
|
||||
}
|
||||
|
||||
/* static */
|
||||
void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
const VideoInfo& aInfo,
|
||||
const YCbCrBuffer &aBuffer,
|
||||
const IntRect& aPicture,
|
||||
bool aCopyData)
|
||||
{
|
||||
if (!aVideoImage) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
|
||||
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
|
||||
@ -229,9 +229,9 @@ void VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
|
||||
aVideoImage->SetDelayedConversion(true);
|
||||
if (aCopyData) {
|
||||
aVideoImage->SetData(data);
|
||||
return aVideoImage->SetData(data);
|
||||
} else {
|
||||
aVideoImage->SetDataNoCopy(data);
|
||||
return aVideoImage->SetDataNoCopy(data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,12 +330,10 @@ VideoData::Create(const VideoInfo& aInfo,
|
||||
"Wrong format?");
|
||||
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||
|
||||
if (!aImage) {
|
||||
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
true /* aCopyData */);
|
||||
} else {
|
||||
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
false /* aCopyData */);
|
||||
bool shouldCopyData = (aImage == nullptr);
|
||||
if (!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
shouldCopyData)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -346,8 +344,10 @@ VideoData::Create(const VideoInfo& aInfo,
|
||||
return nullptr;
|
||||
}
|
||||
videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
|
||||
VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
true /* aCopyData */);
|
||||
if(!VideoData::SetVideoDataToImage(videoImage, aInfo, aBuffer, aPicture,
|
||||
true /* aCopyData */)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return v.forget();
|
||||
@ -473,7 +473,9 @@ VideoData::Create(const VideoInfo& aInfo,
|
||||
data.mPicSize = aPicture.Size();
|
||||
data.mGraphicBuffer = aBuffer;
|
||||
|
||||
videoImage->SetData(data);
|
||||
if (!videoImage->SetData(data)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return v.forget();
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ public:
|
||||
|
||||
// Initialize PlanarYCbCrImage. Only When aCopyData is true,
|
||||
// video data is copied to PlanarYCbCrImage.
|
||||
static void SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
static bool SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
|
||||
const VideoInfo& aInfo,
|
||||
const YCbCrBuffer &aBuffer,
|
||||
const IntRect& aPicture,
|
||||
|
@ -745,6 +745,9 @@ MediaDecoder::NotifyDataEnded(nsresult aStatus)
|
||||
{
|
||||
RefPtr<MediaDecoder> self = this;
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction([=] () {
|
||||
if (self->mShuttingDown) {
|
||||
return;
|
||||
}
|
||||
self->NotifyDownloadEnded(aStatus);
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
HTMLMediaElement* element = self->mOwner->GetMediaElement();
|
||||
|
@ -80,7 +80,10 @@ VideoFrame::CreateBlackImage(const gfx::IntSize& aSize)
|
||||
data.mStereoMode = StereoMode::MONO;
|
||||
|
||||
// SetData copies data, so we can free data.
|
||||
planar->SetData(data);
|
||||
if (!planar->SetData(data)) {
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return image.forget();
|
||||
}
|
||||
|
@ -58,6 +58,12 @@ var gVideoTests = [
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
|
||||
// Temp hack for trackIDs and captureStream() -- bug 1215769
|
||||
var gLongerTests = [
|
||||
{ name:"seek.webm", type:"video/webm", width:320, height:240, duration:3.966 },
|
||||
{ name:"gizmo.mp4", type:"video/mp4", width:560, height:320, duration:5.56 },
|
||||
];
|
||||
|
||||
// Used by test_progress to ensure we get the correct progress information
|
||||
// during resource download.
|
||||
var gProgressTests = [
|
||||
|
@ -14,7 +14,7 @@ createHTML({
|
||||
title: "Captured video-only over peer connection",
|
||||
visible: true
|
||||
}).then(() => new Promise(resolve => {
|
||||
manager.runTests(getPlayableVideos(gSmallTests), startTest);
|
||||
manager.runTests(getPlayableVideos(gLongerTests), startTest);
|
||||
manager.onFinished = () => {
|
||||
// Tear down before SimpleTest.finish.
|
||||
if ("nsINetworkInterfaceListService" in SpecialPowers.Ci) {
|
||||
|
@ -250,10 +250,16 @@ MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
|
||||
0, 0);
|
||||
#endif
|
||||
|
||||
ycbcr_image->SetData(data);
|
||||
bool setData = ycbcr_image->SetData(data);
|
||||
MOZ_ASSERT(setData);
|
||||
|
||||
// SetData copies data, so we can free the frame
|
||||
ReleaseFrame(data);
|
||||
|
||||
if (!setData) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
|
||||
// implicitly releases last image
|
||||
|
@ -315,7 +315,10 @@ MediaEngineRemoteVideoSource::DeliverFrame(unsigned char* buffer,
|
||||
data.mPicSize = IntSize(mWidth, mHeight);
|
||||
data.mStereoMode = StereoMode::MONO;
|
||||
|
||||
videoImage->SetData(data);
|
||||
if (!videoImage->SetData(data)) {
|
||||
MOZ_ASSERT(false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static uint32_t frame_num = 0;
|
||||
|
@ -1444,31 +1444,6 @@ PluginInstanceParent::AllocPPluginScriptableObjectParent()
|
||||
return new PluginScriptableObjectParent(Proxy);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
namespace {
|
||||
|
||||
struct ActorSearchData
|
||||
{
|
||||
PluginScriptableObjectParent* actor;
|
||||
bool found;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
ActorSearch(NPObject* aKey,
|
||||
PluginScriptableObjectParent* aData,
|
||||
void* aUserData)
|
||||
{
|
||||
ActorSearchData* asd = reinterpret_cast<ActorSearchData*>(aUserData);
|
||||
if (asd->actor == aData) {
|
||||
asd->found = true;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif // DEBUG
|
||||
|
||||
bool
|
||||
PluginInstanceParent::DeallocPPluginScriptableObjectParent(
|
||||
PPluginScriptableObjectParent* aObject)
|
||||
@ -1484,9 +1459,10 @@ PluginInstanceParent::DeallocPPluginScriptableObjectParent(
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else {
|
||||
ActorSearchData asd = { actor, false };
|
||||
mScriptableObjects.EnumerateRead(ActorSearch, &asd);
|
||||
NS_ASSERTION(!asd.found, "Actor in the hash with a null NPObject!");
|
||||
for (auto iter = mScriptableObjects.Iter(); !iter.Done(); iter.Next()) {
|
||||
NS_ASSERTION(actor != iter.UserData(),
|
||||
"Actor in the hash with a null NPObject!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -22,16 +22,17 @@ interface nsITCPDeviceInfo: nsISupports
|
||||
readonly attribute uint16_t port;
|
||||
};
|
||||
|
||||
[scriptable, uuid(fbb890a9-9e95-47d1-a425-86fd95881d81)]
|
||||
[scriptable, uuid(09bddfaf-fcc2-4dc9-b33e-a509a1c2fb6d)]
|
||||
interface nsITCPPresentationServerListener: nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback while the server socket stops listening.
|
||||
* @param aReason
|
||||
* The reason of the socket close. NS_OK for manually |close|.
|
||||
* <other-error> on failure.
|
||||
* Callback while the server socket changes port.
|
||||
* This event won't be cached so you should get current port after setting
|
||||
* this listener to make sure the value is updated.
|
||||
* @param aPort
|
||||
* The port of the server socket.
|
||||
*/
|
||||
void onClose(in nsresult aReason);
|
||||
void onPortChange(in uint16_t aPort);
|
||||
|
||||
/**
|
||||
* Callback while the remote host is requesting to start a presentation session.
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
#include "nsIPropertyBag2.h"
|
||||
@ -25,16 +26,12 @@
|
||||
|
||||
#define SERVICE_TYPE "_mozilla_papi._tcp."
|
||||
|
||||
inline static PRLogModuleInfo*
|
||||
GetProviderLog()
|
||||
{
|
||||
static PRLogModuleInfo* log = PR_NewLogModule("MulticastDNSDeviceProvider");
|
||||
return log;
|
||||
}
|
||||
static mozilla::LazyLogModule sMulticastDNSProviderLogModule("MulticastDNSDeviceProvider");
|
||||
|
||||
#undef LOG_I
|
||||
#define LOG_I(...) MOZ_LOG(GetProviderLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#define LOG_I(...) MOZ_LOG(sMulticastDNSProviderLogModule, mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
#undef LOG_E
|
||||
#define LOG_E(...) MOZ_LOG(GetProviderLog(), mozilla::LogLevel::Error, (__VA_ARGS__))
|
||||
#define LOG_E(...) MOZ_LOG(sMulticastDNSProviderLogModule, mozilla::LogLevel::Error, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -261,20 +258,35 @@ MulticastDNSDeviceProvider::RegisterService()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mRegisterRequest);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->SetListener(mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->StartService(0)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint16_t servicePort;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&servicePort)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* If |servicePort| is non-zero, it means PresentationServer is running.
|
||||
* Otherwise, we should make it start serving.
|
||||
*/
|
||||
if (!servicePort) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->SetListener(mWrappedListener)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->StartService(0)))) {
|
||||
return rv;
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mPresentationServer->GetPort(&servicePort)))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel on going service registration.
|
||||
if (mRegisterRequest) {
|
||||
mRegisterRequest->Cancel(NS_OK);
|
||||
mRegisterRequest = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the presentation control channel server as an mDNS service.
|
||||
*/
|
||||
@ -755,12 +767,9 @@ MulticastDNSDeviceProvider::OnRegistrationFailed(nsIDNSServiceInfo* aServiceInfo
|
||||
|
||||
mRegisterRequest = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (aErrorCode == nsIDNSRegistrationListener::ERROR_SERVICE_NOT_RUNNING) {
|
||||
if (NS_WARN_IF(NS_FAILED(rv = RegisterService()))) {
|
||||
return rv;
|
||||
}
|
||||
return NS_DispatchToMainThread(
|
||||
NS_NewRunnableMethod(this, &MulticastDNSDeviceProvider::RegisterService));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -855,17 +864,13 @@ MulticastDNSDeviceProvider::OnResolveFailed(nsIDNSServiceInfo* aServiceInfo,
|
||||
|
||||
// nsITCPPresentationServerListener
|
||||
NS_IMETHODIMP
|
||||
MulticastDNSDeviceProvider::OnClose(nsresult aReason)
|
||||
MulticastDNSDeviceProvider::OnPortChange(uint16_t aPort)
|
||||
{
|
||||
LOG_I("OnClose: %x", aReason);
|
||||
LOG_I("OnPortChange: %d", aPort);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
UnregisterService(aReason);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mDiscoverable && NS_WARN_IF(NS_FAILED(rv = RegisterService()))) {
|
||||
return rv;
|
||||
if (mDiscoverable) {
|
||||
RegisterService();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -40,16 +40,11 @@ TCPPresentationServer.prototype = {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (typeof aPort === "undefined") {
|
||||
DEBUG && log("TCPPresentationServer - aPort should not be undefined");
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 0 or undefined indicates opt-out parameter, and a port will be selected
|
||||
* automatically.
|
||||
*/
|
||||
let serverSocketPort = (aPort !== 0) ? aPort : -1;
|
||||
let serverSocketPort = (typeof aPort !== "undefined" && aPort !== 0) ? aPort : -1;
|
||||
|
||||
this._serverSocket = Cc["@mozilla.org/network/server-socket;1"]
|
||||
.createInstance(Ci.nsIServerSocket);
|
||||
@ -70,7 +65,12 @@ TCPPresentationServer.prototype = {
|
||||
|
||||
this._port = this._serverSocket.port;
|
||||
|
||||
DEBUG && log("TCPPresentationServer - service start on port: " + aPort);
|
||||
DEBUG && log("TCPPresentationServer - service start on port: " + this._port);
|
||||
|
||||
// Monitor network interface change to restart server socket.
|
||||
// Only B2G has nsINetworkManager
|
||||
Services.obs.addObserver(this, "network-active-changed", false);
|
||||
Services.obs.addObserver(this, "network:offline-status-changed", false);
|
||||
},
|
||||
|
||||
get id() {
|
||||
@ -178,31 +178,74 @@ TCPPresentationServer.prototype = {
|
||||
// nsIServerSocketListener (Triggered by nsIServerSocket.init)
|
||||
onStopListening: function(aServerSocket, aStatus) {
|
||||
DEBUG && log("TCPPresentationServer - onStopListening: " + aStatus);
|
||||
|
||||
if (this._serverSocket) {
|
||||
DEBUG && log("TCPPresentationServer - should be non-manually closed");
|
||||
this.close();
|
||||
} else if (aStatus === Cr.NS_BINDING_ABORTED) {
|
||||
DEBUG && log("TCPPresentationServer - should be manually closed");
|
||||
aStatus = Cr.NS_OK;
|
||||
}
|
||||
|
||||
this._listener && this._listener.onClose(aStatus);
|
||||
},
|
||||
|
||||
close: function() {
|
||||
DEBUG && log("TCPPresentationServer - close");
|
||||
if (this._serverSocket) {
|
||||
if (this._isServiceInit()) {
|
||||
DEBUG && log("TCPPresentationServer - close server socket");
|
||||
this._serverSocket.close();
|
||||
this._serverSocket = null;
|
||||
|
||||
Services.obs.removeObserver(this, "network-active-changed");
|
||||
Services.obs.removeObserver(this, "network:offline-status-changed");
|
||||
}
|
||||
this._port = 0;
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
DEBUG && log("TCPPresentationServer - observe: " + aTopic);
|
||||
switch (aTopic) {
|
||||
case "network-active-changed": {
|
||||
if (!aSubject) {
|
||||
DEBUG && log("No active network");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart service only when original status is online because other
|
||||
* cases will be handled by "network:offline-status-changed".
|
||||
*/
|
||||
if (!Services.io.offline) {
|
||||
this._restartService();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "network:offline-status-changed": {
|
||||
if (aData == "offline") {
|
||||
DEBUG && log("network offline");
|
||||
return;
|
||||
}
|
||||
this._restartService();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_restartService: function() {
|
||||
DEBUG && log("TCPPresentationServer - restart service");
|
||||
|
||||
// restart server socket
|
||||
if (this._isServiceInit()) {
|
||||
let port = this._port;
|
||||
this.close();
|
||||
|
||||
try {
|
||||
this.startService();
|
||||
if (this._listener && this._port !== port) {
|
||||
this._listener.onPortChange(this._port);
|
||||
}
|
||||
} catch (e) {
|
||||
DEBUG && log("TCPPresentationServer - restart service fail: " + e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
classID: Components.ID("{f4079b8b-ede5-4b90-a112-5b415a931deb}"),
|
||||
QueryInterface : XPCOMUtils.generateQI([Ci.nsIServerSocketListener,
|
||||
Ci.nsITCPPresentationServer]),
|
||||
Ci.nsITCPPresentationServer,
|
||||
Ci.nsIObserver]),
|
||||
};
|
||||
|
||||
function ChannelDescription(aInit) {
|
||||
|
@ -1002,7 +1002,8 @@ function serverClosed() {
|
||||
Assert.equal(listener.devices.length, 1);
|
||||
|
||||
let serverListener = provider.QueryInterface(Ci.nsITCPPresentationServerListener);
|
||||
serverListener.onClose(Cr.NS_ERROR_UNEXPECTED);
|
||||
let randomPort = 9527;
|
||||
serverListener.onPortChange(randomPort);
|
||||
|
||||
Assert.equal(mockObj.serviceRegistered, 2);
|
||||
Assert.equal(mockObj.serviceUnregistered, 1);
|
||||
|
@ -183,17 +183,17 @@ function testPresentationServer() {
|
||||
}
|
||||
|
||||
function setOffline() {
|
||||
let expectedReason;
|
||||
tps.listener = {
|
||||
onClose: function(aReason) {
|
||||
Assert.equal(aReason, Cr.NS_ERROR_ABORT, 'TCPPresentationServer close as expected');
|
||||
Services.io.offline = false;
|
||||
onPortChange: function(aPort) {
|
||||
Assert.notEqual(aPort, 0, 'TCPPresentationServer port changed and the port should be valid');
|
||||
tps.close();
|
||||
run_next_test();
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
// Let the server socket be closed non-manually
|
||||
// Let the server socket restart automatically.
|
||||
Services.io.offline = true;
|
||||
Services.io.offline = false;
|
||||
}
|
||||
|
||||
function oneMoreLoop() {
|
||||
@ -210,12 +210,13 @@ function oneMoreLoop() {
|
||||
function shutdown()
|
||||
{
|
||||
tps.listener = {
|
||||
onClose: function(aReason) {
|
||||
Assert.equal(aReason, Cr.NS_OK, 'TCPPresentationServer close success');
|
||||
run_next_test();
|
||||
onPortChange: function(aPort) {
|
||||
Assert.ok(false, 'TCPPresentationServer port changed');
|
||||
},
|
||||
}
|
||||
};
|
||||
tps.close();
|
||||
Assert.equal(tps.port, 0, "TCPPresentationServer closed");
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
// Test manually close control channel with NS_ERROR_FAILURE
|
||||
|
@ -771,14 +771,21 @@ var Modem = Modems[0];
|
||||
.then(() => {
|
||||
ok(outCall instanceof TelephonyCall, "check instance");
|
||||
is(outCall.id.number, number);
|
||||
is(outCall.state, "dialing");
|
||||
is(outCall.serviceId, serviceId);
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// A CDMA call goes to connected state directly when the operator find
|
||||
// its callee, which makes the "connected" state in CDMA calls behaves
|
||||
// like the "alerting" state in GSM calls.
|
||||
let state = Modems[serviceId].isGSM() ? "alerting" : "connected";
|
||||
|
||||
// Sometimes the dialing state is missing, see Bug 1220548.
|
||||
if (outCall.state === state) {
|
||||
log("got " + state + " state, dialing is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
is(outCall.state, "dialing", "check state");
|
||||
|
||||
return waitForNamedStateEvent(outCall, state);
|
||||
});
|
||||
}
|
||||
@ -801,13 +808,20 @@ var Modem = Modems[0];
|
||||
ok(outCall instanceof TelephonyCall, "check instance");
|
||||
ok(outCall);
|
||||
is(outCall.id.number, number);
|
||||
is(outCall.state, "dialing");
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// Similar to function |dial|, a CDMA call directly goes to connected
|
||||
// state when the operator find its callee.
|
||||
let state = Modems[outCall.serviceId].isGSM() ? "alerting"
|
||||
: "connected";
|
||||
|
||||
// Sometimes the dialing state is missing, see Bug 1220548.
|
||||
if (outCall.state === state) {
|
||||
log("got " + state + " state, dialing is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
is(outCall.state, "dialing", "check state");
|
||||
|
||||
return waitForNamedStateEvent(outCall, state);
|
||||
})
|
||||
.then(() => {
|
||||
@ -835,6 +849,13 @@ var Modem = Modems[0];
|
||||
|
||||
ok(call instanceof TelephonyCall, "check instance");
|
||||
is(call.id.number, number, "check number");
|
||||
|
||||
// Sometimes the dialing state is missing, see Bug 1220548.
|
||||
if (call.state === "alerting") {
|
||||
log("got alerting state, dialing is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
is(call.state, "dialing", "check call state");
|
||||
|
||||
return waitForNamedStateEvent(call, "alerting");
|
||||
|
@ -113,10 +113,7 @@ AsyncLog(nsIInterceptedChannel *aInterceptedChannel,
|
||||
const nsACString& aMessageName, const nsTArray<nsString>& aParams)
|
||||
{
|
||||
MOZ_ASSERT(aInterceptedChannel);
|
||||
// Since the intercepted channel is kept alive and paused while handling
|
||||
// the FetchEvent, we are guaranteed the reporter is stable on the worker
|
||||
// thread.
|
||||
nsIConsoleReportCollector* reporter =
|
||||
nsCOMPtr<nsIConsoleReportCollector> reporter =
|
||||
aInterceptedChannel->GetConsoleReportCollector();
|
||||
if (reporter) {
|
||||
reporter->AddConsoleReport(nsIScriptError::errorFlag,
|
||||
|
@ -27,14 +27,12 @@ public:
|
||||
protected:
|
||||
virtual ~nsGroupsEnumerator();
|
||||
|
||||
static PLDHashOperator HashEnum(const nsACString& aKey,
|
||||
nsTArray<nsCString>* aData, void* aClosure);
|
||||
nsresult Initialize();
|
||||
|
||||
protected:
|
||||
nsControllerCommandGroup::GroupsHashtable& mHashTable;
|
||||
int32_t mIndex;
|
||||
char** mGroupNames; // array of pointers to char16_t* in the hash table
|
||||
const char** mGroupNames; // array of pointers to char16_t* in the hash table
|
||||
bool mInitted;
|
||||
};
|
||||
|
||||
@ -92,7 +90,7 @@ nsGroupsEnumerator::GetNext(nsISupports** aResult)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
char* thisGroupName = mGroupNames[mIndex];
|
||||
const char* thisGroupName = mGroupNames[mIndex];
|
||||
|
||||
nsCOMPtr<nsISupportsCString> supportsString =
|
||||
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID, &rv);
|
||||
@ -104,18 +102,6 @@ nsGroupsEnumerator::GetNext(nsISupports** aResult)
|
||||
return CallQueryInterface(supportsString, aResult);
|
||||
}
|
||||
|
||||
/* static */
|
||||
/* return false to stop */
|
||||
PLDHashOperator
|
||||
nsGroupsEnumerator::HashEnum(const nsACString& aKey, nsTArray<nsCString>* aData,
|
||||
void* aClosure)
|
||||
{
|
||||
nsGroupsEnumerator* groupsEnum = static_cast<nsGroupsEnumerator*>(aClosure);
|
||||
groupsEnum->mGroupNames[groupsEnum->mIndex] = (char*)aKey.Data();
|
||||
groupsEnum->mIndex++;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGroupsEnumerator::Initialize()
|
||||
{
|
||||
@ -123,13 +109,16 @@ nsGroupsEnumerator::Initialize()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mGroupNames = new char*[mHashTable.Count()];
|
||||
mGroupNames = new const char*[mHashTable.Count()];
|
||||
if (!mGroupNames) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
mIndex = 0;
|
||||
mHashTable.EnumerateRead(HashEnum, this);
|
||||
for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
mGroupNames[mIndex] = iter.Key().Data();
|
||||
mIndex++;
|
||||
}
|
||||
|
||||
mIndex = -1;
|
||||
mInitted = true;
|
||||
|
@ -34,29 +34,19 @@ nsCommandManager::~nsCommandManager()
|
||||
{
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
TraverseCommandObservers(const char* aKey,
|
||||
nsCommandManager::ObserverList* aObservers,
|
||||
void* aClosure)
|
||||
{
|
||||
nsCycleCollectionTraversalCallback* cb =
|
||||
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
|
||||
|
||||
int32_t i, numItems = aObservers->Length();
|
||||
for (i = 0; i < numItems; ++i) {
|
||||
cb->NoteXPCOMChild(aObservers->ElementAt(i));
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsCommandManager)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsCommandManager)
|
||||
tmp->mObserversTable.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsCommandManager)
|
||||
tmp->mObserversTable.EnumerateRead(TraverseCommandObservers, &cb);
|
||||
for (auto iter = tmp->mObserversTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCommandManager::ObserverList* observers = iter.UserData();
|
||||
int32_t numItems = observers->Length();
|
||||
for (int32_t i = 0; i < numItems; ++i) {
|
||||
cb.NoteXPCOMChild(observers->ElementAt(i));
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsCommandManager)
|
||||
|
@ -178,18 +178,6 @@ nsControllerCommandTable::GetCommandState(const char* aCommandName,
|
||||
aCommandRefCon);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
AddCommand(const nsACString& aKey, nsIControllerCommand* aData, void* aArg)
|
||||
{
|
||||
// aArg is a pointer to a array of strings. It gets incremented after
|
||||
// allocating each one so that it points to the next location for AddCommand
|
||||
// to assign a string to.
|
||||
char*** commands = static_cast<char***>(aArg);
|
||||
(**commands) = ToNewCString(aKey);
|
||||
(*commands)++;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsControllerCommandTable::GetSupportedCommands(uint32_t* aCount,
|
||||
char*** aCommands)
|
||||
@ -199,7 +187,10 @@ nsControllerCommandTable::GetSupportedCommands(uint32_t* aCount,
|
||||
*aCount = mCommandsTable.Count();
|
||||
*aCommands = commands;
|
||||
|
||||
mCommandsTable.EnumerateRead(AddCommand, &commands);
|
||||
for (auto iter = mCommandsTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
*commands = ToNewCString(iter.Key());
|
||||
commands++;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -103,12 +103,6 @@ struct nsWebBrowserPersist::URIData
|
||||
nsresult GetLocalURI(nsIURI *targetBaseURI, nsCString& aSpecOut);
|
||||
};
|
||||
|
||||
struct nsWebBrowserPersist::URIFixupData
|
||||
{
|
||||
RefPtr<FlatURIMap> mFlatMap;
|
||||
nsCOMPtr<nsIURI> mTargetBaseURI;
|
||||
};
|
||||
|
||||
// Information about the output stream
|
||||
struct nsWebBrowserPersist::OutputData
|
||||
{
|
||||
@ -593,13 +587,69 @@ nsWebBrowserPersist::SerializeNextFile()
|
||||
// number of times this method is called. If it becomes a
|
||||
// bottleneck, the count of not-yet-persisted URIs could be
|
||||
// maintained separately.
|
||||
mURIMap.EnumerateRead(EnumCountURIsToPersist, &urisToPersist);
|
||||
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
URIData *data = iter.UserData();
|
||||
if (data->mNeedsPersisting && !data->mSaved) {
|
||||
urisToPersist++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (urisToPersist > 0) {
|
||||
// Persist each file in the uri map. The document(s)
|
||||
// will be saved after the last one of these is saved.
|
||||
mURIMap.EnumerateRead(EnumPersistURIs, this);
|
||||
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
URIData *data = iter.UserData();
|
||||
|
||||
if (!data->mNeedsPersisting || data->mSaved) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Create a URI from the key.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), iter.Key(),
|
||||
data->mCharset.get());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Make a URI to save the data to.
|
||||
nsCOMPtr<nsIURI> fileAsURI;
|
||||
rv = data->mDataPath->Clone(getter_AddRefs(fileAsURI));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
rv = AppendPathToURI(fileAsURI, data->mFilename);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
|
||||
// The Referrer Policy doesn't matter here since the referrer is
|
||||
// nullptr.
|
||||
rv = SaveURIInternal(uri, nullptr, nullptr,
|
||||
mozilla::net::RP_Default, nullptr, nullptr,
|
||||
fileAsURI, true, mIsPrivate);
|
||||
// If SaveURIInternal fails, then it will have called EndDownload,
|
||||
// which means that |data| is no longer valid memory. We MUST bail.
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (rv == NS_OK) {
|
||||
// Store the actual object because once it's persisted this
|
||||
// will be fixed up with the right file extension.
|
||||
data->mFile = fileAsURI;
|
||||
data->mSaved = true;
|
||||
} else {
|
||||
data->mNeedsFixup = false;
|
||||
}
|
||||
|
||||
if (mSerializingOutput) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are downloads happening, wait until they're done; the
|
||||
@ -652,17 +702,18 @@ nsWebBrowserPersist::SerializeNextFile()
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// mFlatURIMap must be rebuilt each time through SerializeNextFile, as
|
||||
// mTargetBaseURI is used to create the relative URLs and will be different
|
||||
// with each serialized document.
|
||||
RefPtr<FlatURIMap> flatMap = new FlatURIMap(targetBaseSpec);
|
||||
|
||||
URIFixupData fixupData;
|
||||
fixupData.mFlatMap = flatMap;
|
||||
fixupData.mTargetBaseURI = mTargetBaseURI;
|
||||
|
||||
mURIMap.EnumerateRead(EnumCopyURIsToFlatMap, &fixupData);
|
||||
for (auto iter = mURIMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsAutoCString mapTo;
|
||||
nsresult rv = iter.UserData()->GetLocalURI(mTargetBaseURI, mapTo);
|
||||
if (NS_SUCCEEDED(rv) || !mapTo.IsVoid()) {
|
||||
flatMap->Add(iter.Key(), mapTo);
|
||||
}
|
||||
}
|
||||
mFlatURIMap = flatMap.forget();
|
||||
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
@ -1755,23 +1806,35 @@ nsWebBrowserPersist::FinishSaveDocumentInternal(nsIURI* aFile,
|
||||
void nsWebBrowserPersist::Cleanup()
|
||||
{
|
||||
mURIMap.Clear();
|
||||
mOutputMap.EnumerateRead(EnumCleanupOutputMap, this);
|
||||
for (auto iter = mOutputMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(iter.Key());
|
||||
if (channel) {
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
}
|
||||
mOutputMap.Clear();
|
||||
mUploadList.EnumerateRead(EnumCleanupUploadList, this);
|
||||
|
||||
for (auto iter = mUploadList.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(iter.Key());
|
||||
if (channel) {
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
}
|
||||
mUploadList.Clear();
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < mDocList.Length(); i++)
|
||||
{
|
||||
for (i = 0; i < mDocList.Length(); i++) {
|
||||
DocData *docData = mDocList.ElementAt(i);
|
||||
delete docData;
|
||||
}
|
||||
mDocList.Clear();
|
||||
for (i = 0; i < mCleanupList.Length(); i++)
|
||||
{
|
||||
|
||||
for (i = 0; i < mCleanupList.Length(); i++) {
|
||||
CleanupData *cleanupData = mCleanupList.ElementAt(i);
|
||||
delete cleanupData;
|
||||
}
|
||||
mCleanupList.Clear();
|
||||
|
||||
mFilenameList.Clear();
|
||||
}
|
||||
|
||||
@ -2319,85 +2382,72 @@ nsWebBrowserPersist::EndDownload(nsresult aResult)
|
||||
mEventSink = nullptr;
|
||||
}
|
||||
|
||||
struct MOZ_STACK_CLASS FixRedirectData
|
||||
{
|
||||
nsCOMPtr<nsIChannel> mNewChannel;
|
||||
nsCOMPtr<nsIURI> mOriginalURI;
|
||||
nsCOMPtr<nsISupports> mMatchingKey;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsWebBrowserPersist::FixRedirectedChannelEntry(nsIChannel *aNewChannel)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNewChannel);
|
||||
|
||||
// Iterate through existing open channels looking for one with a URI
|
||||
// matching the one specified.
|
||||
nsCOMPtr<nsIURI> originalURI;
|
||||
aNewChannel->GetOriginalURI(getter_AddRefs(originalURI));
|
||||
for (auto iter = mOutputMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsISupports* key = iter.Key();
|
||||
nsCOMPtr<nsIChannel> thisChannel = do_QueryInterface(key);
|
||||
nsCOMPtr<nsIURI> thisURI;
|
||||
|
||||
// Enumerate through existing open channels looking for one with
|
||||
// a URI matching the one specified.
|
||||
thisChannel->GetOriginalURI(getter_AddRefs(thisURI));
|
||||
|
||||
FixRedirectData data;
|
||||
data.mNewChannel = aNewChannel;
|
||||
data.mNewChannel->GetOriginalURI(getter_AddRefs(data.mOriginalURI));
|
||||
mOutputMap.EnumerateRead(EnumFixRedirect, &data);
|
||||
// Compare this channel's URI to the one passed in.
|
||||
bool matchingURI = false;
|
||||
thisURI->Equals(originalURI, &matchingURI);
|
||||
if (matchingURI) {
|
||||
// If a match is found, remove the data entry with the old channel
|
||||
// key and re-add it with the new channel key.
|
||||
nsAutoPtr<OutputData> outputData;
|
||||
mOutputMap.RemoveAndForget(key, outputData);
|
||||
NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE);
|
||||
|
||||
// If a match is found, remove the data entry with the old channel key
|
||||
// and re-add it with the new channel key.
|
||||
// Store data again with new channel unless told to ignore redirects
|
||||
if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA)) {
|
||||
nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
|
||||
mOutputMap.Put(keyPtr, outputData.forget());
|
||||
}
|
||||
|
||||
if (data.mMatchingKey)
|
||||
{
|
||||
nsAutoPtr<OutputData> outputData;
|
||||
mOutputMap.RemoveAndForget(data.mMatchingKey, outputData);
|
||||
NS_ENSURE_TRUE(outputData, NS_ERROR_FAILURE);
|
||||
|
||||
// Store data again with new channel unless told to ignore redirects
|
||||
if (!(mPersistFlags & PERSIST_FLAGS_IGNORE_REDIRECTED_DATA))
|
||||
{
|
||||
nsCOMPtr<nsISupports> keyPtr = do_QueryInterface(aNewChannel);
|
||||
mOutputMap.Put(keyPtr, outputData.forget());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumFixRedirect(nsISupports *aKey, OutputData *aData, void* aClosure)
|
||||
{
|
||||
FixRedirectData *data = static_cast<FixRedirectData*>(aClosure);
|
||||
|
||||
nsCOMPtr<nsIChannel> thisChannel = do_QueryInterface(aKey);
|
||||
nsCOMPtr<nsIURI> thisURI;
|
||||
|
||||
thisChannel->GetOriginalURI(getter_AddRefs(thisURI));
|
||||
|
||||
// Compare this channel's URI to the one passed in.
|
||||
bool matchingURI = false;
|
||||
thisURI->Equals(data->mOriginalURI, &matchingURI);
|
||||
if (matchingURI)
|
||||
{
|
||||
data->mMatchingKey = aKey;
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsWebBrowserPersist::CalcTotalProgress()
|
||||
{
|
||||
mTotalCurrentProgress = 0;
|
||||
mTotalMaxProgress = 0;
|
||||
|
||||
if (mOutputMap.Count() > 0)
|
||||
{
|
||||
if (mOutputMap.Count() > 0) {
|
||||
// Total up the progress of each output stream
|
||||
mOutputMap.EnumerateRead(EnumCalcProgress, this);
|
||||
for (auto iter = mOutputMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
// Only count toward total progress if destination file is local.
|
||||
OutputData* data = iter.UserData();
|
||||
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(data->mFile);
|
||||
if (fileURL) {
|
||||
mTotalCurrentProgress += data->mSelfProgress;
|
||||
mTotalMaxProgress += data->mSelfProgressMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mUploadList.Count() > 0)
|
||||
{
|
||||
if (mUploadList.Count() > 0) {
|
||||
// Total up the progress of each upload
|
||||
mUploadList.EnumerateRead(EnumCalcUploadProgress, this);
|
||||
for (auto iter = mUploadList.Iter(); !iter.Done(); iter.Next()) {
|
||||
UploadData* data = iter.UserData();
|
||||
if (data) {
|
||||
mTotalCurrentProgress += data->mSelfProgress;
|
||||
mTotalMaxProgress += data->mSelfProgressMax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// XXX this code seems pretty bogus and pointless
|
||||
@ -2409,133 +2459,6 @@ nsWebBrowserPersist::CalcTotalProgress()
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCalcProgress(nsISupports *aKey, OutputData *aData, void* aClosure)
|
||||
{
|
||||
nsWebBrowserPersist *pthis = static_cast<nsWebBrowserPersist*>(aClosure);
|
||||
|
||||
// only count toward total progress if destination file is local
|
||||
nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(aData->mFile);
|
||||
if (fileURL)
|
||||
{
|
||||
pthis->mTotalCurrentProgress += aData->mSelfProgress;
|
||||
pthis->mTotalMaxProgress += aData->mSelfProgressMax;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCalcUploadProgress(nsISupports *aKey, UploadData *aData, void* aClosure)
|
||||
{
|
||||
if (aData && aClosure)
|
||||
{
|
||||
nsWebBrowserPersist *pthis = static_cast<nsWebBrowserPersist*>(aClosure);
|
||||
pthis->mTotalCurrentProgress += aData->mSelfProgress;
|
||||
pthis->mTotalMaxProgress += aData->mSelfProgressMax;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCountURIsToPersist(const nsACString &aKey, URIData *aData, void* aClosure)
|
||||
{
|
||||
uint32_t *count = static_cast<uint32_t*>(aClosure);
|
||||
if (aData->mNeedsPersisting && !aData->mSaved)
|
||||
{
|
||||
(*count)++;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumPersistURIs(const nsACString &aKey, URIData *aData, void* aClosure)
|
||||
{
|
||||
if (!aData->mNeedsPersisting || aData->mSaved)
|
||||
{
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsWebBrowserPersist *pthis = static_cast<nsWebBrowserPersist*>(aClosure);
|
||||
nsresult rv;
|
||||
|
||||
// Create a URI from the key
|
||||
nsAutoCString key = nsAutoCString(aKey);
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri),
|
||||
nsDependentCString(key.get(), key.Length()),
|
||||
aData->mCharset.get());
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
|
||||
// Make a URI to save the data to
|
||||
nsCOMPtr<nsIURI> fileAsURI;
|
||||
rv = aData->mDataPath->Clone(getter_AddRefs(fileAsURI));
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
rv = pthis->AppendPathToURI(fileAsURI, aData->mFilename);
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
|
||||
// The Referrer Policy doesn't matter here since the referrer is nullptr.
|
||||
rv = pthis->SaveURIInternal(uri, nullptr, nullptr, mozilla::net::RP_Default,
|
||||
nullptr, nullptr, fileAsURI, true, pthis->mIsPrivate);
|
||||
// if SaveURIInternal fails, then it will have called EndDownload,
|
||||
// which means that |aData| is no longer valid memory. we MUST bail.
|
||||
NS_ENSURE_SUCCESS(rv, PL_DHASH_STOP);
|
||||
|
||||
if (rv == NS_OK)
|
||||
{
|
||||
// Store the actual object because once it's persisted this
|
||||
// will be fixed up with the right file extension.
|
||||
|
||||
aData->mFile = fileAsURI;
|
||||
aData->mSaved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
aData->mNeedsFixup = false;
|
||||
}
|
||||
|
||||
if (pthis->mSerializingOutput)
|
||||
return PL_DHASH_STOP;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCleanupOutputMap(nsISupports *aKey, OutputData *aData, void* aClosure)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aKey);
|
||||
if (channel)
|
||||
{
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCleanupUploadList(nsISupports *aKey, UploadData *aData, void* aClosure)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aKey);
|
||||
if (channel)
|
||||
{
|
||||
channel->Cancel(NS_BINDING_ABORTED);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
nsWebBrowserPersist::EnumCopyURIsToFlatMap(const nsACString &aKey,
|
||||
URIData *aData,
|
||||
void* aClosure)
|
||||
{
|
||||
URIFixupData *fixupData = static_cast<URIFixupData*>(aClosure);
|
||||
FlatURIMap* theMap = fixupData->mFlatMap;
|
||||
nsAutoCString mapTo;
|
||||
nsresult rv = aData->GetLocalURI(fixupData->mTargetBaseURI, mapTo);
|
||||
if (NS_SUCCEEDED(rv) || !mapTo.IsVoid()) {
|
||||
theMap->Add(aKey, mapTo);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsWebBrowserPersist::StoreURI(
|
||||
const char *aURI, bool aNeedsPersisting, URIData **aData)
|
||||
|
@ -136,24 +136,6 @@ private:
|
||||
|
||||
void SetApplyConversionIfNeeded(nsIChannel *aChannel);
|
||||
|
||||
// Hash table enumerators
|
||||
static PLDHashOperator EnumPersistURIs(
|
||||
const nsACString &aKey, URIData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCleanupOutputMap(
|
||||
nsISupports *aKey, OutputData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCleanupUploadList(
|
||||
nsISupports *aKey, UploadData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCalcProgress(
|
||||
nsISupports *aKey, OutputData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCalcUploadProgress(
|
||||
nsISupports *aKey, UploadData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumFixRedirect(
|
||||
nsISupports *aKey, OutputData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCountURIsToPersist(
|
||||
const nsACString &aKey, URIData *aData, void* aClosure);
|
||||
static PLDHashOperator EnumCopyURIsToFlatMap(
|
||||
const nsACString &aKey, URIData *aData, void* aClosure);
|
||||
|
||||
nsCOMPtr<nsIURI> mCurrentDataPath;
|
||||
bool mCurrentDataPathIsRelative;
|
||||
nsCString mCurrentRelativePathToData;
|
||||
|
@ -57,7 +57,7 @@ GrallocImage::~GrallocImage()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
GrallocImage::SetData(const Data& aData)
|
||||
{
|
||||
MOZ_ASSERT(!mTextureClient, "TextureClient is already set");
|
||||
@ -70,7 +70,7 @@ GrallocImage::SetData(const Data& aData)
|
||||
|
||||
if (gfxPlatform::GetPlatform()->IsInGonkEmulator()) {
|
||||
// Emulator does not support HAL_PIXEL_FORMAT_YV12.
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<GrallocTextureClientOGL> textureClient =
|
||||
@ -88,7 +88,7 @@ GrallocImage::SetData(const Data& aData)
|
||||
sp<GraphicBuffer> graphicBuffer = textureClient->GetGraphicBuffer();
|
||||
if (!result || !graphicBuffer.get()) {
|
||||
mTextureClient = nullptr;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
mTextureClient = textureClient;
|
||||
@ -96,7 +96,7 @@ GrallocImage::SetData(const Data& aData)
|
||||
void* vaddr;
|
||||
if (graphicBuffer->lock(GraphicBuffer::USAGE_SW_WRITE_OFTEN,
|
||||
&vaddr) != OK) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* yChannel = static_cast<uint8_t*>(vaddr);
|
||||
@ -144,12 +144,14 @@ GrallocImage::SetData(const Data& aData)
|
||||
mData.mYChannel = nullptr;
|
||||
mData.mCrChannel = nullptr;
|
||||
mData.mCbChannel = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrallocImage::SetData(const GrallocData& aData)
|
||||
bool GrallocImage::SetData(const GrallocData& aData)
|
||||
{
|
||||
mTextureClient = static_cast<GrallocTextureClientOGL*>(aData.mGraphicBuffer.get());
|
||||
mSize = aData.mPicSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -66,13 +66,13 @@ public:
|
||||
* This makes a copy of the data buffers, in order to support functioning
|
||||
* in all different layer managers.
|
||||
*/
|
||||
virtual void SetData(const Data& aData);
|
||||
virtual bool SetData(const Data& aData);
|
||||
|
||||
/**
|
||||
* Share the SurfaceDescriptor without making the copy, in order
|
||||
* to support functioning in all different layer managers.
|
||||
*/
|
||||
virtual void SetData(const GrallocData& aData);
|
||||
virtual bool SetData(const GrallocData& aData);
|
||||
|
||||
// From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
|
||||
enum {
|
||||
|
@ -484,7 +484,7 @@ CopyPlane(uint8_t *aDst, const uint8_t *aSrc,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
PlanarYCbCrImage::CopyData(const Data& aData)
|
||||
{
|
||||
mData = aData;
|
||||
@ -496,7 +496,7 @@ PlanarYCbCrImage::CopyData(const Data& aData)
|
||||
// get new buffer
|
||||
mBuffer = AllocateBuffer(size);
|
||||
if (!mBuffer)
|
||||
return;
|
||||
return false;
|
||||
|
||||
// update buffer size
|
||||
mBufferSize = size;
|
||||
@ -513,12 +513,13 @@ PlanarYCbCrImage::CopyData(const Data& aData)
|
||||
mData.mCbCrSize, mData.mCbCrStride, mData.mCrSkip);
|
||||
|
||||
mSize = aData.mPicSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
PlanarYCbCrImage::SetData(const Data &aData)
|
||||
{
|
||||
CopyData(aData);
|
||||
return CopyData(aData);
|
||||
}
|
||||
|
||||
gfxImageFormat
|
||||
@ -529,11 +530,12 @@ PlanarYCbCrImage::GetOffscreenFormat()
|
||||
mOffscreenFormat;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
PlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
||||
{
|
||||
mData = aData;
|
||||
mSize = aData.mPicSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
|
@ -656,7 +656,7 @@ public:
|
||||
* This makes a copy of the data buffers, in order to support functioning
|
||||
* in all different layer managers.
|
||||
*/
|
||||
virtual void SetData(const Data& aData);
|
||||
virtual bool SetData(const Data& aData);
|
||||
|
||||
/**
|
||||
* This doesn't make a copy of the data buffers. Can be used when mBuffer is
|
||||
@ -665,7 +665,7 @@ public:
|
||||
* The GStreamer media backend uses this to decode into PlanarYCbCrImage(s)
|
||||
* directly.
|
||||
*/
|
||||
virtual void SetDataNoCopy(const Data &aData);
|
||||
virtual bool SetDataNoCopy(const Data &aData);
|
||||
|
||||
/**
|
||||
* This allocates and returns a new buffer
|
||||
@ -709,7 +709,7 @@ protected:
|
||||
*
|
||||
* @param aData Input image data.
|
||||
*/
|
||||
void CopyData(const Data& aData);
|
||||
bool CopyData(const Data& aData);
|
||||
|
||||
/**
|
||||
* Return a buffer to store image data in.
|
||||
|
@ -1051,6 +1051,11 @@ APZCTreeManager::ProcessMouseEvent(WidgetMouseEventBase& aEvent,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutInputBlockId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Note, we call this before having transformed the reference point.
|
||||
UpdateWheelTransaction(aEvent);
|
||||
|
||||
MouseInput input(aEvent);
|
||||
input.mOrigin = ScreenPoint(aEvent.refPoint.x, aEvent.refPoint.y);
|
||||
|
||||
|
@ -3351,11 +3351,8 @@ AsyncPanZoomController::CurrentPanGestureBlock()
|
||||
}
|
||||
|
||||
void
|
||||
AsyncPanZoomController::ResetInputState()
|
||||
AsyncPanZoomController::ResetTouchInputState()
|
||||
{
|
||||
// This may be called during non-touch input blocks as well. We send
|
||||
// a fake cancel touch event here but on the assumption that none of the
|
||||
// code in GEL assumes a CurrentTouchBlock()
|
||||
MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0, TimeStamp::Now(), 0);
|
||||
RefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener) {
|
||||
|
@ -834,9 +834,9 @@ public:
|
||||
bool ArePointerEventsConsumable(TouchBlockState* aBlock, uint32_t aTouchPoints);
|
||||
|
||||
/**
|
||||
* Clear internal state relating to input handling.
|
||||
* Clear internal state relating to touch input handling.
|
||||
*/
|
||||
void ResetInputState();
|
||||
void ResetTouchInputState();
|
||||
|
||||
private:
|
||||
void CancelAnimationAndGestureState();
|
||||
|
@ -651,7 +651,9 @@ InputQueue::ProcessInputBlocks() {
|
||||
curBlock->DropEvents();
|
||||
} else if (curBlock->IsDefaultPrevented()) {
|
||||
curBlock->DropEvents();
|
||||
target->ResetInputState();
|
||||
if (curBlock->AsTouchBlock()) {
|
||||
target->ResetTouchInputState();
|
||||
}
|
||||
} else {
|
||||
UpdateActiveApzc(curBlock->GetTargetApzc());
|
||||
curBlock->HandleEvents();
|
||||
@ -677,7 +679,7 @@ void
|
||||
InputQueue::UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive) {
|
||||
if (mLastActiveApzc && mLastActiveApzc != aNewActive
|
||||
&& mTouchCounter.GetActiveTouchCount() > 0) {
|
||||
mLastActiveApzc->ResetInputState();
|
||||
mLastActiveApzc->ResetTouchInputState();
|
||||
}
|
||||
mLastActiveApzc = aNewActive;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void SetData(const Data& aData) override;
|
||||
virtual bool SetData(const Data& aData) override;
|
||||
virtual void SetDelayedConversion(bool aDelayed) override { mDelayedConversion = aDelayed; }
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
@ -91,20 +91,20 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
bool
|
||||
BasicPlanarYCbCrImage::SetData(const Data& aData)
|
||||
{
|
||||
PlanarYCbCrImage::SetData(aData);
|
||||
|
||||
if (mDelayedConversion) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do some sanity checks to prevent integer overflow
|
||||
if (aData.mYSize.width > PlanarYCbCrImage::MAX_DIMENSION ||
|
||||
aData.mYSize.height > PlanarYCbCrImage::MAX_DIMENSION) {
|
||||
NS_ERROR("Illegal image source width or height");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat format = gfx::ImageFormatToSurfaceFormat(GetOffscreenFormat());
|
||||
@ -114,7 +114,7 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
||||
if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
|
||||
size.height > PlanarYCbCrImage::MAX_DIMENSION) {
|
||||
NS_ERROR("Illegal image dest width or height");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfxImageFormat iFormat = gfx::SurfaceFormatToImageFormat(format);
|
||||
@ -122,12 +122,14 @@ BasicPlanarYCbCrImage::SetData(const Data& aData)
|
||||
mDecodedBuffer = AllocateBuffer(size.height * mStride);
|
||||
if (!mDecodedBuffer) {
|
||||
// out of memory
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::ConvertYCbCrToRGB(aData, format, size, mDecodedBuffer, mStride);
|
||||
SetOffscreenFormat(iFormat);
|
||||
mSize = size;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
|
@ -1650,6 +1650,7 @@ CompositorParent::SetControllerForLayerTree(uint64_t aLayersId,
|
||||
/*static*/ APZCTreeManager*
|
||||
CompositorParent::GetAPZCTreeManager(uint64_t aLayersId)
|
||||
{
|
||||
EnsureLayerTreeMapReady();
|
||||
const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId);
|
||||
if (state && state->mParent) {
|
||||
return state->mParent->mApzcTreeManager;
|
||||
|
@ -80,7 +80,7 @@ SharedPlanarYCbCrImage::GetAsSourceSurface()
|
||||
return PlanarYCbCrImage::GetAsSourceSurface();
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
|
||||
{
|
||||
// If mTextureClient has not already been allocated (through Allocate(aData))
|
||||
@ -88,20 +88,21 @@ SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
|
||||
// been called since it will trigger a full copy.
|
||||
PlanarYCbCrData data = aData;
|
||||
if (!mTextureClient && !Allocate(data)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
|
||||
if (!mTextureClient->Lock(OpenMode::OPEN_WRITE_ONLY)) {
|
||||
MOZ_ASSERT(false, "Failed to lock the texture.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
TextureClientAutoUnlock unlock(mTextureClient);
|
||||
if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
|
||||
MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
mTextureClient->MarkImmutable();
|
||||
return true;
|
||||
}
|
||||
|
||||
// needs to be overriden because the parent class sets mBuffer which we
|
||||
@ -131,12 +132,12 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
||||
return serializer.GetData();
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
||||
{
|
||||
MOZ_ASSERT(mTextureClient, "This Image should have already allocated data");
|
||||
if (!mTextureClient) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
mData = aData;
|
||||
mSize = aData.mPicSize;
|
||||
@ -159,6 +160,7 @@ SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
||||
aData.mYSize,
|
||||
aData.mCbCrSize,
|
||||
aData.mStereoMode);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
|
@ -35,8 +35,8 @@ public:
|
||||
virtual uint8_t* GetBuffer() override;
|
||||
|
||||
virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
virtual void SetData(const PlanarYCbCrData& aData) override;
|
||||
virtual void SetDataNoCopy(const Data &aData) override;
|
||||
virtual bool SetData(const PlanarYCbCrData& aData) override;
|
||||
virtual bool SetDataNoCopy(const Data &aData) override;
|
||||
|
||||
virtual bool Allocate(PlanarYCbCrData& aData);
|
||||
virtual uint8_t* AllocateBuffer(uint32_t aSize) override;
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsMathUtils.h"
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include <algorithm>
|
||||
@ -57,6 +58,22 @@ inline void VERIFY_COORD(nscoord aCoord) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide aSpace by aN. Assign the resulting quotient to aQuotient and
|
||||
* return the remainder.
|
||||
*/
|
||||
inline nscoord NSCoordDivRem(nscoord aSpace, size_t aN, nscoord* aQuotient)
|
||||
{
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
*aQuotient = aSpace / aN;
|
||||
return 0.0f;
|
||||
#else
|
||||
div_t result = div(aSpace, aN);
|
||||
*aQuotient = nscoord(result.quot);
|
||||
return nscoord(result.rem);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline nscoord NSCoordMulDiv(nscoord aMult1, nscoord aMult2, nscoord aDiv) {
|
||||
#ifdef NS_COORD_IS_FLOAT
|
||||
return (aMult1 * aMult2 / aDiv);
|
||||
|
@ -1297,7 +1297,7 @@ js::AsmJSFunctionToString(JSContext* cx, HandleFunction fun)
|
||||
|
||||
size_t nameEnd = begin + fun->atom()->length();
|
||||
Rooted<JSFlatString*> src(cx, source->substring(cx, nameEnd, end));
|
||||
if (!AppendUseStrictSource(cx, fun, src, out))
|
||||
if (!src || !AppendUseStrictSource(cx, fun, src, out))
|
||||
return nullptr;
|
||||
} else {
|
||||
Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end));
|
||||
|
@ -1928,6 +1928,27 @@ NewUDateFormat(JSContext* cx, HandleObject dateTimeFormat)
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
if (!uTimeZone) {
|
||||
#if ENABLE_INTL_API && defined(ICU_TZ_HAS_RECREATE_DEFAULT)
|
||||
// JS::ResetTimeZone() recomputes the JS language's LocalTZA value. It
|
||||
// *should* also recreate ICU's default time zone (used for formatting
|
||||
// when no time zone has been specified), but this operation is slow.
|
||||
// Doing it eagerly introduces a perf regression -- see bug 1220693.
|
||||
// Therefore we perform it lazily, responding to the value of a global
|
||||
// atomic variable that records whether ICU's default time zone is
|
||||
// accurate. Baroque, but it's the only way to get the job done.
|
||||
//
|
||||
// Beware: this is kosher *only* if every place using ICU's default
|
||||
// time zone performs the atomic compare-exchange and possible
|
||||
// recreation song and dance routine here.
|
||||
if (js::DefaultTimeZoneStatus.compareExchange(IcuTimeZoneStatus::NeedsUpdate,
|
||||
IcuTimeZoneStatus::Updating))
|
||||
{
|
||||
icu::TimeZone::recreateDefault();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// If building with ICU headers before 50.1, use UDAT_IGNORE instead of
|
||||
// UDAT_PATTERN.
|
||||
UDateFormat* df =
|
||||
|
@ -793,7 +793,10 @@ ModuleObject::evaluate(JSContext* cx, HandleModuleObject self, MutableHandleValu
|
||||
{
|
||||
RootedScript script(cx, self->script());
|
||||
RootedModuleEnvironmentObject scope(cx, self->environment());
|
||||
MOZ_ASSERT(scope);
|
||||
if (!scope) {
|
||||
JS_ReportError(cx, "Module declarations have not yet been instantiated");
|
||||
return false;
|
||||
}
|
||||
|
||||
return Execute(cx, script, *scope, rval.address());
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ js::obj_propertyIsEnumerable(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
/* Step 1. */
|
||||
RootedId idRoot(cx);
|
||||
if (!ValueToId<CanGC>(cx, idValue, &idRoot))
|
||||
if (!ToPropertyKey(cx, idValue, &idRoot))
|
||||
return false;
|
||||
|
||||
/* Step 2. */
|
||||
@ -531,7 +531,7 @@ js::obj_hasOwnProperty(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
||||
/* Step 1. */
|
||||
RootedId idRoot(cx);
|
||||
if (!ValueToId<CanGC>(cx, idValue, &idRoot))
|
||||
if (!ToPropertyKey(cx, idValue, &idRoot))
|
||||
return false;
|
||||
|
||||
/* Step 2. */
|
||||
@ -774,7 +774,7 @@ js::obj_defineProperty(JSContext* cx, unsigned argc, Value* vp)
|
||||
if (!GetFirstArgumentAsObject(cx, args, "Object.defineProperty", &obj))
|
||||
return false;
|
||||
RootedId id(cx);
|
||||
if (!ValueToId<CanGC>(cx, args.get(1), &id))
|
||||
if (!ToPropertyKey(cx, args.get(1), &id))
|
||||
return false;
|
||||
|
||||
// Steps 4-5.
|
||||
|
@ -2491,8 +2491,9 @@ ASTSerializer::forInit(ParseNode* pn, MutableHandleValue dst)
|
||||
return true;
|
||||
}
|
||||
|
||||
return (pn->isKind(PNK_VAR))
|
||||
? variableDeclaration(pn, false, dst)
|
||||
bool lexical = pn->isKind(PNK_LET) || pn->isKind(PNK_CONST);
|
||||
return (lexical || pn->isKind(PNK_VAR))
|
||||
? variableDeclaration(pn, lexical, dst)
|
||||
: expression(pn, dst);
|
||||
}
|
||||
|
||||
@ -2641,32 +2642,31 @@ ASTSerializer::statement(ParseNode* pn, MutableHandleValue dst)
|
||||
if (!statement(pn->pn_right, &stmt))
|
||||
return false;
|
||||
|
||||
if (head->isKind(PNK_FORIN)) {
|
||||
if (head->isKind(PNK_FORIN) || head->isKind(PNK_FOROF)) {
|
||||
RootedValue var(cx);
|
||||
return (!head->pn_kid1
|
||||
? pattern(head->pn_kid2, &var)
|
||||
: head->pn_kid1->isKind(PNK_LEXICALSCOPE)
|
||||
? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
|
||||
: variableDeclaration(head->pn_kid1, false, &var)) &&
|
||||
forIn(pn, head, var, stmt, dst);
|
||||
}
|
||||
|
||||
if (head->isKind(PNK_FOROF)) {
|
||||
RootedValue var(cx);
|
||||
return (!head->pn_kid1
|
||||
? pattern(head->pn_kid2, &var)
|
||||
: head->pn_kid1->isKind(PNK_LEXICALSCOPE)
|
||||
? variableDeclaration(head->pn_kid1->pn_expr, true, &var)
|
||||
: variableDeclaration(head->pn_kid1, false, &var)) &&
|
||||
forOf(pn, head, var, stmt, dst);
|
||||
if (!head->pn_kid1) {
|
||||
if (!pattern(head->pn_kid2, &var))
|
||||
return false;
|
||||
} else if (head->pn_kid1->isKind(PNK_LEXICALSCOPE)) {
|
||||
if (!variableDeclaration(head->pn_kid1->pn_expr, true, &var))
|
||||
return false;
|
||||
} else {
|
||||
if (!variableDeclaration(head->pn_kid1,
|
||||
head->pn_kid1->isKind(PNK_LET) ||
|
||||
head->pn_kid1->isKind(PNK_CONST),
|
||||
&var))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (head->isKind(PNK_FORIN))
|
||||
return forIn(pn, head, var, stmt, dst);
|
||||
return forOf(pn, head, var, stmt, dst);
|
||||
}
|
||||
|
||||
RootedValue init(cx), test(cx), update(cx);
|
||||
|
||||
return forInit(head->pn_kid1 && !head->pn_kid1->isKind(PNK_FRESHENBLOCK)
|
||||
? head->pn_kid1
|
||||
: nullptr,
|
||||
&init) &&
|
||||
return forInit(head->pn_kid1, &init) &&
|
||||
optExpression(head->pn_kid2, &test) &&
|
||||
optExpression(head->pn_kid3, &update) &&
|
||||
builder.forStatement(init, test, update, stmt, &pn->pn_pos, dst);
|
||||
|
@ -2323,7 +2323,6 @@ BytecodeEmitter::checkSideEffects(ParseNode* pn, bool* answer)
|
||||
case PNK_FORIN: // by PNK_FOR
|
||||
case PNK_FOROF: // by PNK_FOR
|
||||
case PNK_FORHEAD: // by PNK_FOR
|
||||
case PNK_FRESHENBLOCK: // by PNK_FOR
|
||||
case PNK_CLASSMETHOD: // by PNK_CLASS
|
||||
case PNK_CLASSNAMES: // by PNK_CLASS
|
||||
case PNK_CLASSMETHODLIST: // by PNK_CLASS
|
||||
@ -5289,6 +5288,15 @@ BytecodeEmitter::emitIterator()
|
||||
bool
|
||||
BytecodeEmitter::emitForInOrOfVariables(ParseNode* pn, bool* letDecl)
|
||||
{
|
||||
// ES6 specifies that loop variables get a fresh binding in each iteration.
|
||||
// This is currently implemented for C-style for(;;) loops, but not
|
||||
// for-in/of loops, though a similar approach should work. See bug 449811.
|
||||
//
|
||||
// In `for (let x in/of EXPR)`, ES6 specifies that EXPR is evaluated in a
|
||||
// scope containing an uninitialized `x`. If EXPR accesses `x`, we should
|
||||
// get a ReferenceError due to the TDZ violation. This is not yet
|
||||
// implemented. See bug 1069480.
|
||||
|
||||
*letDecl = pn->isKind(PNK_LEXICALSCOPE);
|
||||
MOZ_ASSERT_IF(*letDecl, pn->isLexical());
|
||||
|
||||
@ -5318,7 +5326,6 @@ BytecodeEmitter::emitForInOrOfVariables(ParseNode* pn, bool* letDecl)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BytecodeEmitter::emitForOf(StmtType type, ParseNode* pn, ptrdiff_t top)
|
||||
{
|
||||
@ -5591,8 +5598,9 @@ BytecodeEmitter::emitForIn(ParseNode* pn, ptrdiff_t top)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* C-style `for (init; cond; update) ...` loop. */
|
||||
bool
|
||||
BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top)
|
||||
BytecodeEmitter::emitCStyleFor(ParseNode* pn, ptrdiff_t top)
|
||||
{
|
||||
LoopStmtInfo stmtInfo(cx);
|
||||
pushLoopStatement(&stmtInfo, StmtType::FOR_LOOP, top);
|
||||
@ -5600,28 +5608,48 @@ BytecodeEmitter::emitNormalFor(ParseNode* pn, ptrdiff_t top)
|
||||
ParseNode* forHead = pn->pn_left;
|
||||
ParseNode* forBody = pn->pn_right;
|
||||
|
||||
/* C-style for (init; cond; update) ... loop. */
|
||||
// If the head of this for-loop declared any lexical variables, the parser
|
||||
// wrapped this PNK_FOR node in a PNK_LEXICALSCOPE representing the
|
||||
// implicit scope of those variables. By the time we get here, we have
|
||||
// already entered that scope. So far, so good.
|
||||
//
|
||||
// ### Scope freshening
|
||||
//
|
||||
// Each iteration of a `for (let V...)` loop creates a fresh loop variable
|
||||
// binding for V, even if the loop is a C-style `for(;;)` loop:
|
||||
//
|
||||
// var funcs = [];
|
||||
// for (let i = 0; i < 2; i++)
|
||||
// funcs.push(function() { return i; });
|
||||
// assertEq(funcs[0](), 0); // the two closures capture...
|
||||
// assertEq(funcs[1](), 1); // ...two different `i` bindings
|
||||
//
|
||||
// This is implemented by "freshening" the implicit block -- changing the
|
||||
// scope chain to a fresh clone of the instantaneous block object -- each
|
||||
// iteration, just before evaluating the "update" in for(;;) loops.
|
||||
//
|
||||
// No freshening occurs in `for (const ...;;)` as there's no point: you
|
||||
// can't reassign consts. This is observable through the Debugger API. (The
|
||||
// ES6 spec also skips cloning the environment in this case.)
|
||||
bool forLoopRequiresFreshening = false;
|
||||
if (ParseNode* init = forHead->pn_kid1) {
|
||||
if (init->isKind(PNK_FRESHENBLOCK)) {
|
||||
// The loop's init declaration was hoisted into an enclosing lexical
|
||||
// scope node. Note that the block scope must be freshened each
|
||||
// iteration.
|
||||
forLoopRequiresFreshening = true;
|
||||
} else {
|
||||
emittingForInit = true;
|
||||
if (!updateSourceCoordNotes(init->pn_pos.begin))
|
||||
return false;
|
||||
if (!emitTree(init))
|
||||
return false;
|
||||
emittingForInit = false;
|
||||
forLoopRequiresFreshening = init->isKind(PNK_LET);
|
||||
|
||||
if (!init->isKind(PNK_VAR) && !init->isKind(PNK_LET) && !init->isKind(PNK_CONST)) {
|
||||
// 'init' is an expression, not a declaration. emitTree left
|
||||
// its value on the stack.
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
// Emit the `init` clause, whether it's an expression or a variable
|
||||
// declaration. (The loop variables were hoisted into an enclosing
|
||||
// scope, but we still need to emit code for the initializers.)
|
||||
emittingForInit = true;
|
||||
if (!updateSourceCoordNotes(init->pn_pos.begin))
|
||||
return false;
|
||||
if (!emitTree(init))
|
||||
return false;
|
||||
emittingForInit = false;
|
||||
|
||||
if (!init->isKind(PNK_VAR) && !init->isKind(PNK_LET) && !init->isKind(PNK_CONST)) {
|
||||
// 'init' is an expression, not a declaration. emitTree left its
|
||||
// value on the stack.
|
||||
if (!emit1(JSOP_POP))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5749,7 +5777,7 @@ BytecodeEmitter::emitFor(ParseNode* pn, ptrdiff_t top)
|
||||
return emitForOf(StmtType::FOR_OF_LOOP, pn, top);
|
||||
|
||||
MOZ_ASSERT(pn->pn_left->isKind(PNK_FORHEAD));
|
||||
return emitNormalFor(pn, top);
|
||||
return emitCStyleFor(pn, top);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE bool
|
||||
|
@ -586,7 +586,7 @@ struct BytecodeEmitter
|
||||
bool emitFor(ParseNode* pn, ptrdiff_t top);
|
||||
bool emitForIn(ParseNode* pn, ptrdiff_t top);
|
||||
bool emitForInOrOfVariables(ParseNode* pn, bool* letDecl);
|
||||
bool emitNormalFor(ParseNode* pn, ptrdiff_t top);
|
||||
bool emitCStyleFor(ParseNode* pn, ptrdiff_t top);
|
||||
bool emitWhile(ParseNode* pn, ptrdiff_t top);
|
||||
|
||||
bool emitBreak(PropertyName* label);
|
||||
|
@ -408,7 +408,6 @@ ContainsHoistedDeclaration(ExclusiveContext* cx, ParseNode* node, bool* result)
|
||||
case PNK_FORIN:
|
||||
case PNK_FOROF:
|
||||
case PNK_FORHEAD:
|
||||
case PNK_FRESHENBLOCK:
|
||||
case PNK_CLASSMETHOD:
|
||||
case PNK_CLASSMETHODLIST:
|
||||
case PNK_CLASSNAMES:
|
||||
@ -1710,7 +1709,6 @@ Fold(ExclusiveContext* cx, ParseNode** pnp, Parser<FullParseHandler>& parser, bo
|
||||
case PNK_GENERATOR:
|
||||
case PNK_EXPORT_BATCH_SPEC:
|
||||
case PNK_OBJECT_PROPERTY_NAME:
|
||||
case PNK_FRESHENBLOCK:
|
||||
case PNK_POSHOLDER:
|
||||
MOZ_ASSERT(pn->isArity(PN_NULLARY));
|
||||
return true;
|
||||
|
@ -571,10 +571,6 @@ class FullParseHandler
|
||||
return new_<TernaryNode>(kind, JSOP_NOP, pn1, pn2, pn3, pos);
|
||||
}
|
||||
|
||||
ParseNode* newFreshenBlock(const TokenPos& pos) {
|
||||
return new_<NullaryNode>(PNK_FRESHENBLOCK, pos);
|
||||
}
|
||||
|
||||
ParseNode* newSwitchStatement(uint32_t begin, ParseNode* discriminant, ParseNode* caseList) {
|
||||
TokenPos pos(begin, caseList->pn_pos.end);
|
||||
return new_<BinaryNode>(PNK_SWITCH, JSOP_NOP, pos, discriminant, caseList);
|
||||
|
@ -374,7 +374,6 @@ class NameResolver
|
||||
case PNK_CONTINUE:
|
||||
case PNK_DEBUGGER:
|
||||
case PNK_EXPORT_BATCH_SPEC:
|
||||
case PNK_FRESHENBLOCK:
|
||||
case PNK_OBJECT_PROPERTY_NAME:
|
||||
case PNK_POSHOLDER:
|
||||
MOZ_ASSERT(cur->isArity(PN_NULLARY));
|
||||
|
@ -214,7 +214,6 @@ PushNodeChildren(ParseNode* pn, NodeStack* stack)
|
||||
case PNK_DEBUGGER:
|
||||
case PNK_EXPORT_BATCH_SPEC:
|
||||
case PNK_OBJECT_PROPERTY_NAME:
|
||||
case PNK_FRESHENBLOCK:
|
||||
case PNK_POSHOLDER:
|
||||
MOZ_ASSERT(pn->isArity(PN_NULLARY));
|
||||
MOZ_ASSERT(!pn->isUsed(), "handle non-trivial cases separately");
|
||||
|
@ -165,7 +165,6 @@ class PackedScopeCoordinate
|
||||
F(FORIN) \
|
||||
F(FOROF) \
|
||||
F(FORHEAD) \
|
||||
F(FRESHENBLOCK) \
|
||||
F(ARGSBODY) \
|
||||
F(SPREAD) \
|
||||
F(MUTATEPROTO) \
|
||||
|
@ -4063,7 +4063,8 @@ Parser<FullParseHandler>::pushLetScope(HandleStaticBlockObject blockObj, AutoPus
|
||||
|
||||
template <>
|
||||
SyntaxParseHandler::Node
|
||||
Parser<SyntaxParseHandler>::pushLetScope(HandleStaticBlockObject blockObj, AutoPushStmtInfoPC& stmt)
|
||||
Parser<SyntaxParseHandler>::pushLetScope(HandleStaticBlockObject blockObj,
|
||||
AutoPushStmtInfoPC& stmt)
|
||||
{
|
||||
JS_ALWAYS_FALSE(abortIfSyntaxParser());
|
||||
return SyntaxParseHandler::NodeFailure;
|
||||
@ -5187,19 +5188,37 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
|
||||
|
||||
MUST_MATCH_TOKEN(TOK_LP, JSMSG_PAREN_AFTER_FOR);
|
||||
|
||||
/*
|
||||
* True if we have 'for (var/let/const ...)'.
|
||||
*/
|
||||
// True if we have 'for (var/let/const ...)'.
|
||||
bool isForDecl = false;
|
||||
|
||||
// The next three variables are used to implement `for (let/const ...)`.
|
||||
//
|
||||
// We generate an implicit block, wrapping the whole loop, to store loop
|
||||
// variables declared this way. Note that if the loop uses `for (var...)`
|
||||
// instead, those variables go on some existing enclosing scope, so no
|
||||
// implicit block scope is created.
|
||||
//
|
||||
// All three variables remain null/none if the loop is any other form.
|
||||
//
|
||||
// blockObj is the static block object for the implicit block scope.
|
||||
RootedStaticBlockObject blockObj(context);
|
||||
|
||||
// letStmt is the BLOCK StmtInfo for the implicit block.
|
||||
//
|
||||
// Caution: `letStmt.emplace()` creates some Rooted objects. Rooteds must
|
||||
// be created/destroyed in FIFO order. Therefore adding a Rooted in this
|
||||
// function, between this point and the .emplace() call below, would trip
|
||||
// assertions.
|
||||
Maybe<AutoPushStmtInfoPC> letStmt;
|
||||
|
||||
// The PNK_LEXICALSCOPE node containing blockObj's ObjectBox.
|
||||
ParseNode* forLetImpliedBlock = nullptr;
|
||||
|
||||
// True if a 'let' token at the head is parsed as an identifier instead of
|
||||
// as starting a declaration.
|
||||
bool letIsIdentifier = false;
|
||||
|
||||
/* Non-null when isForDecl is true for a 'for (let ...)' statement. */
|
||||
RootedStaticBlockObject blockObj(context);
|
||||
|
||||
/* Set to 'x' in 'for (x ;... ;...)' or 'for (x in ...)'. */
|
||||
// Set to 'x' in 'for (x; ...; ...)' or 'for (x in ...)'.
|
||||
ParseNode* pn1;
|
||||
|
||||
TokenStream::Modifier modifier = TokenStream::Operand;
|
||||
@ -5249,9 +5268,19 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
|
||||
|
||||
// Initialize the enclosing scope manually for the call to
|
||||
// |variables| below.
|
||||
blockObj = StaticBlockObject::create(context);
|
||||
if (!blockObj)
|
||||
return null();
|
||||
blockObj->initEnclosingScopeFromParser(pc->innermostStaticScope());
|
||||
letStmt.emplace(*this, StmtType::BLOCK);
|
||||
forLetImpliedBlock = pushLetScope(blockObj, *letStmt);
|
||||
if (!forLetImpliedBlock)
|
||||
return null();
|
||||
(*letStmt)->isForLetBlock = true;
|
||||
|
||||
MOZ_ASSERT(CurrentLexicalStaticBlock(pc) == blockObj);
|
||||
pn1 = variables(yieldHandling, constDecl ? PNK_CONST : PNK_LET, InForInit,
|
||||
nullptr, blockObj, DontHoistVars);
|
||||
nullptr, blockObj, HoistVars);
|
||||
} else {
|
||||
pn1 = expr(InProhibited, yieldHandling, TripledotProhibited);
|
||||
}
|
||||
@ -5269,60 +5298,10 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(isForDecl, pn1->isArity(PN_LIST));
|
||||
MOZ_ASSERT(!!blockObj == (isForDecl && (pn1->isOp(JSOP_DEFLET) || pn1->isOp(JSOP_DEFCONST))));
|
||||
|
||||
// If the head of a for-loop declares any lexical variables, we generate an
|
||||
// implicit block to store them. We implement this by desugaring. These:
|
||||
//
|
||||
// for (let/const <bindings>; <test>; <update>) <stmt>
|
||||
// for (let <pattern> in <expr>) <stmt>
|
||||
// for (let <pattern> of <expr>) <stmt>
|
||||
//
|
||||
// transform into roughly the same parse trees as these (using deprecated
|
||||
// let-block syntax):
|
||||
//
|
||||
// let (<bindings>) { for (; <test>; <update>) <stmt> }
|
||||
// let (<pattern>) { for (<pattern> in <expr>) <stmt> }
|
||||
// let (<pattern>) { for (<pattern> of <expr>) <stmt> }
|
||||
//
|
||||
// This desugaring is not ES6 compliant. Initializers in the head of a
|
||||
// let-block are evaluated *outside* the scope of the variables being
|
||||
// initialized. ES6 mandates that they be evaluated in the same scope,
|
||||
// triggering used-before-initialization temporal dead zone errors as
|
||||
// necessary. See bug 1216623 on scoping and bug 1069480 on TDZ.
|
||||
//
|
||||
// Additionally, in ES6, each iteration of a for-loop creates a fresh
|
||||
// binding of the loop variables. For example:
|
||||
//
|
||||
// var funcs = [];
|
||||
// for (let i = 0; i < 2; i++)
|
||||
// funcs.push(function() { return i; });
|
||||
// assertEq(funcs[0](), 0); // the two closures capture...
|
||||
// assertEq(funcs[1](), 1); // ...two different `i` bindings
|
||||
//
|
||||
// These semantics are implemented by "freshening" the implicit block --
|
||||
// changing the scope chain to a fresh clone of the instantaneous block
|
||||
// object -- each iteration, just before evaluating the "update" in
|
||||
// for(;;) loops. We don't implement this freshening for for-in/of loops
|
||||
// yet: bug 449811.
|
||||
//
|
||||
// No freshening occurs in `for (const ...;;)` as there's no point: you
|
||||
// can't reassign consts. This is observable through the Debugger API. (The
|
||||
// ES6 spec also skips cloning the environment in this case.)
|
||||
//
|
||||
// If the for-loop head includes a lexical declaration, then we create an
|
||||
// implicit block scope, and:
|
||||
//
|
||||
// * forLetImpliedBlock is the node for the implicit block scope.
|
||||
// * forLetDecl is the node for the decl 'let/const <pattern>'.
|
||||
//
|
||||
// Otherwise both are null.
|
||||
ParseNode* forLetImpliedBlock = nullptr;
|
||||
ParseNode* forLetDecl = nullptr;
|
||||
MOZ_ASSERT(letStmt.isSome() == (isForDecl && (pn1->isOp(JSOP_DEFLET) || pn1->isOp(JSOP_DEFCONST))));
|
||||
|
||||
// If there's an |in| keyword here, it's a for-in loop, by dint of careful
|
||||
// parsing of |pn1|.
|
||||
Maybe<AutoPushStmtInfoPC> letStmt; /* used if blockObj != nullptr. */
|
||||
ParseNode* pn2; /* forHead->pn_kid2 */
|
||||
ParseNode* pn3; /* forHead->pn_kid3 */
|
||||
ParseNodeKind headKind = PNK_FORHEAD;
|
||||
@ -5393,7 +5372,7 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
|
||||
}
|
||||
} else {
|
||||
/* Not a declaration. */
|
||||
MOZ_ASSERT(!blockObj);
|
||||
MOZ_ASSERT(!letStmt);
|
||||
pn2 = pn1;
|
||||
pn1 = nullptr;
|
||||
|
||||
@ -5408,27 +5387,10 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
|
||||
return null();
|
||||
modifier = TokenStream::None;
|
||||
|
||||
if (blockObj) {
|
||||
/*
|
||||
* Now that the pn3 has been parsed, push the let scope. To hold
|
||||
* the blockObj for the emitter, wrap the PNK_LEXICALSCOPE node
|
||||
* created by pushLetScope around the for's initializer. This also
|
||||
* serves to indicate the let-decl to the emitter.
|
||||
*/
|
||||
letStmt.emplace(*this, StmtType::BLOCK);
|
||||
ParseNode* block = pushLetScope(blockObj, *letStmt);
|
||||
if (!block)
|
||||
return null();
|
||||
(*letStmt)->isForLetBlock = true;
|
||||
block->pn_expr = pn1;
|
||||
block->pn_pos = pn1->pn_pos;
|
||||
pn1 = block;
|
||||
}
|
||||
|
||||
if (isForDecl) {
|
||||
/*
|
||||
* pn2 is part of a declaration. Make a copy that can be passed to
|
||||
* EmitAssignment. Take care to do this after pushLetScope.
|
||||
* BytecodeEmitter::emitAssignment.
|
||||
*/
|
||||
pn2 = cloneLeftHandSide(pn2);
|
||||
if (!pn2)
|
||||
@ -5450,47 +5412,13 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
|
||||
|
||||
MOZ_ASSERT(headKind == PNK_FORHEAD);
|
||||
|
||||
if (blockObj) {
|
||||
if (letStmt) {
|
||||
// Ensure here that the previously-unchecked assignment mandate for
|
||||
// const declarations holds.
|
||||
if (!checkForHeadConstInitializers(pn1)) {
|
||||
report(ParseError, false, nullptr, JSMSG_BAD_CONST_DECL);
|
||||
return null();
|
||||
}
|
||||
|
||||
// Desugar
|
||||
//
|
||||
// for (let INIT; TEST; UPDATE) STMT
|
||||
//
|
||||
// into
|
||||
//
|
||||
// let (INIT) { for (; TEST; UPDATE) STMT }
|
||||
//
|
||||
// to provide a block scope for INIT.
|
||||
letStmt.emplace(*this, StmtType::BLOCK);
|
||||
forLetImpliedBlock = pushLetScope(blockObj, *letStmt);
|
||||
if (!forLetImpliedBlock)
|
||||
return null();
|
||||
(*letStmt)->isForLetBlock = true;
|
||||
|
||||
forLetDecl = pn1;
|
||||
|
||||
// The above transformation isn't enough to implement |INIT|
|
||||
// scoping, because each loop iteration must see separate bindings
|
||||
// of |INIT|. We handle this by replacing the block on the scope
|
||||
// chain with a new block, copying the old one's contents, each
|
||||
// iteration. We supply a special PNK_FRESHENBLOCK node as the
|
||||
// |let INIT| node for |for(let INIT;;)| loop heads to distinguish
|
||||
// such nodes from *actual*, non-desugared use of the above syntax.
|
||||
// (We don't do this for PNK_CONST nodes because the spec says no
|
||||
// freshening happens -- observable with the Debugger API.)
|
||||
if (pn1->isKind(PNK_CONST)) {
|
||||
pn1 = nullptr;
|
||||
} else {
|
||||
pn1 = handler.newFreshenBlock(pn1->pn_pos);
|
||||
if (!pn1)
|
||||
return null();
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the loop condition or null into pn2. */
|
||||
@ -5542,7 +5470,7 @@ Parser<FullParseHandler>::forStatement(YieldHandling yieldHandling)
|
||||
if (forLetImpliedBlock) {
|
||||
forLetImpliedBlock->pn_expr = forLoop;
|
||||
forLetImpliedBlock->pn_pos = forLoop->pn_pos;
|
||||
return handler.newLetBlock(forLetDecl, forLetImpliedBlock, forLoop->pn_pos);
|
||||
return forLetImpliedBlock;
|
||||
}
|
||||
return forLoop;
|
||||
}
|
||||
@ -8293,6 +8221,7 @@ Parser<ParseHandler>::comprehensionFor(GeneratorKind comprehensionKind)
|
||||
RootedStaticBlockObject blockObj(context, StaticBlockObject::create(context));
|
||||
if (!blockObj)
|
||||
return null();
|
||||
|
||||
// Initialize the enclosing scope manually for the call to |bind|
|
||||
// below, which is before the call to |pushLetScope|.
|
||||
blockObj->initEnclosingScopeFromParser(pc->innermostStaticScope());
|
||||
|
12
js/src/jit-test/tests/asm.js/bug1219954.js
Normal file
12
js/src/jit-test/tests/asm.js/bug1219954.js
Normal file
@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
let g = (function() {
|
||||
"use asm";
|
||||
function f() {}
|
||||
return f;
|
||||
})();
|
||||
|
||||
oomTest(() => "" + g);
|
9
js/src/jit-test/tests/basic/bug1219363.js
Normal file
9
js/src/jit-test/tests/basic/bug1219363.js
Normal file
@ -0,0 +1,9 @@
|
||||
var x = [1, 2, , 4]
|
||||
x[100000] = 1;
|
||||
var y = Object.create(x);
|
||||
y.a = 1;
|
||||
y.b = 1;
|
||||
var arr = [];
|
||||
for (var z in y)
|
||||
arr.push(z);
|
||||
assertEq(arr.join(), "a,b,0,1,3,100000");
|
@ -1,16 +1,16 @@
|
||||
var s, x = 0;
|
||||
var s, v = "NOPE";
|
||||
|
||||
s = '';
|
||||
for (let x = x; x < 3; x++)
|
||||
for (let v = 0, x = v; x < 3; x++)
|
||||
s += x;
|
||||
assertEq(s, '012');
|
||||
|
||||
s = '';
|
||||
for (let x = eval('x'); x < 3; x++)
|
||||
for (let v = 0, x = eval('v'); x < 3; x++)
|
||||
s += x;
|
||||
assertEq(s, '012');
|
||||
|
||||
s = ''
|
||||
for (let x = function () { with ({}) return x; }(); x < 3; x++)
|
||||
for (let v = 0, x = function () { with ({}) return v; }(); x < 3; x++)
|
||||
s += x;
|
||||
assertEq(s, '012');
|
||||
|
@ -1,4 +1,8 @@
|
||||
var s = '', x = {a: 1, b: 2, c: 3};
|
||||
// Scoping: `x` in the head of a `for (let x...)` loop refers to the loop variable.
|
||||
|
||||
// For now, this means it evaluates to undefined. It ought to throw a
|
||||
// ReferenceError instead, but the TDZ isn't implemented here (bug 1069480).
|
||||
var s = "", x = {a: 1, b: 2, c: 3};
|
||||
for (let x in eval('x'))
|
||||
s += x;
|
||||
assertEq(s, 'abc');
|
||||
assertEq(s, "");
|
||||
|
16
js/src/jit-test/tests/basic/bug646968-6.js
Normal file
16
js/src/jit-test/tests/basic/bug646968-6.js
Normal file
@ -0,0 +1,16 @@
|
||||
// In `for (let x = EXPR; ;)`, if `x` appears within EXPR, it refers to the
|
||||
// loop variable. Actually doing this is typically a TDZ error.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
assertThrowsInstanceOf(() => {
|
||||
for (let x = x; null.foo; null.foo++) {}
|
||||
}, ReferenceError);
|
||||
|
||||
assertThrowsInstanceOf(() => {
|
||||
for (let x = eval('x'); null.foo; null.foo++) {}
|
||||
}, ReferenceError);
|
||||
|
||||
assertThrowsInstanceOf(() => {
|
||||
for (let x = function () { with ({}) return x; }(); null.foo; null.foo++) {}
|
||||
}, ReferenceError);
|
@ -1,5 +0,0 @@
|
||||
var x = "foobar";
|
||||
{ for (let x of x) assertEq(x.length, 1, "second x refers to outer x"); }
|
||||
|
||||
var x = "foobar";
|
||||
{ for (let x in x) assertEq(x.length, 1, "second x refers to outer x"); }
|
@ -3,7 +3,8 @@ var otherGlobal = newGlobal();
|
||||
function test(str, arg, result)
|
||||
{
|
||||
arg = arg || 'ponies';
|
||||
result = result || 'ponies';
|
||||
if (arguments.length < 3)
|
||||
result = 'ponies';
|
||||
|
||||
var fun = new Function('x', str);
|
||||
|
||||
@ -136,11 +137,7 @@ test('for (let y = 1;; ++y) {return x;}');
|
||||
test('for (let y = 1; ++y;) {return x;}');
|
||||
test('for (let [[a, [b, c]]] = [[x, []]];;) {return a;}');
|
||||
test('var sum = 0;for (let y = x; y < 4; ++y) {sum += y;}return sum;', 1, 6);
|
||||
test('var sum = 0;for (let x = x, y = 10; x < 4; ++x) {sum += x;}return sum;', 1, 6);
|
||||
test('var sum = 0;for (let x = x; x < 4; ++x) {sum += x;}return x;', 1, 1);
|
||||
test('var sum = 0;for (let x = eval("x"); x < 4; ++x) {sum += x;}return sum;', 1, 6);
|
||||
test('var sum = 0;for (let x = x; eval("x") < 4; ++x) {sum += eval("x");}return sum;', 1, 6);
|
||||
test('var sum = 0;for (let x = eval("x"); eval("x") < 4; ++x) {sum += eval("x");}return sum;', 1, 6);
|
||||
test('var sum = 0;for (let x = 1; eval("x") < 4; ++x) {sum += eval("x");}return sum;', 1, 6);
|
||||
test('for (var y = 1;;) {return x;}');
|
||||
test('for (var y = 1;; ++y) {return x;}');
|
||||
test('for (var y = 1; ++y;) {return x;}');
|
||||
@ -151,8 +148,6 @@ test('var sum = 0;for (var X = x; X < 4; ++X) {sum += X;}return x;', 1, 1);
|
||||
test('var sum = 0;for (var X = eval("x"); X < 4; ++X) {sum += X;}return sum;', 1, 6);
|
||||
test('var sum = 0;for (var X = x; eval("X") < 4; ++X) {sum += eval("X");}return sum;', 1, 6);
|
||||
test('var sum = 0;for (var X = eval("x"); eval("X") < 4; ++X) {sum += eval("X");}return sum;', 1, 6);
|
||||
test('try {for (let x = eval("throw x");;) {}} catch (e) {return e;}');
|
||||
test('try {for (let x = x + "s"; eval("throw x");) {}} catch (e) {return e;}', 'ponie');
|
||||
test('for (let y = x;;) {let x;return y;}');
|
||||
test('for (let y = x;;) {let y;return x;}');
|
||||
test('for (let y;;) {let y;return x;}');
|
||||
@ -170,28 +165,31 @@ test('for (let i in x) {return x;}');
|
||||
test('for (let i in x) {let y;return x;}');
|
||||
test('for each (let [a, b] in x) {let y;return x;}');
|
||||
test('for (let i in x) {let i = x;return i;}');
|
||||
test('for each (let [x, y] in x) {return x + y;}', [['ponies', '']]);
|
||||
test('for each (let [{0: x, 1: y}, z] in x) {return x + y + z;}', [[['po','nies'], '']]);
|
||||
test('var s = "";for (let a in x) {for (let b in x) {s += a + b;}}return s;', [1,2], '00011011');
|
||||
test('var res = "";for (let i in x) {res += x[i];}return res;');
|
||||
test('var res = "";for (var i in x) {res += x[i];}return res;');
|
||||
test('for each (let {x: y, y: x} in [{x: x, y: x}]) {return y;}');
|
||||
test('for (let x in eval("x")) {return x;}', {ponies:true});
|
||||
test('for (let x in x) {return eval("x");}', {ponies:true});
|
||||
test('for (let x in eval("x")) {return eval("x");}', {ponies:true});
|
||||
isParseError('for ((let (x = {y: true}) x).y in eval("x")) {return eval("x");}');
|
||||
test('for (let i in x) {break;}return x;');
|
||||
test('for (let i in x) {break;}return eval("x");');
|
||||
test('for (let x in x) {break;}return x;');
|
||||
test('for (let x in x) {break;}return eval("x");');
|
||||
test('a:for (let i in x) {for (let j in x) {break a;}}return x;');
|
||||
test('a:for (let i in x) {for (let j in x) {break a;}}return eval("x");');
|
||||
test('var j;for (let i in x) {j = i;break;}return j;', {ponies:true});
|
||||
test('try {for (let x in eval("throw x")) {}} catch (e) {return e;}');
|
||||
test('try {for each (let x in x) {eval("throw x");}} catch (e) {return e;}', ['ponies']);
|
||||
isParseError('for (let [x, x] in o) {}');
|
||||
isParseError('for (let [x, y, x] in o) {}');
|
||||
isParseError('for (let [x, [y, [x]]] in o) {}');
|
||||
|
||||
// for(let ... in ...) scoping bugs (bug 1069480)
|
||||
test('for each (let [x, y] in x) {return x + y;}', [['ponies', '']], undefined);
|
||||
test('for each (let [{0: x, 1: y}, z] in x) {return x + y + z;}', [[['po','nies'], '']], undefined);
|
||||
test('for (let x in eval("x")) {return x;}', {ponies:true}, undefined);
|
||||
test('for (let x in x) {return eval("x");}', {ponies:true}, undefined);
|
||||
test('for (let x in eval("x")) {return eval("x");}', {ponies:true}, undefined);
|
||||
test('for (let x in x) {break;}return x;');
|
||||
test('for (let x in x) {break;}return eval("x");');
|
||||
test('try {for (let x in eval("throw x")) {}} catch (e) {return e;}', undefined, undefined);
|
||||
test('try {for each (let x in x) {eval("throw x");}} catch (e) {return e;}', ['ponies'], undefined);
|
||||
test('for each (let {x: y, y: x} in [{x: x, y: x}]) {return y;}', undefined, undefined);
|
||||
|
||||
// genexps
|
||||
test('return (i for (i in x)).next();', {ponies:true});
|
||||
test('return (eval("i") for (i in x)).next();', {ponies:true});
|
||||
@ -222,6 +220,13 @@ isReferenceError('let {x} = {x:x};');
|
||||
isReferenceError('switch (x) {case 3:let x;break;default:if (x === undefined) {return "ponies";}}');
|
||||
isReferenceError('let x = function() {} ? x() : function() {}');
|
||||
isReferenceError('(function() { let x = (function() { return x }()); }())');
|
||||
isReferenceError('var sum = 0;for (let x = x, y = 10; x < 4; ++x) {sum += x;}return sum;');
|
||||
isReferenceError('var sum = 0;for (let x = x; x < 4; ++x) {sum += x;}return x;');
|
||||
isReferenceError('var sum = 0;for (let x = eval("x"); x < 4; ++x) {sum += x;}return sum;');
|
||||
isReferenceError('var sum = 0;for (let x = x; eval("x") < 4; ++x) {sum += eval("x");}return sum;');
|
||||
isReferenceError('var sum = 0;for (let x = eval("x"); eval("x") < 4; ++x) {sum += eval("x");}return sum;');
|
||||
isReferenceError('for (let x = eval("throw x");;) {}');
|
||||
isReferenceError('for (let x = x + "s"; eval("throw x");) {}');
|
||||
|
||||
// redecl with function statements
|
||||
isParseError('let a; function a() {}');
|
||||
|
2
js/src/jit-test/tests/modules/bug-1219408.js
Normal file
2
js/src/jit-test/tests/modules/bug-1219408.js
Normal file
@ -0,0 +1,2 @@
|
||||
// |jit-test| error: Error
|
||||
parseModule("").evaluation();
|
@ -9299,49 +9299,6 @@ CodeGenerator::visitAtomicIsLockFree(LAtomicIsLockFree* lir)
|
||||
masm.bind(&Ldone);
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir)
|
||||
{
|
||||
Register elements = ToRegister(lir->elements());
|
||||
AnyRegister output = ToAnyRegister(lir->output());
|
||||
Register temp = lir->temp()->isBogusTemp() ? InvalidReg : ToRegister(lir->temp());
|
||||
|
||||
Register oldval = ToRegister(lir->oldval());
|
||||
Register newval = ToRegister(lir->newval());
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
int width = Scalar::byteSize(arrayType);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest(elements, ToInt32(lir->index()) * width);
|
||||
masm.compareExchangeToTypedIntArray(arrayType, dest, oldval, newval, temp, output);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()), ScaleFromElemWidth(width));
|
||||
masm.compareExchangeToTypedIntArray(arrayType, dest, oldval, newval, temp, output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitAtomicExchangeTypedArrayElement(LAtomicExchangeTypedArrayElement* lir)
|
||||
{
|
||||
Register elements = ToRegister(lir->elements());
|
||||
AnyRegister output = ToAnyRegister(lir->output());
|
||||
Register temp = lir->temp()->isBogusTemp() ? InvalidReg : ToRegister(lir->temp());
|
||||
|
||||
Register value = ToRegister(lir->value());
|
||||
|
||||
Scalar::Type arrayType = lir->mir()->arrayType();
|
||||
int width = Scalar::byteSize(arrayType);
|
||||
|
||||
if (lir->index()->isConstant()) {
|
||||
Address dest(elements, ToInt32(lir->index()) * width);
|
||||
masm.atomicExchangeToTypedIntArray(arrayType, dest, value, temp, output);
|
||||
} else {
|
||||
BaseIndex dest(elements, ToRegister(lir->index()), ScaleFromElemWidth(width));
|
||||
masm.atomicExchangeToTypedIntArray(arrayType, dest, value, temp, output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::visitClampIToUint8(LClampIToUint8* lir)
|
||||
{
|
||||
|
@ -286,8 +286,6 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
void visitStoreUnboxedScalar(LStoreUnboxedScalar* lir);
|
||||
void visitStoreTypedArrayElementHole(LStoreTypedArrayElementHole* lir);
|
||||
void visitAtomicIsLockFree(LAtomicIsLockFree* lir);
|
||||
void visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement* lir);
|
||||
void visitAtomicExchangeTypedArrayElement(LAtomicExchangeTypedArrayElement* lir);
|
||||
void visitClampIToUint8(LClampIToUint8* lir);
|
||||
void visitClampDToUint8(LClampDToUint8* lir);
|
||||
void visitClampVToUint8(LClampVToUint8* lir);
|
||||
|
@ -11869,6 +11869,11 @@ IonBuilder::getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* na
|
||||
{
|
||||
// See the comment in tryInnerizeWindow for how this works.
|
||||
|
||||
// Note that it's important that we do this _before_ we'd try to
|
||||
// do the optimizations below on obj normally, since some of those
|
||||
// optimizations have fallback paths that are slower than the path
|
||||
// we'd produce here.
|
||||
|
||||
MOZ_ASSERT(*emitted == false);
|
||||
|
||||
MDefinition* inner = tryInnerizeWindow(obj);
|
||||
@ -11876,15 +11881,6 @@ IonBuilder::getPropTryInnerize(bool* emitted, MDefinition* obj, PropertyName* na
|
||||
return true;
|
||||
|
||||
if (!forceInlineCaches()) {
|
||||
// Note: the Baseline ICs don't know about this optimization, so it's
|
||||
// possible the global property's HeapTypeSet has not been initialized
|
||||
// yet. In this case we'll fall back to getPropTryCache for now.
|
||||
|
||||
// Note that it's important that we do this _before_ we'd try to
|
||||
// do the optimizations below on obj normally, since some of those
|
||||
// optimizations have fallback paths that are slower than the path
|
||||
// we'd produce here.
|
||||
|
||||
trackOptimizationAttempt(TrackedStrategy::GetProp_Constant);
|
||||
if (!getPropTryConstant(emitted, inner, NameToId(name), types) || *emitted)
|
||||
return *emitted;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user