mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Merge m-c to fx-team. a=merge
This commit is contained in:
commit
75cd780807
@ -225,7 +225,7 @@ DocAccessibleChild::RecvTextSubstring(const uint64_t& aID,
|
|||||||
bool
|
bool
|
||||||
DocAccessibleChild::RecvGetTextAfterOffset(const uint64_t& aID,
|
DocAccessibleChild::RecvGetTextAfterOffset(const uint64_t& aID,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const AccessibleTextBoundary& aBoundaryType,
|
const int32_t& aBoundaryType,
|
||||||
nsString* aText,
|
nsString* aText,
|
||||||
int32_t* aStartOffset,
|
int32_t* aStartOffset,
|
||||||
int32_t* aEndOffset)
|
int32_t* aEndOffset)
|
||||||
@ -243,7 +243,7 @@ DocAccessibleChild::RecvGetTextAfterOffset(const uint64_t& aID,
|
|||||||
bool
|
bool
|
||||||
DocAccessibleChild::RecvGetTextAtOffset(const uint64_t& aID,
|
DocAccessibleChild::RecvGetTextAtOffset(const uint64_t& aID,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const AccessibleTextBoundary& aBoundaryType,
|
const int32_t& aBoundaryType,
|
||||||
nsString* aText,
|
nsString* aText,
|
||||||
int32_t* aStartOffset,
|
int32_t* aStartOffset,
|
||||||
int32_t* aEndOffset)
|
int32_t* aEndOffset)
|
||||||
@ -261,7 +261,7 @@ DocAccessibleChild::RecvGetTextAtOffset(const uint64_t& aID,
|
|||||||
bool
|
bool
|
||||||
DocAccessibleChild::RecvGetTextBeforeOffset(const uint64_t& aID,
|
DocAccessibleChild::RecvGetTextBeforeOffset(const uint64_t& aID,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const AccessibleTextBoundary& aBoundaryType,
|
const int32_t& aBoundaryType,
|
||||||
nsString* aText,
|
nsString* aText,
|
||||||
int32_t* aStartOffset,
|
int32_t* aStartOffset,
|
||||||
int32_t* aEndOffset)
|
int32_t* aEndOffset)
|
||||||
|
@ -70,17 +70,17 @@ public:
|
|||||||
|
|
||||||
virtual bool RecvGetTextAfterOffset(const uint64_t& aID,
|
virtual bool RecvGetTextAfterOffset(const uint64_t& aID,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const AccessibleTextBoundary& aBoundaryType,
|
const int32_t& aBoundaryType,
|
||||||
nsString* aText, int32_t* aStartOffset,
|
nsString* aText, int32_t* aStartOffset,
|
||||||
int32_t* aEndOffset) MOZ_OVERRIDE;
|
int32_t* aEndOffset) MOZ_OVERRIDE;
|
||||||
virtual bool RecvGetTextAtOffset(const uint64_t& aID,
|
virtual bool RecvGetTextAtOffset(const uint64_t& aID,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const AccessibleTextBoundary& aBoundaryType,
|
const int32_t& aBoundaryType,
|
||||||
nsString* aText, int32_t* aStartOffset,
|
nsString* aText, int32_t* aStartOffset,
|
||||||
int32_t* aEndOffset) MOZ_OVERRIDE;
|
int32_t* aEndOffset) MOZ_OVERRIDE;
|
||||||
virtual bool RecvGetTextBeforeOffset(const uint64_t& aID,
|
virtual bool RecvGetTextBeforeOffset(const uint64_t& aID,
|
||||||
const int32_t& aOffset,
|
const int32_t& aOffset,
|
||||||
const AccessibleTextBoundary& aBoundaryType,
|
const int32_t& aBoundaryType,
|
||||||
nsString* aText, int32_t* aStartOffset,
|
nsString* aText, int32_t* aStartOffset,
|
||||||
int32_t* aEndOffset) MOZ_OVERRIDE;
|
int32_t* aEndOffset) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
include protocol PContent;
|
include protocol PContent;
|
||||||
|
|
||||||
using AccessibleTextBoundary from "nsIAccessibleText.h";
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace a11y {
|
namespace a11y {
|
||||||
|
|
||||||
@ -69,11 +67,11 @@ child:
|
|||||||
// TextSubstring is getText in IDL.
|
// TextSubstring is getText in IDL.
|
||||||
prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
|
prio(high) sync TextSubstring(uint64_t aID, int32_t aStartOffset, int32_t
|
||||||
aEndOffset) returns(nsString aText);
|
aEndOffset) returns(nsString aText);
|
||||||
prio(high) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, AccessibleTextBoundary aBoundaryType)
|
prio(high) sync GetTextAfterOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
|
||||||
returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
|
returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
|
||||||
prio(high) sync GetTextAtOffset(uint64_t aID, int32_t aOffset, AccessibleTextBoundary aBoundaryType)
|
prio(high) sync GetTextAtOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
|
||||||
returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
|
returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
|
||||||
prio(high) sync GetTextBeforeOffset(uint64_t aID, int32_t aOffset, AccessibleTextBoundary aBoundaryType)
|
prio(high) sync GetTextBeforeOffset(uint64_t aID, int32_t aOffset, int32_t aBoundaryType)
|
||||||
returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
|
returns(nsString aText, int32_t aStartOffset, int32_t aEndOffset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -688,6 +688,9 @@ pref("ui.useOverlayScrollbars", 1);
|
|||||||
pref("ui.scrollbarFadeBeginDelay", 450);
|
pref("ui.scrollbarFadeBeginDelay", 450);
|
||||||
pref("ui.scrollbarFadeDuration", 200);
|
pref("ui.scrollbarFadeDuration", 200);
|
||||||
|
|
||||||
|
// Scrollbar position follows the document `dir` attribute
|
||||||
|
pref("layout.scrollbar.side", 1);
|
||||||
|
|
||||||
// Enable the ProcessPriorityManager, and give processes with no visible
|
// Enable the ProcessPriorityManager, and give processes with no visible
|
||||||
// documents a 1s grace period before they're eligible to be marked as
|
// documents a 1s grace period before they're eligible to be marked as
|
||||||
// background. Background processes that are perceivable due to playing
|
// background. Background processes that are perceivable due to playing
|
||||||
@ -1114,10 +1117,8 @@ pref("dom.requestSync.enabled", true);
|
|||||||
pref("gfx.vsync.hw-vsync.enabled", true);
|
pref("gfx.vsync.hw-vsync.enabled", true);
|
||||||
pref("gfx.vsync.compositor", true);
|
pref("gfx.vsync.compositor", true);
|
||||||
pref("gfx.touch.resample", true);
|
pref("gfx.touch.resample", true);
|
||||||
pref("gfx.vsync.refreshdriver", true);
|
|
||||||
#else
|
#else
|
||||||
pref("gfx.vsync.hw-vsync.enabled", false);
|
pref("gfx.vsync.hw-vsync.enabled", false);
|
||||||
pref("gfx.vsync.compositor", false);
|
pref("gfx.vsync.compositor", false);
|
||||||
pref("gfx.touch.resample", false);
|
pref("gfx.touch.resample", false);
|
||||||
pref("gfx.vsync.refreshdriver", false);
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,6 +36,13 @@ xul|scrollbar[orient="vertical"] {
|
|||||||
max-width: 8px;
|
max-width: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* workaround for bug 1119057: as -moz-margin-start may not work as expected,
|
||||||
|
* force a right margin value in RTL mode. */
|
||||||
|
[dir="rtl"] xul|scrollbar[root="true"][orient="vertical"] {
|
||||||
|
-moz-margin-start: unset;
|
||||||
|
margin-right: -8px;
|
||||||
|
}
|
||||||
|
|
||||||
xul|scrollbar[orient="vertical"] xul|thumb {
|
xul|scrollbar[orient="vertical"] xul|thumb {
|
||||||
max-width: 6px !important;
|
max-width: 6px !important;
|
||||||
min-width: 6px !important;
|
min-width: 6px !important;
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
|
@ -19,12 +19,12 @@
|
|||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eb1795a9002eb142ac58c8d68f8f4ba094af07ca"/>
|
||||||
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
|
<project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="2c31ac3a31a340b40ecd9c291df9b9613d3afa72"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
<!-- Stock Android things -->
|
<!-- Stock Android things -->
|
||||||
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
<project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
<project name="platform_build" path="build" remote="b2g" revision="cdaa0a4ac28c781709df8c318ed079e9e475503a">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"git": {
|
"git": {
|
||||||
"git_revision": "4f39e48b95fa00c8669b8707447542024bb55432",
|
"git_revision": "82f286f10a41aab84a0796c89fbefe67b179994b",
|
||||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "e0816d2581cdc2d0581f625c06811128c87c0c48",
|
"revision": "066f0e84321a010700467d1814ee0048dca7e5e1",
|
||||||
"repo_path": "integration/gaia-central"
|
"repo_path": "integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="8d0d11d190ccc50d7d66009bcc896ad4b42d3f0d"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
<project name="platform_build" path="build" remote="b2g" revision="7f2ee9f4cb926684883fc2a2e407045fd9db2199">
|
<project name="platform_build" path="build" remote="b2g" revision="7f2ee9f4cb926684883fc2a2e407045fd9db2199">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="4f39e48b95fa00c8669b8707447542024bb55432"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="82f286f10a41aab84a0796c89fbefe67b179994b"/>
|
||||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2262d4a77d4f46ab230fd747bb91e9b77bad36cb"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="fe893bb760a3bb64375f62fdf4762a58c59df9ef"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||||
|
@ -1809,8 +1809,8 @@ pref("experiments.manifest.uri", "https://telemetry-experiment.cdn.mozilla.net/m
|
|||||||
// Whether experiments are supported by the current application profile.
|
// Whether experiments are supported by the current application profile.
|
||||||
pref("experiments.supported", true);
|
pref("experiments.supported", true);
|
||||||
|
|
||||||
// Enable the OpenH264 plugin support in the addon manager.
|
// Enable GMP support in the addon manager.
|
||||||
pref("media.gmp-gmpopenh264.provider.enabled", true);
|
pref("media.gmp-provider.enabled", true);
|
||||||
|
|
||||||
pref("browser.apps.URL", "https://marketplace.firefox.com/discovery/");
|
pref("browser.apps.URL", "https://marketplace.firefox.com/discovery/");
|
||||||
|
|
||||||
|
@ -69,9 +69,16 @@ CallProgressSocket.prototype = {
|
|||||||
let uri = Services.io.newURI(this._progressUrl, null, null);
|
let uri = Services.io.newURI(this._progressUrl, null, null);
|
||||||
|
|
||||||
// Allow _websocket to be set for testing.
|
// Allow _websocket to be set for testing.
|
||||||
this._websocket = this._websocket ||
|
if (!this._websocket) {
|
||||||
Cc["@mozilla.org/network/protocol;1?name=" + uri.scheme]
|
this._websocket = Cc["@mozilla.org/network/protocol;1?name=" + uri.scheme]
|
||||||
.createInstance(Ci.nsIWebSocketChannel);
|
.createInstance(Ci.nsIWebSocketChannel);
|
||||||
|
|
||||||
|
this._websocket.initLoadInfo(null, // aLoadingNode
|
||||||
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||||
|
null, // aTriggeringPrincipal
|
||||||
|
Ci.nsILoadInfo.SEC_NORMAL,
|
||||||
|
Ci.nsIContentPolicy.TYPE_WEBSOCKET);
|
||||||
|
}
|
||||||
|
|
||||||
this._websocket.asyncOpen(uri, this._progressUrl, this, null);
|
this._websocket.asyncOpen(uri, this._progressUrl, this, null);
|
||||||
},
|
},
|
||||||
|
@ -61,6 +61,11 @@ PushSocket.prototype = {
|
|||||||
if (!this._websocket) {
|
if (!this._websocket) {
|
||||||
this._websocket = Cc["@mozilla.org/network/protocol;1?name=wss"]
|
this._websocket = Cc["@mozilla.org/network/protocol;1?name=wss"]
|
||||||
.createInstance(Ci.nsIWebSocketChannel);
|
.createInstance(Ci.nsIWebSocketChannel);
|
||||||
|
this._websocket.initLoadInfo(null, // aLoadingNode
|
||||||
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||||
|
null, // aTriggeringPrincipal
|
||||||
|
Ci.nsILoadInfo.SEC_NORMAL,
|
||||||
|
Ci.nsIContentPolicy.TYPE_WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
let uri = Services.io.newURI(pushUri, null, null);
|
let uri = Services.io.newURI(pushUri, null, null);
|
||||||
|
@ -20,6 +20,7 @@ namespace mozilla {
|
|||||||
namespace net {
|
namespace net {
|
||||||
class HttpChannelParent;
|
class HttpChannelParent;
|
||||||
class FTPChannelParent;
|
class FTPChannelParent;
|
||||||
|
class WebSocketChannelParent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +52,7 @@ private:
|
|||||||
|
|
||||||
friend class net::HttpChannelParent;
|
friend class net::HttpChannelParent;
|
||||||
friend class net::FTPChannelParent;
|
friend class net::FTPChannelParent;
|
||||||
|
friend class net::WebSocketChannelParent;
|
||||||
|
|
||||||
~LoadInfo();
|
~LoadInfo();
|
||||||
|
|
||||||
|
@ -590,7 +590,16 @@ SendPing(void* aClosure, nsIContent* aContent, nsIURI* aURI,
|
|||||||
nsIDocument* doc = aContent->OwnerDoc();
|
nsIDocument* doc = aContent->OwnerDoc();
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> chan;
|
nsCOMPtr<nsIChannel> chan;
|
||||||
aIOService->NewChannelFromURI(aURI, getter_AddRefs(chan));
|
NS_NewChannel(getter_AddRefs(chan),
|
||||||
|
aURI,
|
||||||
|
doc,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_PING,
|
||||||
|
nullptr, // aLoadGroup
|
||||||
|
nullptr, // aCallbacks
|
||||||
|
nsIRequest::LOAD_NORMAL, // aLoadFlags,
|
||||||
|
aIOService);
|
||||||
|
|
||||||
if (!chan) {
|
if (!chan) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,7 @@ public:
|
|||||||
, mHasFeatureRegistered(false)
|
, mHasFeatureRegistered(false)
|
||||||
#endif
|
#endif
|
||||||
, mIsMainThread(true)
|
, mIsMainThread(true)
|
||||||
|
, mMutex("WebSocketImpl::mMutex")
|
||||||
, mWorkerShuttingDown(false)
|
, mWorkerShuttingDown(false)
|
||||||
{
|
{
|
||||||
if (!NS_IsMainThread()) {
|
if (!NS_IsMainThread()) {
|
||||||
@ -222,6 +223,9 @@ public:
|
|||||||
nsWeakPtr mWeakLoadGroup;
|
nsWeakPtr mWeakLoadGroup;
|
||||||
|
|
||||||
bool mIsMainThread;
|
bool mIsMainThread;
|
||||||
|
|
||||||
|
// This mutex protects mWorkerShuttingDown.
|
||||||
|
mozilla::Mutex mMutex;
|
||||||
bool mWorkerShuttingDown;
|
bool mWorkerShuttingDown;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -422,7 +426,14 @@ public:
|
|||||||
|
|
||||||
~MaybeDisconnect()
|
~MaybeDisconnect()
|
||||||
{
|
{
|
||||||
if (mImpl->mWorkerShuttingDown) {
|
bool toDisconnect = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mImpl->mMutex);
|
||||||
|
toDisconnect = mImpl->mWorkerShuttingDown;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toDisconnect) {
|
||||||
mImpl->Disconnect();
|
mImpl->Disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -886,7 +897,7 @@ WebSocket::WebSocket(nsPIDOMWindow* aOwnerWindow)
|
|||||||
, mCheckMustKeepAlive(true)
|
, mCheckMustKeepAlive(true)
|
||||||
, mOutgoingBufferedAmount(0)
|
, mOutgoingBufferedAmount(0)
|
||||||
, mBinaryType(dom::BinaryType::Blob)
|
, mBinaryType(dom::BinaryType::Blob)
|
||||||
, mMutex("WebSocketImpl::mMutex")
|
, mMutex("WebSocket::mMutex")
|
||||||
, mReadyState(CONNECTING)
|
, mReadyState(CONNECTING)
|
||||||
{
|
{
|
||||||
mImpl = new WebSocketImpl(this);
|
mImpl = new WebSocketImpl(this);
|
||||||
@ -1563,15 +1574,11 @@ WebSocketImpl::InitializeConnection()
|
|||||||
// are not thread-safe.
|
// are not thread-safe.
|
||||||
mOriginDocument = nullptr;
|
mOriginDocument = nullptr;
|
||||||
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
wsChannel->InitLoadInfo(doc ? doc->AsDOMNode() : nullptr,
|
||||||
new LoadInfo(doc ?
|
doc ? doc->NodePrincipal() : mPrincipal.get(),
|
||||||
doc->NodePrincipal() : mPrincipal.get(),
|
mPrincipal,
|
||||||
mPrincipal,
|
nsILoadInfo::SEC_NORMAL,
|
||||||
doc,
|
nsIContentPolicy::TYPE_WEBSOCKET);
|
||||||
nsILoadInfo::SEC_NORMAL,
|
|
||||||
nsIContentPolicy::TYPE_WEBSOCKET);
|
|
||||||
rv = wsChannel->SetLoadInfo(loadInfo);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
if (!mRequestedProtocolList.IsEmpty()) {
|
if (!mRequestedProtocolList.IsEmpty()) {
|
||||||
rv = wsChannel->SetProtocol(mRequestedProtocolList);
|
rv = wsChannel->SetProtocol(mRequestedProtocolList);
|
||||||
@ -1982,7 +1989,11 @@ public:
|
|||||||
MOZ_ASSERT(aStatus > workers::Running);
|
MOZ_ASSERT(aStatus > workers::Running);
|
||||||
|
|
||||||
if (aStatus >= Canceling) {
|
if (aStatus >= Canceling) {
|
||||||
mWebSocketImpl->mWorkerShuttingDown = true;
|
{
|
||||||
|
MutexAutoLock lock(mWebSocketImpl->mMutex);
|
||||||
|
mWebSocketImpl->mWorkerShuttingDown = true;
|
||||||
|
}
|
||||||
|
|
||||||
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1991,7 +2002,11 @@ public:
|
|||||||
|
|
||||||
bool Suspend(JSContext* aCx) MOZ_OVERRIDE
|
bool Suspend(JSContext* aCx) MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
mWebSocketImpl->mWorkerShuttingDown = true;
|
{
|
||||||
|
MutexAutoLock lock(mWebSocketImpl->mMutex);
|
||||||
|
mWebSocketImpl->mWorkerShuttingDown = true;
|
||||||
|
}
|
||||||
|
|
||||||
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
mWebSocketImpl->CloseConnection(nsIWebSocketChannel::CLOSE_GOING_AWAY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2551,9 +2566,13 @@ namespace {
|
|||||||
|
|
||||||
class WorkerRunnableDispatcher MOZ_FINAL : public WorkerRunnable
|
class WorkerRunnableDispatcher MOZ_FINAL : public WorkerRunnable
|
||||||
{
|
{
|
||||||
|
nsRefPtr<WebSocketImpl> mWebSocketImpl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WorkerRunnableDispatcher(WorkerPrivate* aWorkerPrivate, nsIRunnable* aEvent)
|
WorkerRunnableDispatcher(WebSocketImpl* aImpl, WorkerPrivate* aWorkerPrivate,
|
||||||
|
nsIRunnable* aEvent)
|
||||||
: WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
|
: WorkerRunnable(aWorkerPrivate, WorkerThreadUnchangedBusyCount)
|
||||||
|
, mWebSocketImpl(aImpl)
|
||||||
, mEvent(aEvent)
|
, mEvent(aEvent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -2561,6 +2580,13 @@ public:
|
|||||||
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||||
{
|
{
|
||||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||||
|
|
||||||
|
// No messages when disconnected.
|
||||||
|
if (mWebSocketImpl->mDisconnectingOrDisconnected) {
|
||||||
|
NS_WARNING("Dispatching a WebSocket event after the disconnection!");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
||||||
return !NS_FAILED(mEvent->Run());
|
return !NS_FAILED(mEvent->Run());
|
||||||
}
|
}
|
||||||
@ -2596,12 +2622,12 @@ WebSocketImpl::Dispatch(nsIRunnable* aEvent, uint32_t aFlags)
|
|||||||
return NS_DispatchToMainThread(aEvent);
|
return NS_DispatchToMainThread(aEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No messages when disconnected.
|
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
|
||||||
if (mDisconnectingOrDisconnected) {
|
// runnable.
|
||||||
NS_WARNING("Dispatching a WebSocket event after the disconnection!");
|
nsRefPtr<WorkerRunnableDispatcher> event =
|
||||||
return NS_OK;
|
new WorkerRunnableDispatcher(this, mWorkerPrivate, aEvent);
|
||||||
}
|
|
||||||
|
|
||||||
|
MutexAutoLock lock(mMutex);
|
||||||
if (mWorkerShuttingDown) {
|
if (mWorkerShuttingDown) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@ -2612,10 +2638,6 @@ WebSocketImpl::Dispatch(nsIRunnable* aEvent, uint32_t aFlags)
|
|||||||
MOZ_ASSERT(HasFeatureRegistered());
|
MOZ_ASSERT(HasFeatureRegistered());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If the target is a worker, we have to use a custom WorkerRunnableDispatcher
|
|
||||||
// runnable.
|
|
||||||
nsRefPtr<WorkerRunnableDispatcher> event =
|
|
||||||
new WorkerRunnableDispatcher(mWorkerPrivate, aEvent);
|
|
||||||
if (!event->Dispatch(nullptr)) {
|
if (!event->Dispatch(nullptr)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -1667,14 +1667,30 @@ BluetoothServiceBluedroid::BondStateChangedNotification(
|
|||||||
NS_LITERAL_STRING(KEY_ADAPTER),
|
NS_LITERAL_STRING(KEY_ADAPTER),
|
||||||
BluetoothValue(propertiesArray)));
|
BluetoothValue(propertiesArray)));
|
||||||
|
|
||||||
if (bonded && !sBondingRunnableArray.IsEmpty()) {
|
if (aStatus == STATUS_SUCCESS) {
|
||||||
DispatchBluetoothReply(sBondingRunnableArray[0],
|
// Resolve existing pair/unpair promise when pair/unpair succeeded
|
||||||
BluetoothValue(true), EmptyString());
|
if (bonded && !sBondingRunnableArray.IsEmpty()) {
|
||||||
sBondingRunnableArray.RemoveElementAt(0);
|
DispatchBluetoothReply(sBondingRunnableArray[0],
|
||||||
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
|
BluetoothValue(true), EmptyString());
|
||||||
DispatchBluetoothReply(sUnbondingRunnableArray[0],
|
sBondingRunnableArray.RemoveElementAt(0);
|
||||||
BluetoothValue(true), EmptyString());
|
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
|
||||||
sUnbondingRunnableArray.RemoveElementAt(0);
|
DispatchBluetoothReply(sUnbondingRunnableArray[0],
|
||||||
|
BluetoothValue(true), EmptyString());
|
||||||
|
sUnbondingRunnableArray.RemoveElementAt(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Reject existing pair/unpair promise when pair/unpair failed
|
||||||
|
if (!bonded && !sBondingRunnableArray.IsEmpty()) {
|
||||||
|
DispatchBluetoothReply(sBondingRunnableArray[0],
|
||||||
|
BluetoothValue(),
|
||||||
|
NS_LITERAL_STRING("Pair Error"));
|
||||||
|
sBondingRunnableArray.RemoveElementAt(0);
|
||||||
|
} else if (bonded && !sUnbondingRunnableArray.IsEmpty()) {
|
||||||
|
DispatchBluetoothReply(sUnbondingRunnableArray[0],
|
||||||
|
BluetoothValue(),
|
||||||
|
NS_LITERAL_STRING("Unpair Error"));
|
||||||
|
sUnbondingRunnableArray.RemoveElementAt(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,5 +20,9 @@ mimetype_label=MIME Type
|
|||||||
description_label=Description
|
description_label=Description
|
||||||
suffixes_label=Suffixes
|
suffixes_label=Suffixes
|
||||||
|
|
||||||
|
# GMP Plugins
|
||||||
openH264_name=OpenH264 Video Codec provided by Cisco Systems, Inc.
|
openH264_name=OpenH264 Video Codec provided by Cisco Systems, Inc.
|
||||||
openH264_description=Play back web video and use video chats.
|
openH264_description=Play back web video and use video chats.
|
||||||
|
|
||||||
|
eme-adobe_name=Primetime Content Decryption Module provided by Adobe Systems, Incorporated
|
||||||
|
eme-adobe_description=Play back protected web video.
|
||||||
|
@ -2958,7 +2958,7 @@ MediaDecoderStateMachine::FlushDecoding()
|
|||||||
// The reader is not supposed to put any tasks to deliver samples into
|
// The reader is not supposed to put any tasks to deliver samples into
|
||||||
// the queue after this runs (unless we request another sample from it).
|
// the queue after this runs (unless we request another sample from it).
|
||||||
RefPtr<nsIRunnable> task;
|
RefPtr<nsIRunnable> task;
|
||||||
task = NS_NewRunnableMethod(mReader, &MediaDecoderReader::ResetDecode);
|
task = NS_NewRunnableMethod(this, &MediaDecoderStateMachine::ResetDecode);
|
||||||
|
|
||||||
// Wait for the ResetDecode to run and for the decoder to abort
|
// Wait for the ResetDecode to run and for the decoder to abort
|
||||||
// decoding operations and run any pending callbacks. This is
|
// decoding operations and run any pending callbacks. This is
|
||||||
@ -2979,6 +2979,25 @@ MediaDecoderStateMachine::FlushDecoding()
|
|||||||
ResetPlayback();
|
ResetPlayback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MediaDecoderStateMachine::ResetDecode()
|
||||||
|
{
|
||||||
|
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
|
||||||
|
|
||||||
|
if (!mReader) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||||
|
if (mWaitingForDecoderSeek && !mCancelingSeek) {
|
||||||
|
mReader->CancelSeek();
|
||||||
|
mCancelingSeek = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mReader->ResetDecode();
|
||||||
|
}
|
||||||
|
|
||||||
void MediaDecoderStateMachine::RenderVideoFrame(VideoData* aData,
|
void MediaDecoderStateMachine::RenderVideoFrame(VideoData* aData,
|
||||||
TimeStamp aTarget)
|
TimeStamp aTarget)
|
||||||
{
|
{
|
||||||
|
@ -422,6 +422,9 @@ public:
|
|||||||
WaitRequestRef(aRejection.mType).Complete();
|
WaitRequestRef(aRejection.mType).Complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resets all state related to decoding, emptying all buffers etc.
|
||||||
|
void ResetDecode();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void AcquireMonitorAndInvokeDecodeError();
|
void AcquireMonitorAndInvokeDecodeError();
|
||||||
|
|
||||||
|
@ -805,9 +805,8 @@ RTCPeerConnection.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
removeTrack: function(sender) {
|
removeTrack: function(sender) {
|
||||||
// Bug 844295: Not implementing this functionality.
|
this._checkClosed();
|
||||||
throw new this._win.DOMException("removeTrack not yet implemented",
|
this._impl.removeTrack(sender.track);
|
||||||
"NotSupportedError");
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_replaceTrack: function(sender, withTrack) {
|
_replaceTrack: function(sender, withTrack) {
|
||||||
@ -1115,6 +1114,10 @@ PeerConnectionObserver.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onNegotiationNeeded: function() {
|
||||||
|
this.dispatchEvent(new this._win.Event("negotiationneeded"));
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
// This method is primarily responsible for updating iceConnectionState.
|
// This method is primarily responsible for updating iceConnectionState.
|
||||||
// This state is defined in the WebRTC specification as follows:
|
// This state is defined in the WebRTC specification as follows:
|
||||||
|
@ -121,7 +121,7 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem)
|
|||||||
if (!IsVistaOrLater()) {
|
if (!IsVistaOrLater()) {
|
||||||
return MediaKeySystemStatus::Cdm_not_supported;
|
return MediaKeySystemStatus::Cdm_not_supported;
|
||||||
}
|
}
|
||||||
if (!Preferences::GetBool("media.eme.adobe-access.enabled", false)) {
|
if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
|
||||||
return MediaKeySystemStatus::Cdm_disabled;
|
return MediaKeySystemStatus::Cdm_disabled;
|
||||||
}
|
}
|
||||||
if (!HaveGMPFor(mps,
|
if (!HaveGMPFor(mps,
|
||||||
|
@ -17,154 +17,159 @@ function getBlobContent(blob) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var commandsCreateDataChannel = [
|
||||||
|
function PC_REMOTE_EXPECT_DATA_CHANNEL(test) {
|
||||||
|
test.pcRemote.expectDataChannel();
|
||||||
|
},
|
||||||
|
|
||||||
|
function PC_LOCAL_CREATE_DATA_CHANNEL(test) {
|
||||||
|
var channel = test.pcLocal.createDataChannel({});
|
||||||
|
is(channel.binaryType, "blob", channel + " is of binary type 'blob'");
|
||||||
|
is(channel.readyState, "connecting", channel + " is in state: 'connecting'");
|
||||||
|
|
||||||
|
is(test.pcLocal.signalingState, STABLE,
|
||||||
|
"Create datachannel does not change signaling state");
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
var commandsWaitForDataChannel = [
|
||||||
|
function PC_LOCAL_VERIFY_DATA_CHANNEL_STATE(test) {
|
||||||
|
return test.pcLocal.dataChannels[0].opened;
|
||||||
|
},
|
||||||
|
|
||||||
|
function PC_REMOTE_VERIFY_DATA_CHANNEL_STATE(test) {
|
||||||
|
return test.pcRemote.nextDataChannel.then(channel => channel.opened);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
var commandsCheckDataChannel = [
|
||||||
|
function SEND_MESSAGE(test) {
|
||||||
|
var message = "Lorem ipsum dolor sit amet";
|
||||||
|
|
||||||
|
return test.send(message).then(result => {
|
||||||
|
is(result.data, message, "Message correctly transmitted from pcLocal to pcRemote.");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function SEND_BLOB(test) {
|
||||||
|
var contents = ["At vero eos et accusam et justo duo dolores et ea rebum."];
|
||||||
|
var blob = new Blob(contents, { "type" : "text/plain" });
|
||||||
|
|
||||||
|
return test.send(blob).then(result => {
|
||||||
|
ok(result.data instanceof Blob, "Received data is of instance Blob");
|
||||||
|
is(result.data.size, blob.size, "Received data has the correct size.");
|
||||||
|
|
||||||
|
return getBlobContent(result.data);
|
||||||
|
}).then(recv_contents =>
|
||||||
|
is(recv_contents, contents, "Received data has the correct content."));
|
||||||
|
},
|
||||||
|
|
||||||
|
function CREATE_SECOND_DATA_CHANNEL(test) {
|
||||||
|
return test.createDataChannel({ }).then(result => {
|
||||||
|
var sourceChannel = result.local;
|
||||||
|
var targetChannel = result.remote;
|
||||||
|
is(sourceChannel.readyState, "open", sourceChannel + " is in state: 'open'");
|
||||||
|
is(targetChannel.readyState, "open", targetChannel + " is in state: 'open'");
|
||||||
|
|
||||||
|
is(targetChannel.binaryType, "blob", targetChannel + " is of binary type 'blob'");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL(test) {
|
||||||
|
var channels = test.pcRemote.dataChannels;
|
||||||
|
var message = "I am the Omega";
|
||||||
|
|
||||||
|
return test.send(message).then(result => {
|
||||||
|
is(channels.indexOf(result.channel), channels.length - 1, "Last channel used");
|
||||||
|
is(result.data, message, "Received message has the correct content.");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
function SEND_MESSAGE_THROUGH_FIRST_CHANNEL(test) {
|
||||||
|
var message = "Message through 1st channel";
|
||||||
|
var options = {
|
||||||
|
sourceChannel: test.pcLocal.dataChannels[0],
|
||||||
|
targetChannel: test.pcRemote.dataChannels[0]
|
||||||
|
};
|
||||||
|
|
||||||
|
return test.send(message, options).then(result => {
|
||||||
|
is(test.pcRemote.dataChannels.indexOf(result.channel), 0, "1st channel used");
|
||||||
|
is(result.data, message, "Received message has the correct content.");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
function SEND_MESSAGE_BACK_THROUGH_FIRST_CHANNEL(test) {
|
||||||
|
var message = "Return a message also through 1st channel";
|
||||||
|
var options = {
|
||||||
|
sourceChannel: test.pcRemote.dataChannels[0],
|
||||||
|
targetChannel: test.pcLocal.dataChannels[0]
|
||||||
|
};
|
||||||
|
|
||||||
|
return test.send(message, options).then(result => {
|
||||||
|
is(test.pcLocal.dataChannels.indexOf(result.channel), 0, "1st channel used");
|
||||||
|
is(result.data, message, "Return message has the correct content.");
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function CREATE_NEGOTIATED_DATA_CHANNEL(test) {
|
||||||
|
var options = {
|
||||||
|
negotiated:true,
|
||||||
|
id: 5,
|
||||||
|
protocol: "foo/bar",
|
||||||
|
ordered: false,
|
||||||
|
maxRetransmits: 500
|
||||||
|
};
|
||||||
|
return test.createDataChannel(options).then(result => {
|
||||||
|
var sourceChannel2 = result.local;
|
||||||
|
var targetChannel2 = result.remote;
|
||||||
|
is(sourceChannel2.readyState, "open", sourceChannel2 + " is in state: 'open'");
|
||||||
|
is(targetChannel2.readyState, "open", targetChannel2 + " is in state: 'open'");
|
||||||
|
|
||||||
|
is(targetChannel2.binaryType, "blob", targetChannel2 + " is of binary type 'blob'");
|
||||||
|
|
||||||
|
is(sourceChannel2.id, options.id, sourceChannel2 + " id is:" + sourceChannel2.id);
|
||||||
|
var reliable = !options.ordered ? false : (options.maxRetransmits || options.maxRetransmitTime);
|
||||||
|
is(sourceChannel2.protocol, options.protocol, sourceChannel2 + " protocol is:" + sourceChannel2.protocol);
|
||||||
|
is(sourceChannel2.reliable, reliable, sourceChannel2 + " reliable is:" + sourceChannel2.reliable);
|
||||||
|
/*
|
||||||
|
These aren't exposed by IDL yet
|
||||||
|
is(sourceChannel2.ordered, options.ordered, sourceChannel2 + " ordered is:" + sourceChannel2.ordered);
|
||||||
|
is(sourceChannel2.maxRetransmits, options.maxRetransmits, sourceChannel2 + " maxRetransmits is:" +
|
||||||
|
sourceChannel2.maxRetransmits);
|
||||||
|
is(sourceChannel2.maxRetransmitTime, options.maxRetransmitTime, sourceChannel2 + " maxRetransmitTime is:" +
|
||||||
|
sourceChannel2.maxRetransmitTime);
|
||||||
|
*/
|
||||||
|
|
||||||
|
is(targetChannel2.id, options.id, targetChannel2 + " id is:" + targetChannel2.id);
|
||||||
|
is(targetChannel2.protocol, options.protocol, targetChannel2 + " protocol is:" + targetChannel2.protocol);
|
||||||
|
is(targetChannel2.reliable, reliable, targetChannel2 + " reliable is:" + targetChannel2.reliable);
|
||||||
|
/*
|
||||||
|
These aren't exposed by IDL yet
|
||||||
|
is(targetChannel2.ordered, options.ordered, targetChannel2 + " ordered is:" + targetChannel2.ordered);
|
||||||
|
is(targetChannel2.maxRetransmits, options.maxRetransmits, targetChannel2 + " maxRetransmits is:" +
|
||||||
|
targetChannel2.maxRetransmits);
|
||||||
|
is(targetChannel2.maxRetransmitTime, options.maxRetransmitTime, targetChannel2 + " maxRetransmitTime is:" +
|
||||||
|
targetChannel2.maxRetransmitTime);
|
||||||
|
*/
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL2(test) {
|
||||||
|
var channels = test.pcRemote.dataChannels;
|
||||||
|
var message = "I am the walrus; Goo goo g'joob";
|
||||||
|
|
||||||
|
return test.send(message).then(result => {
|
||||||
|
is(channels.indexOf(result.channel), channels.length - 1, "Last channel used");
|
||||||
|
is(result.data, message, "Received message has the correct content.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
function addInitialDataChannel(chain) {
|
function addInitialDataChannel(chain) {
|
||||||
chain.insertBefore('PC_LOCAL_CREATE_OFFER', [
|
chain.insertBefore('PC_LOCAL_CREATE_OFFER', commandsCreateDataChannel);
|
||||||
function PC_REMOTE_EXPECT_DATA_CHANNEL(test) {
|
chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS', commandsWaitForDataChannel);
|
||||||
test.pcRemote.expectDataChannel();
|
|
||||||
},
|
|
||||||
|
|
||||||
function PC_LOCAL_CREATE_DATA_CHANNEL(test) {
|
|
||||||
var channel = test.pcLocal.createDataChannel({});
|
|
||||||
is(channel.binaryType, "blob", channel + " is of binary type 'blob'");
|
|
||||||
is(channel.readyState, "connecting", channel + " is in state: 'connecting'");
|
|
||||||
|
|
||||||
is(test.pcLocal.signalingState, STABLE,
|
|
||||||
"Create datachannel does not change signaling state");
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
|
|
||||||
chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS', [
|
|
||||||
function PC_LOCAL_VERIFY_DATA_CHANNEL_STATE(test) {
|
|
||||||
return test.pcLocal.dataChannels[0].opened;
|
|
||||||
},
|
|
||||||
|
|
||||||
function PC_REMOTE_VERIFY_DATA_CHANNEL_STATE(test) {
|
|
||||||
return test.pcRemote.nextDataChannel.then(channel => channel.opened);
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
chain.removeAfter('PC_REMOTE_CHECK_ICE_CONNECTIONS');
|
chain.removeAfter('PC_REMOTE_CHECK_ICE_CONNECTIONS');
|
||||||
chain.append([
|
chain.append(commandsCheckDataChannel);
|
||||||
function SEND_MESSAGE(test) {
|
|
||||||
var message = "Lorem ipsum dolor sit amet";
|
|
||||||
|
|
||||||
return test.send(message).then(result => {
|
|
||||||
is(result.data, message, "Message correctly transmitted from pcLocal to pcRemote.");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function SEND_BLOB(test) {
|
|
||||||
var contents = ["At vero eos et accusam et justo duo dolores et ea rebum."];
|
|
||||||
var blob = new Blob(contents, { "type" : "text/plain" });
|
|
||||||
|
|
||||||
return test.send(blob).then(result => {
|
|
||||||
ok(result.data instanceof Blob, "Received data is of instance Blob");
|
|
||||||
is(result.data.size, blob.size, "Received data has the correct size.");
|
|
||||||
|
|
||||||
return getBlobContent(result.data);
|
|
||||||
}).then(recv_contents =>
|
|
||||||
is(recv_contents, contents, "Received data has the correct content."));
|
|
||||||
},
|
|
||||||
|
|
||||||
function CREATE_SECOND_DATA_CHANNEL(test) {
|
|
||||||
return test.createDataChannel({ }).then(result => {
|
|
||||||
var sourceChannel = result.local;
|
|
||||||
var targetChannel = result.remote;
|
|
||||||
is(sourceChannel.readyState, "open", sourceChannel + " is in state: 'open'");
|
|
||||||
is(targetChannel.readyState, "open", targetChannel + " is in state: 'open'");
|
|
||||||
|
|
||||||
is(targetChannel.binaryType, "blob", targetChannel + " is of binary type 'blob'");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL(test) {
|
|
||||||
var channels = test.pcRemote.dataChannels;
|
|
||||||
var message = "I am the Omega";
|
|
||||||
|
|
||||||
return test.send(message).then(result => {
|
|
||||||
is(channels.indexOf(result.channel), channels.length - 1, "Last channel used");
|
|
||||||
is(result.data, message, "Received message has the correct content.");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
function SEND_MESSAGE_THROUGH_FIRST_CHANNEL(test) {
|
|
||||||
var message = "Message through 1st channel";
|
|
||||||
var options = {
|
|
||||||
sourceChannel: test.pcLocal.dataChannels[0],
|
|
||||||
targetChannel: test.pcRemote.dataChannels[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
return test.send(message, options).then(result => {
|
|
||||||
is(test.pcRemote.dataChannels.indexOf(result.channel), 0, "1st channel used");
|
|
||||||
is(result.data, message, "Received message has the correct content.");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
function SEND_MESSAGE_BACK_THROUGH_FIRST_CHANNEL(test) {
|
|
||||||
var message = "Return a message also through 1st channel";
|
|
||||||
var options = {
|
|
||||||
sourceChannel: test.pcRemote.dataChannels[0],
|
|
||||||
targetChannel: test.pcLocal.dataChannels[0]
|
|
||||||
};
|
|
||||||
|
|
||||||
return test.send(message, options).then(result => {
|
|
||||||
is(test.pcLocal.dataChannels.indexOf(result.channel), 0, "1st channel used");
|
|
||||||
is(result.data, message, "Return message has the correct content.");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function CREATE_NEGOTIATED_DATA_CHANNEL(test) {
|
|
||||||
var options = {
|
|
||||||
negotiated:true,
|
|
||||||
id: 5,
|
|
||||||
protocol: "foo/bar",
|
|
||||||
ordered: false,
|
|
||||||
maxRetransmits: 500
|
|
||||||
};
|
|
||||||
return test.createDataChannel(options).then(result => {
|
|
||||||
var sourceChannel2 = result.local;
|
|
||||||
var targetChannel2 = result.remote;
|
|
||||||
is(sourceChannel2.readyState, "open", sourceChannel2 + " is in state: 'open'");
|
|
||||||
is(targetChannel2.readyState, "open", targetChannel2 + " is in state: 'open'");
|
|
||||||
|
|
||||||
is(targetChannel2.binaryType, "blob", targetChannel2 + " is of binary type 'blob'");
|
|
||||||
|
|
||||||
is(sourceChannel2.id, options.id, sourceChannel2 + " id is:" + sourceChannel2.id);
|
|
||||||
var reliable = !options.ordered ? false : (options.maxRetransmits || options.maxRetransmitTime);
|
|
||||||
is(sourceChannel2.protocol, options.protocol, sourceChannel2 + " protocol is:" + sourceChannel2.protocol);
|
|
||||||
is(sourceChannel2.reliable, reliable, sourceChannel2 + " reliable is:" + sourceChannel2.reliable);
|
|
||||||
/*
|
|
||||||
These aren't exposed by IDL yet
|
|
||||||
is(sourceChannel2.ordered, options.ordered, sourceChannel2 + " ordered is:" + sourceChannel2.ordered);
|
|
||||||
is(sourceChannel2.maxRetransmits, options.maxRetransmits, sourceChannel2 + " maxRetransmits is:" +
|
|
||||||
sourceChannel2.maxRetransmits);
|
|
||||||
is(sourceChannel2.maxRetransmitTime, options.maxRetransmitTime, sourceChannel2 + " maxRetransmitTime is:" +
|
|
||||||
sourceChannel2.maxRetransmitTime);
|
|
||||||
*/
|
|
||||||
|
|
||||||
is(targetChannel2.id, options.id, targetChannel2 + " id is:" + targetChannel2.id);
|
|
||||||
is(targetChannel2.protocol, options.protocol, targetChannel2 + " protocol is:" + targetChannel2.protocol);
|
|
||||||
is(targetChannel2.reliable, reliable, targetChannel2 + " reliable is:" + targetChannel2.reliable);
|
|
||||||
/*
|
|
||||||
These aren't exposed by IDL yet
|
|
||||||
is(targetChannel2.ordered, options.ordered, targetChannel2 + " ordered is:" + targetChannel2.ordered);
|
|
||||||
is(targetChannel2.maxRetransmits, options.maxRetransmits, targetChannel2 + " maxRetransmits is:" +
|
|
||||||
targetChannel2.maxRetransmits);
|
|
||||||
is(targetChannel2.maxRetransmitTime, options.maxRetransmitTime, targetChannel2 + " maxRetransmitTime is:" +
|
|
||||||
targetChannel2.maxRetransmitTime);
|
|
||||||
*/
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
function SEND_MESSAGE_THROUGH_LAST_OPENED_CHANNEL2(test) {
|
|
||||||
var channels = test.pcRemote.dataChannels;
|
|
||||||
var message = "I am the walrus; Goo goo g'joob";
|
|
||||||
|
|
||||||
return test.send(message).then(result => {
|
|
||||||
is(channels.indexOf(result.channel), channels.length - 1, "Last channel used");
|
|
||||||
is(result.data, message, "Received message has the correct content.");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
@ -363,12 +363,19 @@ CommandChain.prototype = {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the index of the specified command in the chain.
|
* Returns the index of the specified command in the chain.
|
||||||
|
* @param {start} Optional param specifying the index at which the search will
|
||||||
|
* start. If not specified, the search starts at index 0.
|
||||||
*/
|
*/
|
||||||
indexOf: function(functionOrName) {
|
indexOf: function(functionOrName, start) {
|
||||||
|
start = start || 0;
|
||||||
if (typeof functionOrName === 'string') {
|
if (typeof functionOrName === 'string') {
|
||||||
return this.commands.findIndex(f => f.name === functionOrName);
|
var index = this.commands.slice(start).findIndex(f => f.name === functionOrName);
|
||||||
|
if (index !== -1) {
|
||||||
|
index += start;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
return this.commands.indexOf(functionOrName);
|
return this.commands.indexOf(functionOrName, start);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -379,20 +386,35 @@ CommandChain.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts the new commands before the specified command.
|
* Inserts the new commands after every occurrence of the specified command
|
||||||
*/
|
*/
|
||||||
insertBefore: function(functionOrName, commands) {
|
insertAfterEach: function(functionOrName, commands) {
|
||||||
this._insertHelper(functionOrName, commands, 0);
|
this._insertHelper(functionOrName, commands, 1, true);
|
||||||
},
|
},
|
||||||
|
|
||||||
_insertHelper: function(functionOrName, commands, delta) {
|
/**
|
||||||
var index = this.indexOf(functionOrName);
|
* Inserts the new commands before the specified command.
|
||||||
|
*/
|
||||||
|
insertBefore: function(functionOrName, commands, all, start) {
|
||||||
|
this._insertHelper(functionOrName, commands, 0, all, start);
|
||||||
|
},
|
||||||
|
|
||||||
if (index >= 0) {
|
_insertHelper: function(functionOrName, commands, delta, all, start) {
|
||||||
this.commands = [].concat(
|
var index = this.indexOf(functionOrName);
|
||||||
this.commands.slice(0, index + delta),
|
start = start || 0;
|
||||||
commands,
|
for (; index !== -1; index = this.indexOf(functionOrName, index)) {
|
||||||
this.commands.slice(index + delta));
|
if (!start) {
|
||||||
|
this.commands = [].concat(
|
||||||
|
this.commands.slice(0, index + delta),
|
||||||
|
commands,
|
||||||
|
this.commands.slice(index + delta));
|
||||||
|
if (!all) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
start -= 1;
|
||||||
|
}
|
||||||
|
index += (commands.length + 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -460,7 +482,7 @@ CommandChain.prototype = {
|
|||||||
*/
|
*/
|
||||||
filterOut: function (id_match) {
|
filterOut: function (id_match) {
|
||||||
this.commands = this.commands.filter(c => !id_match.test(c.name));
|
this.commands = this.commands.filter(c => !id_match.test(c.name));
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -150,8 +150,32 @@ skip-if = (toolkit == 'gonk' || (e10s && debug)) # b2g (Bug 1059867) or fd exhau
|
|||||||
skip-if = (toolkit == 'gonk' || (e10s && debug)) # b2g (Bug 1059867) or fd exhaustion on e10s debug intermittent (Bug 1126078)
|
skip-if = (toolkit == 'gonk' || (e10s && debug)) # b2g (Bug 1059867) or fd exhaustion on e10s debug intermittent (Bug 1126078)
|
||||||
[test_peerConnection_twoVideoStreams.html]
|
[test_peerConnection_twoVideoStreams.html]
|
||||||
skip-if = (toolkit == 'gonk' || (e10s && debug)) # b2g (Bug 1059867) or fd exhaustion on e10s debug intermittent (Bug 1126078)
|
skip-if = (toolkit == 'gonk' || (e10s && debug)) # b2g (Bug 1059867) or fd exhaustion on e10s debug intermittent (Bug 1126078)
|
||||||
# Renegotiation is not yet supported (bug 1017888)
|
[test_peerConnection_addSecondAudioStream.html]
|
||||||
#[test_peerConnection_addSecondAudioStream.html]
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_answererAddSecondAudioStream.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_removeAudioTrack.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_removeThenAddAudioTrack.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_addSecondVideoStream.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_removeVideoTrack.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_removeThenAddVideoTrack.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_addSecondAudioStreamNoBundle.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_removeThenAddAudioTrackNoBundle.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_addSecondVideoStreamNoBundle.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_removeThenAddVideoTrackNoBundle.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_addDataChannel.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
[test_peerConnection_addDataChannelNoBundle.html]
|
||||||
|
skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
|
||||||
|
|
||||||
# Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases
|
# Bug 950317: Hack for making a cleanup hook after finishing all WebRTC cases
|
||||||
[test_zmedia_cleanup.html]
|
[test_zmedia_cleanup.html]
|
||||||
|
@ -121,6 +121,12 @@ function removeVP8(sdp) {
|
|||||||
return updated_sdp;
|
return updated_sdp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var makeDefaultCommands = () => {
|
||||||
|
return [].concat(commandsPeerConnectionInitial,
|
||||||
|
commandsGetUserMedia,
|
||||||
|
commandsPeerConnectionOfferAnswer);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles tests for peer connections.
|
* This class handles tests for peer connections.
|
||||||
*
|
*
|
||||||
@ -142,7 +148,7 @@ function removeVP8(sdp) {
|
|||||||
function PeerConnectionTest(options) {
|
function PeerConnectionTest(options) {
|
||||||
// If no options are specified make it an empty object
|
// If no options are specified make it an empty object
|
||||||
options = options || { };
|
options = options || { };
|
||||||
options.commands = options.commands || commandsPeerConnection;
|
options.commands = options.commands || makeDefaultCommands();
|
||||||
options.is_local = "is_local" in options ? options.is_local : true;
|
options.is_local = "is_local" in options ? options.is_local : true;
|
||||||
options.is_remote = "is_remote" in options ? options.is_remote : true;
|
options.is_remote = "is_remote" in options ? options.is_remote : true;
|
||||||
|
|
||||||
@ -740,8 +746,6 @@ function PeerConnectionWrapper(label, configuration, h264) {
|
|||||||
|
|
||||||
this.dataChannels = [ ];
|
this.dataChannels = [ ];
|
||||||
|
|
||||||
this.addStreamCounter = {audio: 0, video: 0 };
|
|
||||||
|
|
||||||
this._local_ice_candidates = [];
|
this._local_ice_candidates = [];
|
||||||
this._remote_ice_candidates = [];
|
this._remote_ice_candidates = [];
|
||||||
this.holdIceCandidates = new Promise(r => this.releaseIceCandidates = r);
|
this.holdIceCandidates = new Promise(r => this.releaseIceCandidates = r);
|
||||||
@ -749,6 +753,16 @@ function PeerConnectionWrapper(label, configuration, h264) {
|
|||||||
this.remoteRequiresTrickleIce = false;
|
this.remoteRequiresTrickleIce = false;
|
||||||
this.localMediaElements = [];
|
this.localMediaElements = [];
|
||||||
|
|
||||||
|
this.expectedLocalTrackTypesById = {};
|
||||||
|
this.expectedRemoteTrackTypesById = {};
|
||||||
|
this.observedRemoteTrackTypesById = {};
|
||||||
|
|
||||||
|
this.disableRtpCountChecking = false;
|
||||||
|
|
||||||
|
this.negotiationNeededFired = false;
|
||||||
|
|
||||||
|
this.iceCheckingRestartExpected = false;
|
||||||
|
|
||||||
this.h264 = typeof h264 !== "undefined" ? true : false;
|
this.h264 = typeof h264 !== "undefined" ? true : false;
|
||||||
|
|
||||||
info("Creating " + this);
|
info("Creating " + this);
|
||||||
@ -769,27 +783,6 @@ function PeerConnectionWrapper(label, configuration, h264) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for native peer connection 'onaddstream' events.
|
|
||||||
*
|
|
||||||
* @param {Object} event
|
|
||||||
* Event data which includes the stream to be added
|
|
||||||
*/
|
|
||||||
this._pc.onaddstream = event => {
|
|
||||||
info(this + ": 'onaddstream' event fired for " + JSON.stringify(event.stream));
|
|
||||||
|
|
||||||
var type = '';
|
|
||||||
if (event.stream.getAudioTracks().length > 0) {
|
|
||||||
type = 'audio';
|
|
||||||
this.addStreamCounter.audio += this.countTracksInStreams('audio', [event.stream]);
|
|
||||||
}
|
|
||||||
if (event.stream.getVideoTracks().length > 0) {
|
|
||||||
type += 'video';
|
|
||||||
this.addStreamCounter.video += this.countTracksInStreams('video', [event.stream]);
|
|
||||||
}
|
|
||||||
this.attachMedia(event.stream, type, 'remote');
|
|
||||||
};
|
|
||||||
|
|
||||||
createOneShotEventWrapper(this, this._pc, 'datachannel');
|
createOneShotEventWrapper(this, this._pc, 'datachannel');
|
||||||
this._pc.addEventListener('datachannel', e => {
|
this._pc.addEventListener('datachannel', e => {
|
||||||
var wrapper = new DataChannelWrapper(e.channel, this);
|
var wrapper = new DataChannelWrapper(e.channel, this);
|
||||||
@ -797,6 +790,7 @@ function PeerConnectionWrapper(label, configuration, h264) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
createOneShotEventWrapper(this, this._pc, 'signalingstatechange');
|
createOneShotEventWrapper(this, this._pc, 'signalingstatechange');
|
||||||
|
createOneShotEventWrapper(this, this._pc, 'negotiationneeded');
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerConnectionWrapper.prototype = {
|
PeerConnectionWrapper.prototype = {
|
||||||
@ -888,6 +882,12 @@ PeerConnectionWrapper.prototype = {
|
|||||||
is(sender.track, track, "addTrack returns sender");
|
is(sender.track, track, "addTrack returns sender");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream.getTracks().forEach(track => {
|
||||||
|
ok(track.id, "track has id");
|
||||||
|
ok(track.kind, "track has kind");
|
||||||
|
this.expectedLocalTrackTypesById[track.id] = track.kind;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var element = createMediaElement(type, this.label + '_' + side + this.streams.length);
|
var element = createMediaElement(type, this.label + '_' + side + this.streams.length);
|
||||||
@ -902,6 +902,12 @@ PeerConnectionWrapper.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeSender : function(index) {
|
||||||
|
var sender = this._pc.getSenders()[index];
|
||||||
|
delete this.expectedLocalTrackTypesById[sender.track.id];
|
||||||
|
this._pc.removeTrack(sender);
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests all the media streams as specified in the constrains property.
|
* Requests all the media streams as specified in the constrains property.
|
||||||
*
|
*
|
||||||
@ -1068,6 +1074,59 @@ PeerConnectionWrapper.prototype = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a given track is expected, has not been observed yet, and
|
||||||
|
* is of the correct type. Then, moves the track from
|
||||||
|
* |expectedTrackTypesById| to |observedTrackTypesById|.
|
||||||
|
*/
|
||||||
|
checkTrackIsExpected : function(track,
|
||||||
|
expectedTrackTypesById,
|
||||||
|
observedTrackTypesById) {
|
||||||
|
ok(expectedTrackTypesById[track.id], "track id " + track.id + " was expected");
|
||||||
|
ok(!observedTrackTypesById[track.id], "track id " + track.id + " was not yet observed");
|
||||||
|
var observedKind = track.kind;
|
||||||
|
var expectedKind = expectedTrackTypesById[track.id];
|
||||||
|
is(observedKind, expectedKind,
|
||||||
|
"track id " + track.id + " was of kind " +
|
||||||
|
observedKind + ", which matches " + expectedKind);
|
||||||
|
observedTrackTypesById[track.id] = expectedTrackTypesById[track.id];
|
||||||
|
delete expectedTrackTypesById[track.id];
|
||||||
|
},
|
||||||
|
|
||||||
|
setupAddStreamEventHandler: function() {
|
||||||
|
var resolveAllAddStreamEventsDone;
|
||||||
|
|
||||||
|
// checkMediaTracks waits on this promise later on in the test.
|
||||||
|
this.allAddStreamEventsDonePromise =
|
||||||
|
new Promise(resolve => resolveAllAddStreamEventsDone = resolve);
|
||||||
|
|
||||||
|
this._pc.addEventListener('addstream', event => {
|
||||||
|
info(this + ": 'onaddstream' event fired for " + JSON.stringify(event.stream));
|
||||||
|
|
||||||
|
// TODO(bug 1130185): We need to handle addtrack events once we start
|
||||||
|
// testing addTrack on pre-existing streams.
|
||||||
|
|
||||||
|
event.stream.getTracks().forEach(track => {
|
||||||
|
this.checkTrackIsExpected(track,
|
||||||
|
this.expectedRemoteTrackTypesById,
|
||||||
|
this.observedRemoteTrackTypesById);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (Object.keys(this.expectedRemoteTrackTypesById).length === 0) {
|
||||||
|
resolveAllAddStreamEventsDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = '';
|
||||||
|
if (event.stream.getAudioTracks().length > 0) {
|
||||||
|
type = 'audio';
|
||||||
|
}
|
||||||
|
if (event.stream.getVideoTracks().length > 0) {
|
||||||
|
type += 'video';
|
||||||
|
}
|
||||||
|
this.attachMedia(event.stream, type, 'remote');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Either adds a given ICE candidate right away or stores it to be added
|
* Either adds a given ICE candidate right away or stores it to be added
|
||||||
* later, depending on the state of the PeerConnection.
|
* later, depending on the state of the PeerConnection.
|
||||||
@ -1148,7 +1207,14 @@ PeerConnectionWrapper.prototype = {
|
|||||||
var newstate = this._pc.iceConnectionState;
|
var newstate = this._pc.iceConnectionState;
|
||||||
var oldstate = this.iceConnectionLog[this.iceConnectionLog.length - 1]
|
var oldstate = this.iceConnectionLog[this.iceConnectionLog.length - 1]
|
||||||
if (Object.keys(iceStateTransitions).indexOf(oldstate) != -1) {
|
if (Object.keys(iceStateTransitions).indexOf(oldstate) != -1) {
|
||||||
ok(iceStateTransitions[oldstate].indexOf(newstate) != -1, this + ": legal ICE state transition from " + oldstate + " to " + newstate);
|
if (this.iceCheckingRestartExpected) {
|
||||||
|
is(newstate, "checking",
|
||||||
|
"iceconnectionstate event \'" + newstate +
|
||||||
|
"\' matches expected state \'checking\'");
|
||||||
|
this.iceCheckingRestartExpected = false;
|
||||||
|
} else {
|
||||||
|
ok(iceStateTransitions[oldstate].indexOf(newstate) != -1, this + ": legal ICE state transition from " + oldstate + " to " + newstate);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ok(false, this + ": old ICE state " + oldstate + " missing in ICE transition array");
|
ok(false, this + ": old ICE state " + oldstate + " missing in ICE transition array");
|
||||||
}
|
}
|
||||||
@ -1284,23 +1350,25 @@ PeerConnectionWrapper.prototype = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
checkLocalMediaTracks : function() {
|
||||||
* Counts the amount of tracks of the given type in a set of streams.
|
var observedLocalTrackTypesById = {};
|
||||||
*
|
// We do not want to empty out this.expectedLocalTrackTypesById, so make a
|
||||||
* @param type audio|video
|
// copy.
|
||||||
* @param streams
|
var expectedLocalTrackTypesById =
|
||||||
* An array of streams (as returned by getLocalStreams()) to be
|
JSON.parse(JSON.stringify((this.expectedLocalTrackTypesById)));
|
||||||
* examined.
|
info(this + " Checking local tracks " +
|
||||||
*/
|
JSON.stringify(expectedLocalTrackTypesById));
|
||||||
countTracksInStreams: function(type, streams) {
|
this._pc.getLocalStreams().forEach(stream => {
|
||||||
if (!Array.isArray(streams)) {
|
stream.getTracks().forEach(track => {
|
||||||
return 0;
|
this.checkTrackIsExpected(track,
|
||||||
}
|
expectedLocalTrackTypesById,
|
||||||
var f = (type === 'video') ? "getVideoTracks" : "getAudioTracks";
|
observedLocalTrackTypesById);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return streams.reduce((count, st) => {
|
Object.keys(expectedLocalTrackTypesById).forEach(id => {
|
||||||
return count + st[f]().length;
|
ok(false, this + " local id " + id + " was observed");
|
||||||
}, 0);
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1309,42 +1377,18 @@ PeerConnectionWrapper.prototype = {
|
|||||||
* @param {object} constraints
|
* @param {object} constraints
|
||||||
* The media constraints of the remote peer connection object
|
* The media constraints of the remote peer connection object
|
||||||
*/
|
*/
|
||||||
checkMediaTracks : function(remoteConstraints) {
|
checkMediaTracks : function() {
|
||||||
var waitForExpectedTracks = type => {
|
this.checkLocalMediaTracks();
|
||||||
var outstandingCount = this.countTracksInConstraint(type, remoteConstraints);
|
|
||||||
outstandingCount -= this.addStreamCounter[type];
|
|
||||||
if (outstandingCount <= 0) {
|
|
||||||
return Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise(resolve => {
|
info(this + " Checking remote tracks " +
|
||||||
this._pc.addEventListener('addstream', e => {
|
JSON.stringify(this.expectedRemoteTrackTypesById));
|
||||||
outstandingCount -= this.countTracksInStreams(type, [e.stream]);
|
|
||||||
if (outstandingCount <= 0) {
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var checkTrackCounts = (side, streams, constraints) => {
|
// No tracks are expected
|
||||||
['audio', 'video'].forEach(type => {
|
if (Object.keys(this.expectedRemoteTrackTypesById).length === 0) {
|
||||||
var actual = this.countTracksInStreams(type, streams);
|
return;
|
||||||
var expected = this.countTracksInConstraint(type, constraints);
|
}
|
||||||
is(actual, expected, this + ' has ' + actual + ' ' +
|
|
||||||
side + ' ' + type + ' tracks');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
info(this + " checkMediaTracks() got called before onAddStream fired");
|
return timerGuard(this.allAddStreamEventsDonePromise, 60000, "onaddstream never fired");
|
||||||
var checkPromise = Promise.all([
|
|
||||||
waitForExpectedTracks('audio'),
|
|
||||||
waitForExpectedTracks('video')
|
|
||||||
]).then(() => {
|
|
||||||
checkTrackCounts('local', this._pc.getLocalStreams(), this.constraints);
|
|
||||||
checkTrackCounts('remote', this._pc.getRemoteStreams(), remoteConstraints);
|
|
||||||
});
|
|
||||||
return timerGuard(checkPromise, 60000, "onaddstream never fired");
|
|
||||||
},
|
},
|
||||||
|
|
||||||
checkMsids: function() {
|
checkMsids: function() {
|
||||||
@ -1515,10 +1559,12 @@ PeerConnectionWrapper.prototype = {
|
|||||||
if(res.type == "outboundrtp") {
|
if(res.type == "outboundrtp") {
|
||||||
ok(rem.type == "inboundrtp", "Rtcp is inbound");
|
ok(rem.type == "inboundrtp", "Rtcp is inbound");
|
||||||
ok(rem.packetsReceived !== undefined, "Rtcp packetsReceived");
|
ok(rem.packetsReceived !== undefined, "Rtcp packetsReceived");
|
||||||
ok(rem.packetsReceived <= res.packetsSent, "No more than sent");
|
|
||||||
ok(rem.packetsLost !== undefined, "Rtcp packetsLost");
|
ok(rem.packetsLost !== undefined, "Rtcp packetsLost");
|
||||||
ok(rem.bytesReceived >= rem.packetsReceived, "Rtcp bytesReceived");
|
ok(rem.bytesReceived >= rem.packetsReceived, "Rtcp bytesReceived");
|
||||||
ok(rem.bytesReceived <= res.bytesSent, "No more than sent bytes");
|
if (!this.disableRtpCountChecking) {
|
||||||
|
ok(rem.packetsReceived <= res.packetsSent, "No more than sent packets");
|
||||||
|
ok(rem.bytesReceived <= res.bytesSent, "No more than sent bytes");
|
||||||
|
}
|
||||||
ok(rem.jitter !== undefined, "Rtcp jitter");
|
ok(rem.jitter !== undefined, "Rtcp jitter");
|
||||||
ok(rem.mozRtt !== undefined, "Rtcp rtt");
|
ok(rem.mozRtt !== undefined, "Rtcp rtt");
|
||||||
ok(rem.mozRtt >= 0, "Rtcp rtt " + rem.mozRtt + " >= 0");
|
ok(rem.mozRtt >= 0, "Rtcp rtt " + rem.mozRtt + " >= 0");
|
||||||
|
@ -63,17 +63,19 @@ function dumpSdp(test) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function waitForIceConnected(test, pc) {
|
function waitForIceConnected(test, pc) {
|
||||||
if (pc.isIceConnected()) {
|
if (!pc.iceCheckingRestartExpected) {
|
||||||
info(pc + ": ICE connection state log: " + pc.iceConnectionLog);
|
if (pc.isIceConnected()) {
|
||||||
ok(true, pc + ": ICE is in connected state");
|
info(pc + ": ICE connection state log: " + pc.iceConnectionLog);
|
||||||
return Promise.resolve();
|
ok(true, pc + ": ICE is in connected state");
|
||||||
}
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
if (!pc.isIceConnectionPending()) {
|
if (!pc.isIceConnectionPending()) {
|
||||||
dumpSdp(test);
|
dumpSdp(test);
|
||||||
var details = pc + ": ICE is already in bad state: " + pc.iceConnectionState;
|
var details = pc + ": ICE is already in bad state: " + pc.iceConnectionState;
|
||||||
ok(false, details);
|
ok(false, details);
|
||||||
return Promise.reject(new Error(details));
|
return Promise.reject(new Error(details));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pc.waitForIceConnected()
|
return pc.waitForIceConnected()
|
||||||
@ -135,7 +137,9 @@ function checkTrackStats(pc, audio, outbound) {
|
|||||||
var checkAllTrackStats = pc =>
|
var checkAllTrackStats = pc =>
|
||||||
Promise.all([0, 1, 2, 3].map(i => checkTrackStats(pc, i & 1, i & 2)));
|
Promise.all([0, 1, 2, 3].map(i => checkTrackStats(pc, i & 1, i & 2)));
|
||||||
|
|
||||||
var commandsPeerConnection = [
|
// Commands run once at the beginning of each test, even when performing a
|
||||||
|
// renegotiation test.
|
||||||
|
var commandsPeerConnectionInitial = [
|
||||||
function PC_SETUP_SIGNALING_CLIENT(test) {
|
function PC_SETUP_SIGNALING_CLIENT(test) {
|
||||||
if (test.steeplechase) {
|
if (test.steeplechase) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -169,12 +173,12 @@ var commandsPeerConnection = [
|
|||||||
test.pcRemote.logSignalingState();
|
test.pcRemote.logSignalingState();
|
||||||
},
|
},
|
||||||
|
|
||||||
function PC_LOCAL_GUM(test) {
|
function PC_LOCAL_SETUP_ADDSTREAM_HANDLER(test) {
|
||||||
return test.pcLocal.getAllUserMedia(test.pcLocal.constraints);
|
test.pcLocal.setupAddStreamEventHandler();
|
||||||
},
|
},
|
||||||
|
|
||||||
function PC_REMOTE_GUM(test) {
|
function PC_REMOTE_SETUP_ADDSTREAM_HANDLER(test) {
|
||||||
return test.pcRemote.getAllUserMedia(test.pcRemote.constraints);
|
test.pcRemote.setupAddStreamEventHandler();
|
||||||
},
|
},
|
||||||
|
|
||||||
function PC_LOCAL_CHECK_INITIAL_SIGNALINGSTATE(test) {
|
function PC_LOCAL_CHECK_INITIAL_SIGNALINGSTATE(test) {
|
||||||
@ -197,6 +201,34 @@ var commandsPeerConnection = [
|
|||||||
"Initial remote ICE connection state is 'new'");
|
"Initial remote ICE connection state is 'new'");
|
||||||
},
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
var commandsGetUserMedia = [
|
||||||
|
function PC_LOCAL_GUM(test) {
|
||||||
|
return test.pcLocal.getAllUserMedia(test.pcLocal.constraints);
|
||||||
|
},
|
||||||
|
|
||||||
|
function PC_REMOTE_GUM(test) {
|
||||||
|
return test.pcRemote.getAllUserMedia(test.pcRemote.constraints);
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
var commandsBeforeRenegotiation = [
|
||||||
|
function PC_LOCAL_SETUP_NEGOTIATION_CALLBACK(test) {
|
||||||
|
test.pcLocal.onnegotiationneeded = event => {
|
||||||
|
test.pcLocal.negotiationNeededFired = true;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
var commandsAfterRenegotiation = [
|
||||||
|
function PC_LOCAL_CHECK_NEGOTIATION_CALLBACK(test) {
|
||||||
|
ok(test.pcLocal.negotiationNeededFired, "Expected negotiationneeded event");
|
||||||
|
test.pcLocal.negotiationNeededFired = false;
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
var commandsPeerConnectionOfferAnswer = [
|
||||||
function PC_LOCAL_SETUP_ICE_HANDLER(test) {
|
function PC_LOCAL_SETUP_ICE_HANDLER(test) {
|
||||||
test.pcLocal.setupIceCandidateHandler(test);
|
test.pcLocal.setupIceCandidateHandler(test);
|
||||||
if (test.steeplechase) {
|
if (test.steeplechase) {
|
||||||
@ -215,6 +247,56 @@ var commandsPeerConnection = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
function PC_LOCAL_STEEPLECHASE_SIGNAL_EXPECTED_LOCAL_TRACKS(test) {
|
||||||
|
if (test.steeplechase) {
|
||||||
|
send_message({"type": "local_expected_tracks",
|
||||||
|
"expected_tracks": test.pcLocal.expectedLocalTrackTypesById});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
function PC_REMOTE_STEEPLECHASE_SIGNAL_EXPECTED_LOCAL_TRACKS(test) {
|
||||||
|
if (test.steeplechase) {
|
||||||
|
send_message({"type": "remote_expected_tracks",
|
||||||
|
"expected_tracks": test.pcRemote.expectedLocalTrackTypesById});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
function PC_LOCAL_GET_EXPECTED_REMOTE_TRACKS(test) {
|
||||||
|
if (test.steeplechase) {
|
||||||
|
return test.getSignalingMessage("remote_expected_tracks").then(
|
||||||
|
message => {
|
||||||
|
test.pcLocal.expectedRemoteTrackTypesById = message.expected_tracks;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Deep copy, as similar to steeplechase as possible
|
||||||
|
test.pcLocal.expectedRemoteTrackTypesById =
|
||||||
|
JSON.parse(JSON.stringify((test.pcRemote.expectedLocalTrackTypesById)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove what we've already observed
|
||||||
|
Object.keys(test.pcLocal.observedRemoteTrackTypesById).forEach(id => {
|
||||||
|
delete test.pcLocal.expectedRemoteTrackTypesById[id];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
function PC_LOCAL_GET_EXPECTED_REMOTE_TRACKS(test) {
|
||||||
|
if (test.steeplechase) {
|
||||||
|
return test.getSignalingMessage("local_expected_tracks").then(
|
||||||
|
message => {
|
||||||
|
test.pcRemote.expectedRemoteTrackTypesById = message.expected_tracks;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Deep copy, as similar to steeplechase as possible
|
||||||
|
test.pcRemote.expectedRemoteTrackTypesById =
|
||||||
|
JSON.parse(JSON.stringify((test.pcLocal.expectedLocalTrackTypesById)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove what we've already observed
|
||||||
|
Object.keys(test.pcRemote.observedRemoteTrackTypesById).forEach(id => {
|
||||||
|
delete test.pcRemote.expectedRemoteTrackTypesById[id];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
function PC_LOCAL_CREATE_OFFER(test) {
|
function PC_LOCAL_CREATE_OFFER(test) {
|
||||||
return test.createOffer(test.pcLocal).then(offer => {
|
return test.createOffer(test.pcLocal).then(offer => {
|
||||||
is(test.pcLocal.signalingState, STABLE,
|
is(test.pcLocal.signalingState, STABLE,
|
||||||
@ -390,11 +472,11 @@ var commandsPeerConnection = [
|
|||||||
},
|
},
|
||||||
|
|
||||||
function PC_LOCAL_CHECK_MEDIA_TRACKS(test) {
|
function PC_LOCAL_CHECK_MEDIA_TRACKS(test) {
|
||||||
return test.pcLocal.checkMediaTracks(test._answer_constraints);
|
return test.pcLocal.checkMediaTracks();
|
||||||
},
|
},
|
||||||
|
|
||||||
function PC_REMOTE_CHECK_MEDIA_TRACKS(test) {
|
function PC_REMOTE_CHECK_MEDIA_TRACKS(test) {
|
||||||
return test.pcRemote.checkMediaTracks(test._offer_constraints);
|
return test.pcRemote.checkMediaTracks();
|
||||||
},
|
},
|
||||||
|
|
||||||
function PC_LOCAL_CHECK_MEDIA_FLOW_PRESENT(test) {
|
function PC_LOCAL_CHECK_MEDIA_FLOW_PRESENT(test) {
|
||||||
@ -468,3 +550,32 @@ var commandsPeerConnection = [
|
|||||||
return checkAllTrackStats(test.pcRemote);
|
return checkAllTrackStats(test.pcRemote);
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER(test) {
|
||||||
|
test.originalOffer.sdp = test.originalOffer.sdp.replace(
|
||||||
|
/a=group:BUNDLE .*\r\n/g,
|
||||||
|
""
|
||||||
|
);
|
||||||
|
info("Updated no bundle offer: " + JSON.stringify(test.originalOffer));
|
||||||
|
};
|
||||||
|
|
||||||
|
var addRenegotiation = (chain, commands, checks) => {
|
||||||
|
chain.append(commandsBeforeRenegotiation);
|
||||||
|
chain.append(commands);
|
||||||
|
chain.append(commandsAfterRenegotiation);
|
||||||
|
chain.append(commandsPeerConnectionOfferAnswer);
|
||||||
|
if (checks) {
|
||||||
|
chain.append(checks);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var addRenegotiationAnswerer = (chain, commands, checks) => {
|
||||||
|
chain.append(function SWAP_PC_LOCAL_PC_REMOTE(test) {
|
||||||
|
var temp = test.pcLocal;
|
||||||
|
test.pcLocal = test.pcRemote;
|
||||||
|
test.pcRemote = temp;
|
||||||
|
});
|
||||||
|
addRenegotiation(chain, commands, checks);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: add DataChannel"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
commandsCreateDataChannel,
|
||||||
|
commandsCheckDataChannel);
|
||||||
|
|
||||||
|
// Insert before the second PC_LOCAL_CHECK_MEDIA_TRACKS
|
||||||
|
test.chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS',
|
||||||
|
commandsWaitForDataChannel,
|
||||||
|
false,
|
||||||
|
1);
|
||||||
|
|
||||||
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,46 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: add DataChannel"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
commandsCreateDataChannel.concat(
|
||||||
|
[
|
||||||
|
function PC_LOCAL_EXPECT_ICE_CHECKING(test) {
|
||||||
|
test.pcLocal.iceCheckingRestartExpected = true;
|
||||||
|
},
|
||||||
|
function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
|
||||||
|
test.pcRemote.iceCheckingRestartExpected = true;
|
||||||
|
},
|
||||||
|
]
|
||||||
|
),
|
||||||
|
commandsCheckDataChannel);
|
||||||
|
|
||||||
|
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
|
||||||
|
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
|
||||||
|
|
||||||
|
// Insert before the second PC_LOCAL_CHECK_MEDIA_TRACKS
|
||||||
|
test.chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS',
|
||||||
|
commandsWaitForDataChannel,
|
||||||
|
false,
|
||||||
|
1);
|
||||||
|
|
||||||
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -7,49 +7,24 @@
|
|||||||
<pre id="test">
|
<pre id="test">
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
createHTML({
|
createHTML({
|
||||||
bug: "1091242",
|
bug: "1017888",
|
||||||
title: "Renegotiation: add second audio stream"
|
title: "Renegotiation: add second audio stream"
|
||||||
});
|
});
|
||||||
|
|
||||||
var test;
|
var test;
|
||||||
runNetworkTest(function (options) {
|
runNetworkTest(function (options) {
|
||||||
test = new PeerConnectionTest(options);
|
test = new PeerConnectionTest(options);
|
||||||
test.chain.append([
|
addRenegotiation(test.chain,
|
||||||
function PC_LOCAL_SETUP_NEGOTIATION_CALLBACK(test) {
|
[
|
||||||
test.pcLocal.onNegotiationneededFired = false;
|
function PC_LOCAL_ADD_SECOND_STREAM(test) {
|
||||||
test.pcLocal._pc.onnegotiationneeded = anEvent => {
|
test.setMediaConstraints([{audio: true}, {audio: true}],
|
||||||
info("pcLocal.onnegotiationneeded fired");
|
[{audio: true}]);
|
||||||
test.pcLocal.onNegotiationneededFired = true;
|
return test.pcLocal.getAllUserMedia([{audio: true}]);
|
||||||
};
|
},
|
||||||
},
|
]
|
||||||
function PC_LOCAL_ADD_SECOND_STREAM(test) {
|
);
|
||||||
return test.pcLocal.getAllUserMedia([{audio: true}]);
|
|
||||||
},
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
function PC_LOCAL_CREATE_NEW_OFFER(test) {
|
|
||||||
ok(test.pcLocal.onNegotiationneededFired, "onnegotiationneeded");
|
|
||||||
return test.createOffer(test.pcLocal).then(offer => {
|
|
||||||
test._new_offer = offer;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function PC_LOCAL_SET_NEW_LOCAL_DESCRIPTION(test) {
|
|
||||||
return test.setLocalDescription(test.pcLocal, test._new_offer, HAVE_LOCAL_OFFER);
|
|
||||||
},
|
|
||||||
function PC_REMOTE_SET_NEW_REMOTE_DESCRIPTION(test) {
|
|
||||||
return test.setRemoteDescription(test.pcRemote, test._new_offer, HAVE_REMOTE_OFFER);
|
|
||||||
},
|
|
||||||
function PC_REMOTE_CREATE_NEW_ANSWER(test) {
|
|
||||||
return test.createAnswer(test.pcRemote).then(answer => {
|
|
||||||
test._new_answer = answer;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function PC_REMOTE_SET_NEW_LOCAL_DESCRIPTION(test) {
|
|
||||||
return test.setLocalDescription(test.pcRemote, test._new_answer, STABLE);
|
|
||||||
},
|
|
||||||
function PC_LOCAL_SET_NEW_REMOTE_DESCRIPTION(test) {
|
|
||||||
return test.setRemoteDescription(test.pcLocal, test._new_answer, STABLE);
|
|
||||||
}
|
|
||||||
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
|
||||||
]);
|
|
||||||
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
test.run();
|
test.run();
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: add second audio stream, no bundle"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_ADD_SECOND_STREAM(test) {
|
||||||
|
test.setMediaConstraints([{audio: true}, {audio: true}],
|
||||||
|
[{audio: true}]);
|
||||||
|
// Since this is a NoBundle variant, adding a track will cause us to
|
||||||
|
// go back to checking.
|
||||||
|
test.pcLocal.iceCheckingRestartExpected = true;
|
||||||
|
return test.pcLocal.getAllUserMedia([{audio: true}]);
|
||||||
|
},
|
||||||
|
function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
|
||||||
|
test.pcRemote.iceCheckingRestartExpected = true;
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
|
||||||
|
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: add second video stream"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_ADD_SECOND_STREAM(test) {
|
||||||
|
test.setMediaConstraints([{video: true}, {video: true}],
|
||||||
|
[{video: true}]);
|
||||||
|
return test.pcLocal.getAllUserMedia([{video: true}]);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
|
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: add second video stream, no bundle"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_ADD_SECOND_STREAM(test) {
|
||||||
|
test.setMediaConstraints([{video: true}, {video: true}],
|
||||||
|
[{video: true}]);
|
||||||
|
// Since this is a NoBundle variant, adding a track will cause us to
|
||||||
|
// go back to checking.
|
||||||
|
test.pcLocal.iceCheckingRestartExpected = true;
|
||||||
|
return test.pcLocal.getAllUserMedia([{video: true}]);
|
||||||
|
},
|
||||||
|
function PC_REMOTE_EXPECT_ICE_CHECKING(test) {
|
||||||
|
test.pcRemote.iceCheckingRestartExpected = true;
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
|
||||||
|
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
|
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,34 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: answerer adds second audio stream"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiationAnswerer(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_ADD_SECOND_STREAM(test) {
|
||||||
|
test.setMediaConstraints([{audio: true}, {audio: true}],
|
||||||
|
[{audio: true}]);
|
||||||
|
return test.pcLocal.getAllUserMedia([{audio: true}]);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -15,15 +15,7 @@
|
|||||||
var test = new PeerConnectionTest(options);
|
var test = new PeerConnectionTest(options);
|
||||||
test.chain.insertAfter(
|
test.chain.insertAfter(
|
||||||
'PC_LOCAL_CREATE_OFFER',
|
'PC_LOCAL_CREATE_OFFER',
|
||||||
[
|
[PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER]);
|
||||||
function PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER(test) {
|
|
||||||
test.originalOffer.sdp = test.originalOffer.sdp.replace(
|
|
||||||
/a=group:BUNDLE .*\r\n/g,
|
|
||||||
""
|
|
||||||
);
|
|
||||||
info("Updated no bundle offer: " + JSON.stringify(test.originalOffer));
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
test.setMediaConstraints([{audio: true}, {video: true}],
|
test.setMediaConstraints([{audio: true}, {video: true}],
|
||||||
[{audio: true}, {video: true}]);
|
[{audio: true}, {video: true}]);
|
||||||
test.run();
|
test.run();
|
||||||
|
@ -31,7 +31,10 @@ runNetworkTest(function() {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
var stream = v1.mozCaptureStreamUntilEnded();
|
var stream = v1.mozCaptureStreamUntilEnded();
|
||||||
is(stream.getTracks().length, 2, "Captured stream has 2 tracks");
|
is(stream.getTracks().length, 2, "Captured stream has 2 tracks");
|
||||||
stream.getTracks().forEach(tr => test.pcLocal._pc.addTrack(tr, stream));
|
stream.getTracks().forEach(tr => {
|
||||||
|
test.pcLocal._pc.addTrack(tr, stream);
|
||||||
|
test.pcLocal.expectedLocalTrackTypesById[tr.id] = tr.kind;
|
||||||
|
});
|
||||||
test.pcLocal.constraints = [{ video: true, audio:true }]; // fool tests
|
test.pcLocal.constraints = [{ video: true, audio:true }]; // fool tests
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: remove audio track"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
|
||||||
|
test.setOfferOptions({ offerToReceiveAudio: true });
|
||||||
|
test.setMediaConstraints([], [{audio: true}]);
|
||||||
|
return test.pcLocal.removeSender(0);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify that media stopped flowing from pcLocal
|
||||||
|
|
||||||
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,39 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: remove then add audio track"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
|
||||||
|
return test.pcLocal.removeSender(0);
|
||||||
|
},
|
||||||
|
function PC_LOCAL_ADD_AUDIO_TRACK(test) {
|
||||||
|
// The new track's pipeline will start with a packet count of
|
||||||
|
// 0, but the remote side will keep its old pipeline and packet
|
||||||
|
// count.
|
||||||
|
test.pcLocal.disableRtpCountChecking = true;
|
||||||
|
return test.pcLocal.getAllUserMedia([{audio: true}]);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: remove then add audio track"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
|
||||||
|
// The new track's pipeline will start with a packet count of
|
||||||
|
// 0, but the remote side will keep its old pipeline and packet
|
||||||
|
// count.
|
||||||
|
test.pcLocal.disableRtpCountChecking = true;
|
||||||
|
return test.pcLocal.removeSender(0);
|
||||||
|
},
|
||||||
|
function PC_LOCAL_ADD_AUDIO_TRACK(test) {
|
||||||
|
return test.pcLocal.getAllUserMedia([{audio: true}]);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
|
||||||
|
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
|
test.setMediaConstraints([{audio: true}], [{audio: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,39 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: remove then add video track"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
|
||||||
|
// The new track's pipeline will start with a packet count of
|
||||||
|
// 0, but the remote side will keep its old pipeline and packet
|
||||||
|
// count.
|
||||||
|
test.pcLocal.disableRtpCountChecking = true;
|
||||||
|
return test.pcLocal.removeSender(0);
|
||||||
|
},
|
||||||
|
function PC_LOCAL_ADD_AUDIO_TRACK(test) {
|
||||||
|
return test.pcLocal.getAllUserMedia([{video: true}]);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
|
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: remove then add video track, no bundle"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_REMOVE_AUDIO_TRACK(test) {
|
||||||
|
// The new track's pipeline will start with a packet count of
|
||||||
|
// 0, but the remote side will keep its old pipeline and packet
|
||||||
|
// count.
|
||||||
|
test.pcLocal.disableRtpCountChecking = true;
|
||||||
|
return test.pcLocal.removeSender(0);
|
||||||
|
},
|
||||||
|
function PC_LOCAL_ADD_AUDIO_TRACK(test) {
|
||||||
|
return test.pcLocal.getAllUserMedia([{video: true}]);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
test.chain.insertAfterEach('PC_LOCAL_CREATE_OFFER',
|
||||||
|
PC_LOCAL_REMOVE_BUNDLE_FROM_OFFER);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify if media flows through the new stream
|
||||||
|
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,35 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script type="application/javascript" src="pc.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
createHTML({
|
||||||
|
bug: "1017888",
|
||||||
|
title: "Renegotiation: remove video track"
|
||||||
|
});
|
||||||
|
|
||||||
|
var test;
|
||||||
|
runNetworkTest(function (options) {
|
||||||
|
test = new PeerConnectionTest(options);
|
||||||
|
addRenegotiation(test.chain,
|
||||||
|
[
|
||||||
|
function PC_LOCAL_REMOVE_VIDEO_TRACK(test) {
|
||||||
|
test.setOfferOptions({ offerToReceiveVideo: true });
|
||||||
|
test.setMediaConstraints([], [{video: true}]);
|
||||||
|
return test.pcLocal.removeSender(0);
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO(bug 1093835): figure out how to verify that media stopped flowing from pcLocal
|
||||||
|
|
||||||
|
test.setMediaConstraints([{video: true}], [{video: true}]);
|
||||||
|
test.run();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -23,6 +23,8 @@
|
|||||||
#include "gfxSharedImageSurface.h"
|
#include "gfxSharedImageSurface.h"
|
||||||
#include "nsNPAPIPluginInstance.h"
|
#include "nsNPAPIPluginInstance.h"
|
||||||
#include "nsPluginInstanceOwner.h"
|
#include "nsPluginInstanceOwner.h"
|
||||||
|
#include "nsFocusManager.h"
|
||||||
|
#include "nsIDOMElement.h"
|
||||||
#ifdef MOZ_X11
|
#ifdef MOZ_X11
|
||||||
#include "gfxXlibSurface.h"
|
#include "gfxXlibSurface.h"
|
||||||
#endif
|
#endif
|
||||||
@ -45,10 +47,6 @@
|
|||||||
#include "mozilla/plugins/PluginSurfaceParent.h"
|
#include "mozilla/plugins/PluginSurfaceParent.h"
|
||||||
#include "nsClassHashtable.h"
|
#include "nsClassHashtable.h"
|
||||||
#include "nsHashKeys.h"
|
#include "nsHashKeys.h"
|
||||||
// Plugin focus event for widget.
|
|
||||||
extern const wchar_t* kOOPPPluginFocusEventId;
|
|
||||||
UINT gOOPPPluginFocusEvent =
|
|
||||||
RegisterWindowMessage(kOOPPPluginFocusEventId);
|
|
||||||
extern const wchar_t* kFlashFullscreenClass;
|
extern const wchar_t* kFlashFullscreenClass;
|
||||||
#elif defined(MOZ_WIDGET_GTK)
|
#elif defined(MOZ_WIDGET_GTK)
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
@ -1789,7 +1787,6 @@ PluginInstanceParent::SubclassPluginWindow(HWND aWnd)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(XP_WIN)
|
|
||||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||||
if (!aWnd) {
|
if (!aWnd) {
|
||||||
NS_WARNING("PluginInstanceParent::SubclassPluginWindow unexpected null window");
|
NS_WARNING("PluginInstanceParent::SubclassPluginWindow unexpected null window");
|
||||||
@ -1802,7 +1799,6 @@ PluginInstanceParent::SubclassPluginWindow(HWND aWnd)
|
|||||||
sPluginInstanceList->Put((void*)mPluginHWND, this);
|
sPluginInstanceList->Put((void*)mPluginHWND, this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND),
|
NS_ASSERTION(!(mPluginHWND && aWnd != mPluginHWND),
|
||||||
"PluginInstanceParent::SubclassPluginWindow hwnd is not our window!");
|
"PluginInstanceParent::SubclassPluginWindow hwnd is not our window!");
|
||||||
@ -1821,7 +1817,6 @@ PluginInstanceParent::SubclassPluginWindow(HWND aWnd)
|
|||||||
void
|
void
|
||||||
PluginInstanceParent::UnsubclassPluginWindow()
|
PluginInstanceParent::UnsubclassPluginWindow()
|
||||||
{
|
{
|
||||||
#if defined(XP_WIN)
|
|
||||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||||
if (mPluginHWND) {
|
if (mPluginHWND) {
|
||||||
// Remove 'this' from the plugin list safely
|
// Remove 'this' from the plugin list safely
|
||||||
@ -1837,7 +1832,6 @@ PluginInstanceParent::UnsubclassPluginWindow()
|
|||||||
mPluginHWND = nullptr;
|
mPluginHWND = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (mPluginHWND && mPluginWndProc) {
|
if (mPluginHWND && mPluginWndProc) {
|
||||||
::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
|
::SetWindowLongPtrA(mPluginHWND, GWLP_WNDPROC,
|
||||||
@ -1980,14 +1974,21 @@ PluginInstanceParent::AnswerPluginFocusChange(const bool& gotFocus)
|
|||||||
{
|
{
|
||||||
PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
|
PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
|
||||||
|
|
||||||
// Currently only in use on windows - an rpc event we receive from the
|
// Currently only in use on windows - an event we receive from the child
|
||||||
// child when it's plugin window (or one of it's children) receives keyboard
|
// when it's plugin window (or one of it's children) receives keyboard
|
||||||
// focus. We forward the event down to widget so the dom/focus manager can
|
// focus. We detect this and forward a notification here so we can update
|
||||||
// be updated.
|
// focus.
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// XXX This needs to go to PuppetWidget. bug ???
|
if (gotFocus) {
|
||||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
nsPluginInstanceOwner* owner = GetOwner();
|
||||||
::SendMessage(mPluginHWND, gOOPPPluginFocusEvent, gotFocus ? 1 : 0, 0);
|
if (owner) {
|
||||||
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||||
|
nsCOMPtr<nsIDOMElement> element;
|
||||||
|
owner->GetDOMElement(getter_AddRefs(element));
|
||||||
|
if (fm && element) {
|
||||||
|
fm->SetFocus(element, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
|
@ -819,6 +819,12 @@ this.PushService = {
|
|||||||
if (uri.scheme === "wss") {
|
if (uri.scheme === "wss") {
|
||||||
this._ws = Cc["@mozilla.org/network/protocol;1?name=wss"]
|
this._ws = Cc["@mozilla.org/network/protocol;1?name=wss"]
|
||||||
.createInstance(Ci.nsIWebSocketChannel);
|
.createInstance(Ci.nsIWebSocketChannel);
|
||||||
|
|
||||||
|
this._ws.initLoadInfo(null, // aLoadingNode
|
||||||
|
Services.scriptSecurityManager.getSystemPrincipal(),
|
||||||
|
null, // aTriggeringPrincipal
|
||||||
|
Ci.nsILoadInfo.SEC_NORMAL,
|
||||||
|
Ci.nsIContentPolicy.TYPE_WEBSOCKET);
|
||||||
}
|
}
|
||||||
else if (uri.scheme === "ws") {
|
else if (uri.scheme === "ws") {
|
||||||
debug("Push over an insecure connection (ws://) is not allowed!");
|
debug("Push over an insecure connection (ws://) is not allowed!");
|
||||||
|
@ -23,6 +23,7 @@ interface PeerConnectionObserver
|
|||||||
void onAddIceCandidateSuccess();
|
void onAddIceCandidateSuccess();
|
||||||
void onAddIceCandidateError(unsigned long name, DOMString message);
|
void onAddIceCandidateError(unsigned long name, DOMString message);
|
||||||
void onIceCandidate(unsigned short level, DOMString mid, DOMString candidate);
|
void onIceCandidate(unsigned short level, DOMString mid, DOMString candidate);
|
||||||
|
void onNegotiationNeeded();
|
||||||
|
|
||||||
/* Stats callbacks */
|
/* Stats callbacks */
|
||||||
void onGetStatsSuccess(optional RTCStatsReportInternal report);
|
void onGetStatsSuccess(optional RTCStatsReportInternal report);
|
||||||
@ -40,7 +41,7 @@ interface PeerConnectionObserver
|
|||||||
|
|
||||||
/* Changes to MediaStreamTracks */
|
/* Changes to MediaStreamTracks */
|
||||||
void onAddStream(MediaStream stream);
|
void onAddStream(MediaStream stream);
|
||||||
void onRemoveStream();
|
void onRemoveStream(MediaStream stream);
|
||||||
void onAddTrack(MediaStreamTrack track);
|
void onAddTrack(MediaStreamTrack track);
|
||||||
void onRemoveTrack();
|
void onRemoveTrack(MediaStreamTrack track);
|
||||||
};
|
};
|
||||||
|
@ -130,7 +130,6 @@ ServiceWorkerRegistrationInfo::Clear()
|
|||||||
mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
|
mWaitingWorker->UpdateState(ServiceWorkerState::Redundant);
|
||||||
// Fire statechange.
|
// Fire statechange.
|
||||||
mWaitingWorker = nullptr;
|
mWaitingWorker = nullptr;
|
||||||
mWaitingToActivate = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mActiveWorker) {
|
if (mActiveWorker) {
|
||||||
@ -199,8 +198,6 @@ ServiceWorkerManager::~ServiceWorkerManager()
|
|||||||
mServiceWorkerRegistrationInfos.Clear();
|
mServiceWorkerRegistrationInfos.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServiceWorkerRegisterJob;
|
|
||||||
|
|
||||||
class ContinueLifecycleTask : public nsISupports
|
class ContinueLifecycleTask : public nsISupports
|
||||||
{
|
{
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
@ -216,6 +213,8 @@ public:
|
|||||||
|
|
||||||
NS_IMPL_ISUPPORTS0(ContinueLifecycleTask);
|
NS_IMPL_ISUPPORTS0(ContinueLifecycleTask);
|
||||||
|
|
||||||
|
class ServiceWorkerRegisterJob;
|
||||||
|
|
||||||
class ContinueInstallTask MOZ_FINAL : public ContinueLifecycleTask
|
class ContinueInstallTask MOZ_FINAL : public ContinueLifecycleTask
|
||||||
{
|
{
|
||||||
nsRefPtr<ServiceWorkerRegisterJob> mJob;
|
nsRefPtr<ServiceWorkerRegisterJob> mJob;
|
||||||
@ -238,10 +237,7 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
void
|
void
|
||||||
ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately /* unused */) MOZ_OVERRIDE
|
ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately /* unused */) MOZ_OVERRIDE;
|
||||||
{
|
|
||||||
mRegistration->FinishActivate(aSuccess);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ContinueLifecycleRunnable MOZ_FINAL : public nsRunnable
|
class ContinueLifecycleRunnable MOZ_FINAL : public nsRunnable
|
||||||
@ -571,6 +567,7 @@ public:
|
|||||||
getter_AddRefs(serviceWorker));
|
getter_AddRefs(serviceWorker));
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
swm->mSetOfScopesBeingUpdated.Remove(mRegistration->mScope);
|
||||||
Fail(NS_ERROR_DOM_ABORT_ERR);
|
Fail(NS_ERROR_DOM_ABORT_ERR);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -585,6 +582,7 @@ public:
|
|||||||
jsapi.Init();
|
jsapi.Init();
|
||||||
bool ok = r->Dispatch(jsapi.cx());
|
bool ok = r->Dispatch(jsapi.cx());
|
||||||
if (NS_WARN_IF(!ok)) {
|
if (NS_WARN_IF(!ok)) {
|
||||||
|
swm->mSetOfScopesBeingUpdated.Remove(mRegistration->mScope);
|
||||||
Fail(NS_ERROR_DOM_ABORT_ERR);
|
Fail(NS_ERROR_DOM_ABORT_ERR);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -608,6 +606,10 @@ public:
|
|||||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||||
MOZ_ASSERT(swm->mSetOfScopesBeingUpdated.Contains(mRegistration->mScope));
|
MOZ_ASSERT(swm->mSetOfScopesBeingUpdated.Contains(mRegistration->mScope));
|
||||||
swm->mSetOfScopesBeingUpdated.Remove(mRegistration->mScope);
|
swm->mSetOfScopesBeingUpdated.Remove(mRegistration->mScope);
|
||||||
|
// This is effectively the end of Step 4.3 of the [[Update]] algorithm.
|
||||||
|
// The invocation of [[Install]] is not part of the atomic block.
|
||||||
|
|
||||||
|
// Begin [[Install]] atomic step 4.
|
||||||
if (mRegistration->mInstallingWorker) {
|
if (mRegistration->mInstallingWorker) {
|
||||||
// FIXME(nsm): Terminate and stuff
|
// FIXME(nsm): Terminate and stuff
|
||||||
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
|
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
|
||||||
@ -620,15 +622,13 @@ public:
|
|||||||
|
|
||||||
Succeed();
|
Succeed();
|
||||||
|
|
||||||
|
// Step 4.6 "Queue a task..." for updatefound.
|
||||||
nsCOMPtr<nsIRunnable> upr =
|
nsCOMPtr<nsIRunnable> upr =
|
||||||
NS_NewRunnableMethodWithArg<ServiceWorkerRegistrationInfo*>(swm,
|
NS_NewRunnableMethodWithArg<ServiceWorkerRegistrationInfo*>(swm,
|
||||||
&ServiceWorkerManager::FireUpdateFound,
|
&ServiceWorkerManager::FireUpdateFound,
|
||||||
mRegistration);
|
mRegistration);
|
||||||
NS_DispatchToMainThread(upr);
|
NS_DispatchToMainThread(upr);
|
||||||
|
|
||||||
nsMainThreadPtrHandle<ContinueLifecycleTask> handle(
|
|
||||||
new nsMainThreadPtrHolder<ContinueLifecycleTask>(new ContinueInstallTask(this)));
|
|
||||||
|
|
||||||
nsRefPtr<ServiceWorker> serviceWorker;
|
nsRefPtr<ServiceWorker> serviceWorker;
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
swm->CreateServiceWorker(mRegistration->mPrincipal,
|
swm->CreateServiceWorker(mRegistration->mPrincipal,
|
||||||
@ -637,15 +637,21 @@ public:
|
|||||||
getter_AddRefs(serviceWorker));
|
getter_AddRefs(serviceWorker));
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
ContinueAfterInstallEvent(false /* success */, false /* activate immediately */);
|
ContinueAfterInstallEvent(false /* aSuccess */, false /* aActivateImmediately */);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsMainThreadPtrHandle<ContinueLifecycleTask> handle(
|
||||||
|
new nsMainThreadPtrHolder<ContinueLifecycleTask>(new ContinueInstallTask(this)));
|
||||||
|
|
||||||
nsRefPtr<LifecycleEventWorkerRunnable> r =
|
nsRefPtr<LifecycleEventWorkerRunnable> r =
|
||||||
new LifecycleEventWorkerRunnable(serviceWorker->GetWorkerPrivate(), NS_LITERAL_STRING("install"), handle);
|
new LifecycleEventWorkerRunnable(serviceWorker->GetWorkerPrivate(), NS_LITERAL_STRING("install"), handle);
|
||||||
|
|
||||||
AutoJSAPI jsapi;
|
AutoJSAPI jsapi;
|
||||||
jsapi.Init();
|
jsapi.Init();
|
||||||
|
|
||||||
|
// This triggers Step 4.7 "Queue a task to run the following substeps..."
|
||||||
|
// which sends the install event to the worker.
|
||||||
r->Dispatch(jsapi.cx());
|
r->Dispatch(jsapi.cx());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -727,7 +733,8 @@ private:
|
|||||||
FailCommon(nsresult aRv)
|
FailCommon(nsresult aRv)
|
||||||
{
|
{
|
||||||
mCallback = nullptr;
|
mCallback = nullptr;
|
||||||
MaybeRemoveRegistration();
|
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||||
|
swm->MaybeRemoveRegistration(mRegistration);
|
||||||
// Ensures that the job can't do anything useful from this point on.
|
// Ensures that the job can't do anything useful from this point on.
|
||||||
mRegistration = nullptr;
|
mRegistration = nullptr;
|
||||||
Done(aRv);
|
Done(aRv);
|
||||||
@ -745,23 +752,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MaybeRemoveRegistration()
|
ContinueAfterInstallEvent(bool aInstallEventSuccess, bool aActivateImmediately)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mRegistration);
|
|
||||||
nsRefPtr<ServiceWorkerInfo> newest = mRegistration->Newest();
|
|
||||||
if (!newest) {
|
|
||||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
|
||||||
swm->RemoveRegistration(mRegistration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ContinueAfterInstallEvent(bool aSuccess, bool aActivateImmediately)
|
|
||||||
{
|
|
||||||
// By this point the callback should've been notified about success or fail
|
|
||||||
// and nulled.
|
|
||||||
MOZ_ASSERT(!mCallback);
|
|
||||||
|
|
||||||
if (!mRegistration->mInstallingWorker) {
|
if (!mRegistration->mInstallingWorker) {
|
||||||
NS_WARNING("mInstallingWorker was null.");
|
NS_WARNING("mInstallingWorker was null.");
|
||||||
return Done(NS_ERROR_DOM_ABORT_ERR);
|
return Done(NS_ERROR_DOM_ABORT_ERR);
|
||||||
@ -770,12 +762,12 @@ private:
|
|||||||
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
|
||||||
|
|
||||||
// "If installFailed is true"
|
// "If installFailed is true"
|
||||||
if (!aSuccess) {
|
if (!aInstallEventSuccess) {
|
||||||
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
|
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Redundant);
|
||||||
mRegistration->mInstallingWorker = nullptr;
|
mRegistration->mInstallingWorker = nullptr;
|
||||||
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
|
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
|
||||||
WhichServiceWorker::INSTALLING_WORKER);
|
WhichServiceWorker::INSTALLING_WORKER);
|
||||||
MaybeRemoveRegistration();
|
swm->MaybeRemoveRegistration(mRegistration);
|
||||||
return Done(NS_ERROR_DOM_ABORT_ERR);
|
return Done(NS_ERROR_DOM_ABORT_ERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -792,14 +784,14 @@ private:
|
|||||||
// swapping it with waiting worker.
|
// swapping it with waiting worker.
|
||||||
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Installed);
|
mRegistration->mInstallingWorker->UpdateState(ServiceWorkerState::Installed);
|
||||||
mRegistration->mWaitingWorker = mRegistration->mInstallingWorker.forget();
|
mRegistration->mWaitingWorker = mRegistration->mInstallingWorker.forget();
|
||||||
mRegistration->mWaitingToActivate = false;
|
|
||||||
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
|
swm->InvalidateServiceWorkerRegistrationWorker(mRegistration,
|
||||||
WhichServiceWorker::INSTALLING_WORKER | WhichServiceWorker::WAITING_WORKER);
|
WhichServiceWorker::INSTALLING_WORKER | WhichServiceWorker::WAITING_WORKER);
|
||||||
|
|
||||||
// FIXME(nsm): Bug 982711 Deal with activateImmediately.
|
// FIXME(nsm): Bug 982711 Deal with activateImmediately.
|
||||||
NS_WARN_IF_FALSE(!aActivateImmediately, "Immediate activation using replace() is not supported yet");
|
NS_WARN_IF_FALSE(!aActivateImmediately, "Immediate activation using replace() is not supported yet");
|
||||||
mRegistration->TryToActivate();
|
|
||||||
Done(NS_OK);
|
Done(NS_OK);
|
||||||
|
// Activate() is invoked out of band of atomic.
|
||||||
|
mRegistration->TryToActivate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -818,6 +810,8 @@ ContinueUpdateRunnable::Run()
|
|||||||
void
|
void
|
||||||
ContinueInstallTask::ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately)
|
ContinueInstallTask::ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately)
|
||||||
{
|
{
|
||||||
|
// This does not start the job immediately if there are other jobs in the
|
||||||
|
// queue, which captures the "atomic" behaviour we want.
|
||||||
mJob->ContinueAfterInstallEvent(aSuccess, aActivateImmediately);
|
mJob->ContinueAfterInstallEvent(aSuccess, aActivateImmediately);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1100,18 +1094,20 @@ LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx, WorkerPriva
|
|||||||
void
|
void
|
||||||
ServiceWorkerRegistrationInfo::TryToActivate()
|
ServiceWorkerRegistrationInfo::TryToActivate()
|
||||||
{
|
{
|
||||||
mWaitingToActivate = true;
|
|
||||||
if (!IsControllingDocuments()) {
|
if (!IsControllingDocuments()) {
|
||||||
Activate();
|
Activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ContinueActivateTask::ContinueAfterWorkerEvent(bool aSuccess, bool aActivateImmediately /* unused */)
|
||||||
|
{
|
||||||
|
mRegistration->FinishActivate(aSuccess);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ServiceWorkerRegistrationInfo::Activate()
|
ServiceWorkerRegistrationInfo::Activate()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mWaitingToActivate);
|
|
||||||
mWaitingToActivate = false;
|
|
||||||
|
|
||||||
nsRefPtr<ServiceWorkerInfo> activatingWorker = mWaitingWorker;
|
nsRefPtr<ServiceWorkerInfo> activatingWorker = mWaitingWorker;
|
||||||
nsRefPtr<ServiceWorkerInfo> exitingWorker = mActiveWorker;
|
nsRefPtr<ServiceWorkerInfo> exitingWorker = mActiveWorker;
|
||||||
|
|
||||||
@ -1132,18 +1128,18 @@ ServiceWorkerRegistrationInfo::Activate()
|
|||||||
mWaitingWorker = nullptr;
|
mWaitingWorker = nullptr;
|
||||||
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
|
mActiveWorker->UpdateState(ServiceWorkerState::Activating);
|
||||||
|
|
||||||
|
// FIXME(nsm): Unlink appcache if there is one.
|
||||||
|
|
||||||
swm->CheckPendingReadyPromises();
|
swm->CheckPendingReadyPromises();
|
||||||
swm->StoreRegistration(mPrincipal, this);
|
swm->StoreRegistration(mPrincipal, this);
|
||||||
|
|
||||||
// "Queue a task to fire a simple event named controllerchange..."
|
// "Queue a task to fire a simple event named controllerchange..."
|
||||||
nsCOMPtr<nsIRunnable> controllerChangeRunnable =
|
nsCOMPtr<nsIRunnable> controllerChangeRunnable =
|
||||||
NS_NewRunnableMethodWithArg<ServiceWorkerRegistrationInfo*>(swm, &ServiceWorkerManager::FireControllerChange, this);
|
NS_NewRunnableMethodWithArg<ServiceWorkerRegistrationInfo*>(swm,
|
||||||
|
&ServiceWorkerManager::FireControllerChange,
|
||||||
|
this);
|
||||||
NS_DispatchToMainThread(controllerChangeRunnable);
|
NS_DispatchToMainThread(controllerChangeRunnable);
|
||||||
|
|
||||||
// XXXnsm I have my doubts about this. Leaving the main thread means that
|
|
||||||
// subsequent calls to Activate() not from a Register() call, i.e. due to all
|
|
||||||
// controlled documents going away, may lead to two or more calls being
|
|
||||||
// interleaved.
|
|
||||||
MOZ_ASSERT(mActiveWorker);
|
MOZ_ASSERT(mActiveWorker);
|
||||||
nsRefPtr<ServiceWorker> serviceWorker;
|
nsRefPtr<ServiceWorker> serviceWorker;
|
||||||
nsresult rv =
|
nsresult rv =
|
||||||
@ -1152,7 +1148,11 @@ ServiceWorkerRegistrationInfo::Activate()
|
|||||||
mScope,
|
mScope,
|
||||||
getter_AddRefs(serviceWorker));
|
getter_AddRefs(serviceWorker));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
FinishActivate(false /* success */);
|
nsCOMPtr<nsIRunnable> r =
|
||||||
|
NS_NewRunnableMethodWithArg<bool>(this,
|
||||||
|
&ServiceWorkerRegistrationInfo::FinishActivate,
|
||||||
|
false /* success */);
|
||||||
|
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(NS_DispatchToMainThread(r)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1688,7 +1688,10 @@ ServiceWorkerManager::HandleError(JSContext* aCx,
|
|||||||
void
|
void
|
||||||
ServiceWorkerRegistrationInfo::FinishActivate(bool aSuccess)
|
ServiceWorkerRegistrationInfo::FinishActivate(bool aSuccess)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(mActiveWorker);
|
if (mPendingUninstall || !mActiveWorker) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (aSuccess) {
|
if (aSuccess) {
|
||||||
mActiveWorker->UpdateState(ServiceWorkerState::Activated);
|
mActiveWorker->UpdateState(ServiceWorkerState::Activated);
|
||||||
} else {
|
} else {
|
||||||
@ -1933,10 +1936,6 @@ void
|
|||||||
ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc)
|
ServiceWorkerManager::MaybeStartControlling(nsIDocument* aDoc)
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
if (!Preferences::GetBool("dom.serviceWorkers.enabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
nsRefPtr<ServiceWorkerRegistrationInfo> registration =
|
||||||
GetServiceWorkerRegistrationInfo(aDoc);
|
GetServiceWorkerRegistrationInfo(aDoc);
|
||||||
if (registration) {
|
if (registration) {
|
||||||
@ -1952,10 +1951,6 @@ void
|
|||||||
ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc)
|
ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aDoc);
|
MOZ_ASSERT(aDoc);
|
||||||
if (!Preferences::GetBool("dom.serviceWorkers.enabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
nsRefPtr<ServiceWorkerRegistrationInfo> registration;
|
||||||
mControlledDocuments.Remove(aDoc, getter_AddRefs(registration));
|
mControlledDocuments.Remove(aDoc, getter_AddRefs(registration));
|
||||||
// A document which was uncontrolled does not maintain that state itself, so
|
// A document which was uncontrolled does not maintain that state itself, so
|
||||||
@ -1963,6 +1958,14 @@ ServiceWorkerManager::MaybeStopControlling(nsIDocument* aDoc)
|
|||||||
// associated registration. So this check is required.
|
// associated registration. So this check is required.
|
||||||
if (registration) {
|
if (registration) {
|
||||||
registration->StopControllingADocument();
|
registration->StopControllingADocument();
|
||||||
|
if (!registration->IsControllingDocuments()) {
|
||||||
|
if (registration->mPendingUninstall) {
|
||||||
|
registration->Clear();
|
||||||
|
RemoveRegistration(registration);
|
||||||
|
} else {
|
||||||
|
registration->TryToActivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2410,4 +2413,14 @@ ServiceWorkerManager::CreateNewRegistration(const nsCString& aScope,
|
|||||||
return registration;
|
return registration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServiceWorkerManager::MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aRegistration);
|
||||||
|
nsRefPtr<ServiceWorkerInfo> newest = aRegistration->Newest();
|
||||||
|
if (!newest) {
|
||||||
|
RemoveRegistration(aRegistration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
END_WORKERS_NAMESPACE
|
END_WORKERS_NAMESPACE
|
||||||
|
@ -49,6 +49,7 @@ class ServiceWorkerJobQueue;
|
|||||||
|
|
||||||
class ServiceWorkerJob : public nsISupports
|
class ServiceWorkerJob : public nsISupports
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
// The queue keeps the jobs alive, so they can hold a rawptr back to the
|
// The queue keeps the jobs alive, so they can hold a rawptr back to the
|
||||||
// queue.
|
// queue.
|
||||||
ServiceWorkerJobQueue* mQueue;
|
ServiceWorkerJobQueue* mQueue;
|
||||||
@ -151,7 +152,6 @@ public:
|
|||||||
// removed since documents may be controlled. It is marked as
|
// removed since documents may be controlled. It is marked as
|
||||||
// pendingUninstall and when all controlling documents go away, removed.
|
// pendingUninstall and when all controlling documents go away, removed.
|
||||||
bool mPendingUninstall;
|
bool mPendingUninstall;
|
||||||
bool mWaitingToActivate;
|
|
||||||
|
|
||||||
explicit ServiceWorkerRegistrationInfo(const nsACString& aScope,
|
explicit ServiceWorkerRegistrationInfo(const nsACString& aScope,
|
||||||
nsIPrincipal* aPrincipal);
|
nsIPrincipal* aPrincipal);
|
||||||
@ -289,13 +289,11 @@ class ServiceWorkerManager MOZ_FINAL
|
|||||||
: public nsIServiceWorkerManager
|
: public nsIServiceWorkerManager
|
||||||
, public nsIIPCBackgroundChildCreateCallback
|
, public nsIIPCBackgroundChildCreateCallback
|
||||||
{
|
{
|
||||||
friend class ActivationRunnable;
|
|
||||||
friend class ServiceWorkerRegistrationInfo;
|
|
||||||
friend class ServiceWorkerRegisterJob;
|
|
||||||
friend class GetReadyPromiseRunnable;
|
friend class GetReadyPromiseRunnable;
|
||||||
friend class GetRegistrationsRunnable;
|
friend class GetRegistrationsRunnable;
|
||||||
friend class GetRegistrationRunnable;
|
friend class GetRegistrationRunnable;
|
||||||
friend class QueueFireUpdateFoundRunnable;
|
friend class ServiceWorkerRegisterJob;
|
||||||
|
friend class ServiceWorkerRegistrationInfo;
|
||||||
friend class ServiceWorkerUnregisterJob;
|
friend class ServiceWorkerUnregisterJob;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -349,6 +347,8 @@ public:
|
|||||||
void
|
void
|
||||||
RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
|
RemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aRegistration);
|
||||||
|
MOZ_ASSERT(!aRegistration->IsControllingDocuments());
|
||||||
MOZ_ASSERT(mServiceWorkerRegistrationInfos.Contains(aRegistration->mScope));
|
MOZ_ASSERT(mServiceWorkerRegistrationInfos.Contains(aRegistration->mScope));
|
||||||
ServiceWorkerManager::RemoveScope(mOrderedScopes, aRegistration->mScope);
|
ServiceWorkerManager::RemoveScope(mOrderedScopes, aRegistration->mScope);
|
||||||
mServiceWorkerRegistrationInfos.Remove(aRegistration->mScope);
|
mServiceWorkerRegistrationInfos.Remove(aRegistration->mScope);
|
||||||
@ -491,6 +491,9 @@ private:
|
|||||||
void* aUnused);
|
void* aUnused);
|
||||||
|
|
||||||
nsClassHashtable<nsISupportsHashKey, PendingReadyPromise> mPendingReadyPromises;
|
nsClassHashtable<nsISupportsHashKey, PendingReadyPromise> mPendingReadyPromises;
|
||||||
|
|
||||||
|
void
|
||||||
|
MaybeRemoveRegistration(ServiceWorkerRegistrationInfo* aRegistration);
|
||||||
|
|
||||||
mozilla::ipc::PBackgroundChild* mActor;
|
mozilla::ipc::PBackgroundChild* mActor;
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
|
|
||||||
// Make sure to use good, unique messages, since the actual expression will not show up in test results.
|
// Make sure to use good, unique messages, since the actual expression will not show up in test results.
|
||||||
function my_ok(result, msg) {
|
function my_ok(result, msg) {
|
||||||
window.opener.postMessage({status: "ok", result: result, message: msg}, "*");
|
parent.postMessage({status: "ok", result: result, message: msg}, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
function finish() {
|
function finish() {
|
||||||
window.opener.postMessage({status: "done"}, "*");
|
parent.postMessage({status: "done"}, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
navigator.serviceWorker.ready.then(function(swr) {
|
navigator.serviceWorker.ready.then(function(swr) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Worker that errors on receiving an install event.
|
// Worker that errors on receiving an install event.
|
||||||
oninstall = function(e) {
|
oninstall = function(e) {
|
||||||
undefined.doSomething;
|
undefined.doSomething;
|
||||||
}
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[DEFAULT]
|
[DEFAULT]
|
||||||
skip-if = buildapp == 'b2g' || android_version == "10" # bug 1056702
|
skip-if = buildapp == 'b2g'
|
||||||
support-files =
|
support-files =
|
||||||
worker.js
|
worker.js
|
||||||
worker2.js
|
worker2.js
|
||||||
@ -22,18 +22,16 @@ support-files =
|
|||||||
message_posting_worker.js
|
message_posting_worker.js
|
||||||
|
|
||||||
[test_unregister.html]
|
[test_unregister.html]
|
||||||
skip-if = true # bug 1094375
|
skip-if = true # Bug 1133805
|
||||||
[test_installation_simple.html]
|
[test_installation_simple.html]
|
||||||
skip-if = true # bug 1094375
|
|
||||||
[test_get_serviced.html]
|
[test_get_serviced.html]
|
||||||
[test_install_event.html]
|
[test_install_event.html]
|
||||||
[test_navigator.html]
|
[test_navigator.html]
|
||||||
[test_scopes.html]
|
[test_scopes.html]
|
||||||
skip-if = true # bug 1126470 and many others
|
|
||||||
[test_controller.html]
|
[test_controller.html]
|
||||||
[test_workerUpdate.html]
|
[test_workerUpdate.html]
|
||||||
skip-if = true # Enable after Bug 982726 postMessage is landed.
|
skip-if = true # Bug 1133805
|
||||||
[test_workerUnregister.html]
|
[test_workerUnregister.html]
|
||||||
skip-if = true # Enable after Bug 982726 postMessage is landed.
|
skip-if = true # Bug 1133805
|
||||||
[test_post_message.html]
|
[test_post_message.html]
|
||||||
[test_post_message_advanced.html]
|
[test_post_message_advanced.html]
|
||||||
|
@ -3,13 +3,11 @@
|
|||||||
<body>
|
<body>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
window.addEventListener('message', function(evt) {
|
window.addEventListener('message', function(evt) {
|
||||||
navigator.serviceWorker.ready.then(function() {
|
navigator.serviceWorker.ready.then(function() {
|
||||||
navigator.serviceWorker.oncontrollerchange = function(e) {
|
evt.ports[0].postMessage("WOW!");
|
||||||
evt.ports[0].postMessage("WOW!");
|
});
|
||||||
}
|
}, false);
|
||||||
});
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -15,6 +15,9 @@
|
|||||||
<pre id="test"></pre>
|
<pre id="test"></pre>
|
||||||
<script class="testbody" type="text/javascript">
|
<script class="testbody" type="text/javascript">
|
||||||
|
|
||||||
|
var content;
|
||||||
|
var iframe;
|
||||||
|
|
||||||
function simpleRegister() {
|
function simpleRegister() {
|
||||||
// We use the control scope for the less specific registration. The window will register a worker on controller/
|
// We use the control scope for the less specific registration. The window will register a worker on controller/
|
||||||
return navigator.serviceWorker.register("worker.js", { scope: "./control" });
|
return navigator.serviceWorker.register("worker.js", { scope: "./control" });
|
||||||
@ -27,17 +30,23 @@
|
|||||||
ok(e.data.result, e.data.message);
|
ok(e.data.result, e.data.message);
|
||||||
} else if (e.data.status == "done") {
|
} else if (e.data.status == "done") {
|
||||||
window.onmessage = null;
|
window.onmessage = null;
|
||||||
w.close();
|
content.removeChild(iframe);
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var w = window.open("controller/index.html");
|
content = document.getElementById("content");
|
||||||
|
ok(content, "Parent exists.");
|
||||||
|
|
||||||
|
iframe = document.createElement("iframe");
|
||||||
|
iframe.setAttribute('src', "controller/index.html");
|
||||||
|
content.appendChild(iframe);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This document just flips the prefs and opens the window for the actual test.
|
// This document just flips the prefs and opens the iframe for the actual test.
|
||||||
function runTest() {
|
function runTest() {
|
||||||
simpleRegister()
|
simpleRegister()
|
||||||
.then(testController)
|
.then(testController)
|
||||||
|
@ -38,9 +38,10 @@
|
|||||||
|
|
||||||
function installError() {
|
function installError() {
|
||||||
// Silence worker errors so they don't cause the test to fail.
|
// Silence worker errors so they don't cause the test to fail.
|
||||||
window.onerror = function() { }
|
window.onerror = function(e) {}
|
||||||
return navigator.serviceWorker.register("install_event_error_worker.js", { scope: "./install_event" })
|
return navigator.serviceWorker.register("install_event_error_worker.js", { scope: "./install_event" })
|
||||||
.then(function(swr) {
|
.then(function(swr) {
|
||||||
|
ok(swr.installing instanceof ServiceWorker, "There should be an installing worker if promise resolves.");
|
||||||
ok(swr.installing.state == "installing", "Installing worker's state should be 'installing'");
|
ok(swr.installing.state == "installing", "Installing worker's state should be 'installing'");
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
swr.installing.onstatechange = function(e) {
|
swr.installing.onstatechange = function(e) {
|
||||||
@ -85,7 +86,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function runTest() {
|
function runTest() {
|
||||||
simpleRegister()
|
Promise.resolve()
|
||||||
|
.then(simpleRegister)
|
||||||
.then(nextRegister)
|
.then(nextRegister)
|
||||||
.then(installError)
|
.then(installError)
|
||||||
.then(activateError)
|
.then(activateError)
|
||||||
|
@ -75,25 +75,6 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function abortPrevious() {
|
|
||||||
var p = navigator.serviceWorker.register("worker2.js", { scope: "foo/" });
|
|
||||||
var q = navigator.serviceWorker.register("worker3.js", { scope: "foo/" });
|
|
||||||
|
|
||||||
return Promise.all([
|
|
||||||
p.then(function(wr) {
|
|
||||||
ok(false, "First registration should fail with AbortError");
|
|
||||||
}, function(e) {
|
|
||||||
ok(e.name === "AbortError", "First registration should fail with AbortError");
|
|
||||||
}),
|
|
||||||
|
|
||||||
q.then(function(wr) {
|
|
||||||
ok(wr instanceof ServiceWorkerRegistration, "Second registration should succeed");
|
|
||||||
}, function(e) {
|
|
||||||
ok(false, "Second registration should succeed");
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function networkError404() {
|
function networkError404() {
|
||||||
return navigator.serviceWorker.register("404.js", { scope: "network_error/"}).then(function(w) {
|
return navigator.serviceWorker.register("404.js", { scope: "network_error/"}).then(function(w) {
|
||||||
ok(false, "Should fail with NetworkError");
|
ok(false, "Should fail with NetworkError");
|
||||||
@ -111,7 +92,6 @@
|
|||||||
is(swr, undefined, "A failed registration for a scope with no prior controllers should clear itself");
|
is(swr, undefined, "A failed registration for a scope with no prior controllers should clear itself");
|
||||||
});
|
});
|
||||||
}, function(e) {
|
}, function(e) {
|
||||||
info("NSM " + e.name);
|
|
||||||
ok(e instanceof Error, "Registration should fail with parse error");
|
ok(e instanceof Error, "Registration should fail with parse error");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -140,8 +120,7 @@
|
|||||||
window.onmessage = null;
|
window.onmessage = null;
|
||||||
// We have to make frame navigate away, otherwise it will call
|
// We have to make frame navigate away, otherwise it will call
|
||||||
// MaybeStopControlling() when this document is unloaded. At that point
|
// MaybeStopControlling() when this document is unloaded. At that point
|
||||||
// the pref has been disabled, and so MaybeStopControlling() will just
|
// the pref has been disabled, so the ServiceWorkerManager is not available.
|
||||||
// return since it is currently gated.
|
|
||||||
frame.setAttribute("src", new URL("about:blank").href);
|
frame.setAttribute("src", new URL("about:blank").href);
|
||||||
resolve();
|
resolve();
|
||||||
} else if (e.data.type == "check") {
|
} else if (e.data.type == "check") {
|
||||||
@ -183,7 +162,6 @@
|
|||||||
.then(sameOriginScope)
|
.then(sameOriginScope)
|
||||||
.then(httpsOnly)
|
.then(httpsOnly)
|
||||||
.then(realWorker)
|
.then(realWorker)
|
||||||
.then(abortPrevious)
|
|
||||||
.then(networkError404)
|
.then(networkError404)
|
||||||
.then(parseError)
|
.then(parseError)
|
||||||
.then(updatefound)
|
.then(updatefound)
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
ok(getScope(p("sub/dir/afoo")) === p("sub/dir/a"), "Scope should match");
|
ok(getScope(p("sub/dir/afoo")) === p("sub/dir/a"), "Scope should match");
|
||||||
ok(getScope(p("star*wars")) === p("star*"), "Scope should match");
|
ok(getScope(p("star*wars")) === p("star*"), "Scope should match");
|
||||||
ok(getScope(p("star/a.html")) === p(""), "Scope should match");
|
ok(getScope(p("star/a.html")) === p(""), "Scope should match");
|
||||||
resolve(true);
|
resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,22 +19,19 @@
|
|||||||
info("unregister/index.html should not to be launched directly!");
|
info("unregister/index.html should not to be launched directly!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SimpleTest.requestFlakyTimeout("Unfortunately we have no way to test for a page being uncontrolled except waiting for ready to not resolve");
|
||||||
var tId = setTimeout(function() {
|
var tId = setTimeout(function() {
|
||||||
info("tId timeout!");
|
|
||||||
parent.postMessage({ controlled: false }, "*");
|
parent.postMessage({ controlled: false }, "*");
|
||||||
tId = null;
|
tId = null;
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
navigator.serviceWorker.ready.then(function() {
|
navigator.serviceWorker.ready.then(function() {
|
||||||
info("Got ready");
|
|
||||||
if (tId == null) {
|
if (tId == null) {
|
||||||
info("tId was null");
|
|
||||||
parent.postMessage("FAIL!!!", "*");
|
parent.postMessage("FAIL!!!", "*");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearTimeout(tId);
|
clearTimeout(tId);
|
||||||
info("tId was non-null");
|
|
||||||
parent.postMessage({ controlled: true }, "*");
|
parent.postMessage({ controlled: true }, "*");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "nsAppDirectoryServiceDefs.h"
|
#include "nsAppDirectoryServiceDefs.h"
|
||||||
|
|
||||||
#include "nsIURI.h"
|
#include "nsIURI.h"
|
||||||
#include "nsIIOService.h"
|
|
||||||
#include "nsIFileChannel.h"
|
#include "nsIFileChannel.h"
|
||||||
#include "nsIFile.h"
|
#include "nsIFile.h"
|
||||||
#include "nsGkAtoms.h"
|
#include "nsGkAtoms.h"
|
||||||
@ -27,6 +26,7 @@
|
|||||||
#include "mozIStorageService.h"
|
#include "mozIStorageService.h"
|
||||||
#include "nsIChannel.h"
|
#include "nsIChannel.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
@ -212,11 +212,13 @@ nsXULTemplateQueryProcessorStorage::GetDatasource(nsIArray* aDataSources,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
nsCOMPtr<nsIIOService> ioservice =
|
nsCOMPtr<nsINode> node = do_QueryInterface(aRootNode);
|
||||||
do_GetService("@mozilla.org/network/io-service;1", &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = ioservice->NewChannelFromURI(uri, getter_AddRefs(channel));
|
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||||
|
uri,
|
||||||
|
node,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel, &rv);
|
nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel, &rv);
|
||||||
|
@ -3628,11 +3628,11 @@ nsWebBrowserPersist::CreateChannelFromURI(nsIURI *aURI, nsIChannel **aChannel)
|
|||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
*aChannel = nullptr;
|
*aChannel = nullptr;
|
||||||
|
|
||||||
nsCOMPtr<nsIIOService> ioserv;
|
rv = NS_NewChannel(aChannel,
|
||||||
ioserv = do_GetIOService(&rv);
|
aURI,
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
nsContentUtils::GetSystemPrincipal(),
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
rv = ioserv->NewChannelFromURI(aURI, aChannel);
|
nsIContentPolicy::TYPE_OTHER);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
NS_ENSURE_ARG_POINTER(*aChannel);
|
NS_ENSURE_ARG_POINTER(*aChannel);
|
||||||
|
|
||||||
|
@ -1895,18 +1895,16 @@ nsPermissionManager::ImportDefaults()
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsIIOService> ioservice =
|
|
||||||
do_GetService("@mozilla.org/network/io-service;1", &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> defaultsURI;
|
nsCOMPtr<nsIURI> defaultsURI;
|
||||||
rv = NS_NewURI(getter_AddRefs(defaultsURI), defaultsURL,
|
nsresult rv = NS_NewURI(getter_AddRefs(defaultsURI), defaultsURL);
|
||||||
nullptr, nullptr, ioservice);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
rv = ioservice->NewChannelFromURI(defaultsURI, getter_AddRefs(channel));
|
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||||
|
defaultsURI,
|
||||||
|
nsContentUtils::GetSystemPrincipal(),
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsIInputStream> inputStream;
|
nsCOMPtr<nsIInputStream> inputStream;
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "nspr.h"
|
#include "nspr.h"
|
||||||
#include "nsXULAppAPI.h"
|
#include "nsXULAppAPI.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
|
||||||
extern PRLogModuleInfo *MCD;
|
extern PRLogModuleInfo *MCD;
|
||||||
|
|
||||||
@ -253,26 +254,23 @@ nsresult nsReadConfig::openAndEvaluateJSFile(const char *aFileName, int32_t obsc
|
|||||||
return rv;
|
return rv;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
|
|
||||||
if (NS_FAILED(rv))
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
nsAutoCString location("resource://gre/defaults/autoconfig/");
|
nsAutoCString location("resource://gre/defaults/autoconfig/");
|
||||||
location += aFileName;
|
location += aFileName;
|
||||||
|
|
||||||
nsCOMPtr<nsIURI> uri;
|
nsCOMPtr<nsIURI> uri;
|
||||||
rv = ioService->NewURI(location, nullptr, nullptr, getter_AddRefs(uri));
|
rv = NS_NewURI(getter_AddRefs(uri), location);
|
||||||
if (NS_FAILED(rv))
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
return rv;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
rv = ioService->NewChannelFromURI(uri, getter_AddRefs(channel));
|
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||||
if (NS_FAILED(rv))
|
uri,
|
||||||
return rv;
|
nsContentUtils::GetSystemPrincipal(),
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = channel->Open(getter_AddRefs(inStr));
|
rv = channel->Open(getter_AddRefs(inStr));
|
||||||
if (NS_FAILED(rv))
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t fs64;
|
uint64_t fs64;
|
||||||
|
@ -418,36 +418,20 @@ ClientTiledPaintedLayer::RenderLayer()
|
|||||||
ToClientLayer(GetMaskLayer())->RenderLayer();
|
ToClientLayer(GetMaskLayer())->RenderLayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// For more complex cases we need to calculate a bunch of metrics before we
|
|
||||||
// can do the paint.
|
|
||||||
BeginPaint();
|
|
||||||
if (mPaintData.mPaintFinished) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// In some cases we can take a fast path and just be done with it.
|
// In some cases we can take a fast path and just be done with it.
|
||||||
if (UseFastPath()) {
|
if (UseFastPath()) {
|
||||||
TILING_LOG("TILING %p: Taking fast-path\n", this);
|
TILING_LOG("TILING %p: Taking fast-path\n", this);
|
||||||
mValidRegion = neededRegion;
|
mValidRegion = neededRegion;
|
||||||
|
|
||||||
// Make sure that tiles that fall outside of the visible region or outside of the
|
|
||||||
// critical displayport are discarded on the first update. Also make sure that we
|
|
||||||
// only draw stuff inside the critical displayport on the first update.
|
|
||||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
|
||||||
mValidRegion.And(mValidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
|
|
||||||
invalidRegion.And(invalidRegion, LayerIntRect::ToUntyped(mPaintData.mCriticalDisplayPort));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invalidRegion.IsEmpty()) {
|
|
||||||
EndPaint();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
|
|
||||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data);
|
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, callback, data);
|
||||||
ClientManager()->Hold(this);
|
ClientManager()->Hold(this);
|
||||||
mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
|
mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
|
||||||
EndPaint();
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For more complex cases we need to calculate a bunch of metrics before we
|
||||||
|
// can do the paint.
|
||||||
|
BeginPaint();
|
||||||
|
if (mPaintData.mPaintFinished) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2137,13 +2137,8 @@ IsCoercionCall(ModuleCompiler &m, ParseNode *pn, AsmJSCoercion *coercion, ParseN
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (global->isSimdCtor() ||
|
if (global->isSimdOperation() && global->simdOperation() == AsmJSSimdOperation_check) {
|
||||||
(global->isSimdOperation() && global->simdOperation() == AsmJSSimdOperation_check))
|
switch (global->simdOperationType()) {
|
||||||
{
|
|
||||||
AsmJSSimdType type = global->isSimdCtor()
|
|
||||||
? global->simdCtorType()
|
|
||||||
: global->simdOperationType();
|
|
||||||
switch (type) {
|
|
||||||
case AsmJSSimdType_int32x4:
|
case AsmJSSimdType_int32x4:
|
||||||
*coercion = AsmJS_ToInt32x4;
|
*coercion = AsmJS_ToInt32x4;
|
||||||
return true;
|
return true;
|
||||||
@ -5572,12 +5567,7 @@ class CheckSimdVectorScalarArgs
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Second argument is the scalar
|
// Second argument is the scalar
|
||||||
Type coercedFormalType = SimdToCoercedScalarType(formalSimdType_);
|
return CheckSimdScalarArgs(formalSimdType_)(f, arg, argIndex, actualType, def);
|
||||||
if (!(actualType <= coercedFormalType)) {
|
|
||||||
return f.failf(arg, "%s is not a subtype of %s", actualType.toChars(),
|
|
||||||
coercedFormalType.toChars());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -5981,11 +5971,6 @@ CheckSimdCtorCall(FunctionCompiler &f, ParseNode *call, const ModuleCompiler::Gl
|
|||||||
{
|
{
|
||||||
MOZ_ASSERT(call->isKind(PNK_CALL));
|
MOZ_ASSERT(call->isKind(PNK_CALL));
|
||||||
|
|
||||||
AsmJSCoercion coercion;
|
|
||||||
ParseNode *argNode;
|
|
||||||
if (IsCoercionCall(f.m(), call, &coercion, &argNode))
|
|
||||||
return CheckCoercionArg(f, argNode, coercion, def, type);
|
|
||||||
|
|
||||||
AsmJSSimdType simdType = global->simdCtorType();
|
AsmJSSimdType simdType = global->simdCtorType();
|
||||||
unsigned length = SimdTypeToLength(simdType);
|
unsigned length = SimdTypeToLength(simdType);
|
||||||
DefinitionVector defs;
|
DefinitionVector defs;
|
||||||
|
@ -350,17 +350,6 @@ SimdTypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
Rooted<SimdTypeDescr*> descr(cx, &args.callee().as<SimdTypeDescr>());
|
Rooted<SimdTypeDescr*> descr(cx, &args.callee().as<SimdTypeDescr>());
|
||||||
if (args.length() == 1) {
|
|
||||||
// SIMD type used as a coercion
|
|
||||||
if (!CheckVectorObject(args[0], descr->type())) {
|
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_SIMD_NOT_A_VECTOR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
args.rval().setObject(args[0].toObject());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(size_t(static_cast<TypeDescr*>(descr)->size()) <= InlineTypedObject::MaximumSize,
|
MOZ_ASSERT(size_t(static_cast<TypeDescr*>(descr)->size()) <= InlineTypedObject::MaximumSize,
|
||||||
"inline storage is needed for using InternalHandle belows");
|
"inline storage is needed for using InternalHandle belows");
|
||||||
|
|
||||||
@ -733,27 +722,18 @@ FuncWith(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
typedef typename V::Elem Elem;
|
typedef typename V::Elem Elem;
|
||||||
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
if (args.length() != 2 || !IsVectorObject<V>(args[0]) ||
|
if (args.length() != 2 || !IsVectorObject<V>(args[0]))
|
||||||
(!args[1].isNumber() && !args[1].isBoolean()))
|
|
||||||
{
|
|
||||||
return ErrorBadArgs(cx);
|
return ErrorBadArgs(cx);
|
||||||
}
|
|
||||||
|
|
||||||
Elem *val = TypedObjectMemory<Elem *>(args[0]);
|
Elem *vec = TypedObjectMemory<Elem *>(args[0]);
|
||||||
Elem result[V::lanes];
|
Elem result[V::lanes];
|
||||||
|
|
||||||
if (args[1].isNumber()) {
|
Elem value;
|
||||||
Elem withAsNumber;
|
if (!V::toType(cx, args[1], &value))
|
||||||
if (!V::toType(cx, args[1], &withAsNumber))
|
return false;
|
||||||
return false;
|
|
||||||
for (unsigned i = 0; i < V::lanes; i++)
|
for (unsigned i = 0; i < V::lanes; i++)
|
||||||
result[i] = OpWith<Elem>::apply(i, withAsNumber, val[i]);
|
result[i] = OpWith<Elem>::apply(i, value, vec[i]);
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(args[1].isBoolean());
|
|
||||||
bool withAsBool = args[1].toBoolean();
|
|
||||||
for (unsigned i = 0; i < V::lanes; i++)
|
|
||||||
result[i] = OpWith<Elem>::apply(i, withAsBool, val[i]);
|
|
||||||
}
|
|
||||||
return StoreResult<V>(cx, args, result);
|
return StoreResult<V>(cx, args, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -827,7 +807,7 @@ Int32x4BinaryScalar(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
return ErrorBadArgs(cx);
|
return ErrorBadArgs(cx);
|
||||||
|
|
||||||
int32_t result[4];
|
int32_t result[4];
|
||||||
if (!IsVectorObject<Int32x4>(args[0]) || !args[1].isNumber())
|
if (!IsVectorObject<Int32x4>(args[0]))
|
||||||
return ErrorBadArgs(cx);
|
return ErrorBadArgs(cx);
|
||||||
|
|
||||||
int32_t *val = TypedObjectMemory<int32_t *>(args[0]);
|
int32_t *val = TypedObjectMemory<int32_t *>(args[0]);
|
||||||
@ -922,7 +902,7 @@ FuncSplat(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
typedef typename Vret::Elem RetElem;
|
typedef typename Vret::Elem RetElem;
|
||||||
|
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
if (args.length() != 1 || !args[0].isNumber())
|
if (args.length() != 1)
|
||||||
return ErrorBadArgs(cx);
|
return ErrorBadArgs(cx);
|
||||||
|
|
||||||
RetElem arg;
|
RetElem arg;
|
||||||
|
@ -273,7 +273,10 @@ struct Float32x4 {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) {
|
static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) {
|
||||||
*out = v.toNumber();
|
double d;
|
||||||
|
if (!ToNumber(cx, v, &d))
|
||||||
|
return false;
|
||||||
|
*out = float(d);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
static void setReturn(CallArgs &args, Elem value) {
|
static void setReturn(CallArgs &args, Elem value) {
|
||||||
@ -293,8 +296,7 @@ struct Float64x2 {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) {
|
static bool toType(JSContext *cx, JS::HandleValue v, Elem *out) {
|
||||||
*out = v.toNumber();
|
return ToNumber(cx, v, out);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
static void setReturn(CallArgs &args, Elem value) {
|
static void setReturn(CallArgs &args, Elem value) {
|
||||||
args.rval().setDouble(JS::CanonicalizeNaN(value));
|
args.rval().setDouble(JS::CanonicalizeNaN(value));
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,8 +28,10 @@ function assertEqX4(real, expected, assertFunc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
// Load / Store
|
// Load / Store
|
||||||
var IMPORTS = USE_ASM + 'var H=new glob.Uint8Array(heap); var i4=glob.SIMD.int32x4; var load=i4.load; var store=i4.store;';
|
var IMPORTS = USE_ASM + 'var H=new glob.Uint8Array(heap); var i4=glob.SIMD.int32x4; var ci4=i4.check; var load=i4.load; var store=i4.store;';
|
||||||
|
|
||||||
// Bad number of args
|
// Bad number of args
|
||||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load();} return f");
|
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load();} return f");
|
||||||
@ -63,9 +65,9 @@ assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (IN
|
|||||||
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 15) + ");} return f");
|
assertAsmTypeFail('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 15) + ");} return f");
|
||||||
asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 16) + ");} return f");
|
asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f(){load(H, " + (INT32_MAX + 1 - 16) + ");} return f");
|
||||||
|
|
||||||
assertAsmLinkFail(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return i4(load(H, " + (BUF_MIN - 15) + "));} return f"), this, {}, buf);
|
assertAsmLinkFail(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + (BUF_MIN - 15) + "));} return f"), this, {}, buf);
|
||||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return i4(load(H, " + (BUF_MIN - 16) + "));} return f"), this, {}, buf)(), [4, 3, 2, 1]);
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + (BUF_MIN - 16) + "));} return f"), this, {}, buf)(), [4, 3, 2, 1]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return i4(load(H, " + BUF_MIN + " - 16 | 0));} return f"), this, {}, buf)(), [4, 3, 2, 1]);
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', IMPORTS + "function f() {return ci4(load(H, " + BUF_MIN + " - 16 | 0));} return f"), this, {}, buf)(), [4, 3, 2, 1]);
|
||||||
|
|
||||||
var CONSTANT_INDEX = 42;
|
var CONSTANT_INDEX = 42;
|
||||||
var CONSTANT_BYTE_INDEX = CONSTANT_INDEX << 2;
|
var CONSTANT_BYTE_INDEX = CONSTANT_INDEX << 2;
|
||||||
@ -78,33 +80,35 @@ var loadStoreCode = `
|
|||||||
var i4 = glob.SIMD.int32x4;
|
var i4 = glob.SIMD.int32x4;
|
||||||
var i4load = i4.load;
|
var i4load = i4.load;
|
||||||
var i4store = i4.store;
|
var i4store = i4.store;
|
||||||
|
var ci4 = i4.check;
|
||||||
|
|
||||||
var f4 = glob.SIMD.float32x4;
|
var f4 = glob.SIMD.float32x4;
|
||||||
var f4load = f4.load;
|
var f4load = f4.load;
|
||||||
var f4store = f4.store;
|
var f4store = f4.store;
|
||||||
|
var cf4 = f4.check;
|
||||||
|
|
||||||
function f32l(i) { i=i|0; return f4(f4load(H, i|0)); }
|
function f32l(i) { i=i|0; return cf4(f4load(H, i|0)); }
|
||||||
function f32lcst() { return f4(f4load(H, ${CONSTANT_BYTE_INDEX})); }
|
function f32lcst() { return cf4(f4load(H, ${CONSTANT_BYTE_INDEX})); }
|
||||||
function f32s(i, vec) { i=i|0; vec=f4(vec); f4store(H, i|0, vec); }
|
function f32s(i, vec) { i=i|0; vec=cf4(vec); f4store(H, i|0, vec); }
|
||||||
function f32scst(vec) { vec=f4(vec); f4store(H, ${CONSTANT_BYTE_INDEX}, vec); }
|
function f32scst(vec) { vec=cf4(vec); f4store(H, ${CONSTANT_BYTE_INDEX}, vec); }
|
||||||
|
|
||||||
function i32l(i) { i=i|0; return i4(i4load(H, i|0)); }
|
function i32l(i) { i=i|0; return ci4(i4load(H, i|0)); }
|
||||||
function i32lcst() { return i4(i4load(H, ${CONSTANT_BYTE_INDEX})); }
|
function i32lcst() { return ci4(i4load(H, ${CONSTANT_BYTE_INDEX})); }
|
||||||
function i32s(i, vec) { i=i|0; vec=i4(vec); i4store(H, i|0, vec); }
|
function i32s(i, vec) { i=i|0; vec=ci4(vec); i4store(H, i|0, vec); }
|
||||||
function i32scst(vec) { vec=i4(vec); i4store(H, ${CONSTANT_BYTE_INDEX}, vec); }
|
function i32scst(vec) { vec=ci4(vec); i4store(H, ${CONSTANT_BYTE_INDEX}, vec); }
|
||||||
|
|
||||||
function f32lbndcheck(i) {
|
function f32lbndcheck(i) {
|
||||||
i=i|0;
|
i=i|0;
|
||||||
if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX};
|
if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX};
|
||||||
if ((i|0) < 0) i = 0;
|
if ((i|0) < 0) i = 0;
|
||||||
return f4(f4load(H, i|0));
|
return cf4(f4load(H, i|0));
|
||||||
}
|
}
|
||||||
function f32sbndcheck(i, vec) {
|
function f32sbndcheck(i, vec) {
|
||||||
i=i|0;
|
i=i|0;
|
||||||
vec=f4(vec);
|
vec=cf4(vec);
|
||||||
if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX};
|
if ((i|0) > ${CONSTANT_BYTE_INDEX}) i=${CONSTANT_BYTE_INDEX};
|
||||||
if ((i|0) < 0) i = 0;
|
if ((i|0) < 0) i = 0;
|
||||||
return f4(f4store(H, i|0, vec));
|
return cf4(f4store(H, i|0, vec));
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -169,12 +173,12 @@ var code = `
|
|||||||
x = (x>>0) < 0 ? 0 : x;
|
x = (x>>0) < 0 ? 0 : x;
|
||||||
// ptr value gets a precise range but the bounds check shouldn't get
|
// ptr value gets a precise range but the bounds check shouldn't get
|
||||||
// eliminated.
|
// eliminated.
|
||||||
return f4(f4l(u8, 0xFFFA + x | 0));
|
return f4l(u8, 0xFFFA + x | 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return g;
|
return g;
|
||||||
`;
|
`;
|
||||||
assertThrowsInstanceOf(() =>asmLink(asmCompile('glob', 'ffi', 'heap', code), this, {}, new ArrayBuffer(0x10000))(0), RangeError);
|
assertThrowsInstanceOf(() => asmLink(asmCompile('glob', 'ffi', 'heap', code), this, {}, new ArrayBuffer(0x10000))(0), RangeError);
|
||||||
|
|
||||||
// Float32x4.store
|
// Float32x4.store
|
||||||
function f32s(n, v) { return m.f32s((n|0) << 2 | 0, v); };
|
function f32s(n, v) { return m.f32s((n|0) << 2 | 0, v); };
|
||||||
@ -274,6 +278,7 @@ function MakeCodeFor(typeName) {
|
|||||||
return `
|
return `
|
||||||
"use asm";
|
"use asm";
|
||||||
var type = glob.SIMD.${typeName};
|
var type = glob.SIMD.${typeName};
|
||||||
|
var c = type.check;
|
||||||
|
|
||||||
var lx = type.loadX;
|
var lx = type.loadX;
|
||||||
var lxy = type.loadXY;
|
var lxy = type.loadXY;
|
||||||
@ -293,13 +298,13 @@ function MakeCodeFor(typeName) {
|
|||||||
function loadCstXY() { return lxy(u8, 41 << 2); }
|
function loadCstXY() { return lxy(u8, 41 << 2); }
|
||||||
function loadCstXYZ() { return lxyz(u8, 41 << 2); }
|
function loadCstXYZ() { return lxyz(u8, 41 << 2); }
|
||||||
|
|
||||||
function storeX(i, x) { i=i|0; x=type(x); return sx(u8, i, x); }
|
function storeX(i, x) { i=i|0; x=c(x); return sx(u8, i, x); }
|
||||||
function storeXY(i, x) { i=i|0; x=type(x); return sxy(u8, i, x); }
|
function storeXY(i, x) { i=i|0; x=c(x); return sxy(u8, i, x); }
|
||||||
function storeXYZ(i, x) { i=i|0; x=type(x); return sxyz(u8, i, x); }
|
function storeXYZ(i, x) { i=i|0; x=c(x); return sxyz(u8, i, x); }
|
||||||
|
|
||||||
function storeCstX(x) { x=type(x); return sx(u8, 41 << 2, x); }
|
function storeCstX(x) { x=c(x); return sx(u8, 41 << 2, x); }
|
||||||
function storeCstXY(x) { x=type(x); return sxy(u8, 41 << 2, x); }
|
function storeCstXY(x) { x=c(x); return sxy(u8, 41 << 2, x); }
|
||||||
function storeCstXYZ(x) { x=type(x); return sxyz(u8, 41 << 2, x); }
|
function storeCstXYZ(x) { x=c(x); return sxyz(u8, 41 << 2, x); }
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loadX: loadX,
|
loadX: loadX,
|
||||||
@ -505,3 +510,5 @@ TestPartialLoads(mint32x4, i32,
|
|||||||
TestPartialStores(mint32x4, i32, 'int32x4', 42, -3, 13, 37);
|
TestPartialStores(mint32x4, i32, 'int32x4', 42, -3, 13, 37);
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
} catch (e) { print('stack: ', e.stack); throw e }
|
||||||
|
@ -10,10 +10,12 @@ if (!isSimdAvailable() || typeof SIMD === 'undefined') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const I32 = 'var i4 = glob.SIMD.int32x4;'
|
const I32 = 'var i4 = glob.SIMD.int32x4;'
|
||||||
|
const CI32 = 'var ci4 = i4.check;'
|
||||||
const I32A = 'var i4a = i4.add;'
|
const I32A = 'var i4a = i4.add;'
|
||||||
const I32S = 'var i4s = i4.sub;'
|
const I32S = 'var i4s = i4.sub;'
|
||||||
const I32M = 'var i4m = i4.mul;'
|
const I32M = 'var i4m = i4.mul;'
|
||||||
const F32 = 'var f4 = glob.SIMD.float32x4;'
|
const F32 = 'var f4 = glob.SIMD.float32x4;'
|
||||||
|
const CF32 = 'var cf4 = f4.check;'
|
||||||
const F32A = 'var f4a = f4.add;'
|
const F32A = 'var f4a = f4.add;'
|
||||||
const F32S = 'var f4s = f4.sub;'
|
const F32S = 'var f4s = f4.sub;'
|
||||||
const F32M = 'var f4m = f4.mul;'
|
const F32M = 'var f4m = f4.mul;'
|
||||||
@ -37,15 +39,15 @@ function assertEqX4(real, expected, assertFunc) {
|
|||||||
|
|
||||||
function CheckI4(header, code, expected) {
|
function CheckI4(header, code, expected) {
|
||||||
// code needs to contain a local called x
|
// code needs to contain a local called x
|
||||||
header = USE_ASM + I32 + F32 + header;
|
header = USE_ASM + I32 + CI32 + F32 + header;
|
||||||
var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return i4(x)} return f'), this)();
|
var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return ci4(x)} return f'), this)();
|
||||||
assertEqX4(observed, expected);
|
assertEqX4(observed, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CheckF4(header, code, expected) {
|
function CheckF4(header, code, expected) {
|
||||||
// code needs to contain a local called x
|
// code needs to contain a local called x
|
||||||
header = USE_ASM + F32 + header;
|
header = USE_ASM + F32 + CF32 + header;
|
||||||
var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return f4(x)} return f'), this)();
|
var observed = asmLink(asmCompile('glob', header + ';function f() {' + code + ';return cf4(x)} return f'), this)();
|
||||||
assertEqX4(observed, expected.map(Math.fround));
|
assertEqX4(observed, expected.map(Math.fround));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,27 +121,27 @@ assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(i) {var x=f4(1,2,3,i
|
|||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return +i4(1,2,3,4)} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return +i4(1,2,3,4)} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4)|0} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4)|0} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {return f32(i4(1,2,3,4))} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {return f32(i4(1,2,3,4))} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f() {return f4(i4(1,2,3,4))} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "function f() {return cf4(i4(1,2,3,4))} return f");
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return +f4(1,2,3,4)} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return +f4(1,2,3,4)} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4)|0} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4)|0} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + FROUND + "function f() {return f32(f4(1,2,3,4))} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + FROUND + "function f() {return f32(f4(1,2,3,4))} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f() {return i4(f4(1,2,3,4))} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + "function f() {return ci4(f4(1,2,3,4))} return f");
|
||||||
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {return i4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {return i4(i4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f() {return ci4(i4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(1,2,3,4);} return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {return f4(f4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f() {return cf4(f4(1,2,3,4));} return f"), this)(), [1, 2, 3, 4]);
|
||||||
|
|
||||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {i4(1,2,3,4);} return f"), this)(), undefined);
|
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {i4(1,2,3,4);} return f"), this)(), undefined);
|
||||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {f4(1,2,3,4);} return f"), this)(), undefined);
|
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {f4(1,2,3,4);} return f"), this)(), undefined);
|
||||||
|
|
||||||
// Int32x4 ctor should accept int?
|
// Int32x4 ctor should accept int?
|
||||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return i4(i4(i32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [0, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + CI32 + "var i32=new glob.Int32Array(heap); function f(i) {i=i|0; return ci4(i4(i32[i>>2], 2, 3, 4))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [0, 2, 3, 4]);
|
||||||
// Float32x4 ctor should accept floatish (i.e. float || float? || floatish) and doublit
|
// Float32x4 ctor should accept floatish (i.e. float || float? || floatish) and doublit
|
||||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + FROUND + "var h=new glob.Float32Array(heap); function f(i) {i=i|0; return f4(f4(h[i>>2], f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + FROUND + "var h=new glob.Float32Array(heap); function f(i) {i=i|0; return cf4(f4(h[i>>2], f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [NaN, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + "function f(i) {i=i|0; return f4(f4(f32(1) + f32(2), f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + FROUND + "function f(i) {i=i|0; return cf4(f4(f32(1) + f32(2), f32(2), f32(3), f32(4)))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + FROUND + "function f(i) {i=i|0; return f4(f4(f32(1) + f32(2), 2.0, 3.0, 4.0))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + FROUND + "function f(i) {i=i|0; return cf4(f4(f32(1) + f32(2), 2.0, 3.0, 4.0))} return f"), this, {}, new ArrayBuffer(0x10000))(0x20000), [3, 2, 3, 4]);
|
||||||
|
|
||||||
// 1.3.2 Reading values out of lanes
|
// 1.3.2 Reading values out of lanes
|
||||||
assertAsmTypeFail('glob', USE_ASM + "function f() {var x=1; return x.y | 0;} return f");
|
assertAsmTypeFail('glob', USE_ASM + "function f() {var x=1; return x.y | 0;} return f");
|
||||||
@ -240,73 +242,63 @@ assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4)
|
|||||||
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "function f() {var x=f4(1,2,3,4); var y=i4(1,2,3,4); x=1?y:y;} return f");
|
||||||
|
|
||||||
CheckF4('', 'var x=f4(1,2,3,4); var y=f4(4,3,2,1); x=3?y:x', [4, 3, 2, 1]);
|
CheckF4('', 'var x=f4(1,2,3,4); var y=f4(4,3,2,1); x=3?y:x', [4, 3, 2, 1]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(x) {x=x|0; var v=f4(1,2,3,4); var w=f4(5,6,7,8); return f4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=x|0; var v=f4(1,2,3,4); var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(v) {v=f4(v); var w=f4(5,6,7,8); return f4(4?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4)), [5,6,7,8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v) {v=cf4(v); var w=f4(5,6,7,8); return cf4(4?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4)), [5,6,7,8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(v, x) {v=f4(v); x=x|0; var w=f4(5,6,7,8); return f4(x?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4), 0), [1,2,3,4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(v, x) {v=cf4(v); x=x|0; var w=f4(5,6,7,8); return cf4(x?w:v);} return f"), this)(SIMD.float32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||||
|
|
||||||
CheckI4('', 'var x=i4(1,2,3,4); var y=i4(4,3,2,1); x=(x.x|0)?y:x', [4, 3, 2, 1]);
|
CheckI4('', 'var x=i4(1,2,3,4); var y=i4(4,3,2,1); x=(x.x|0)?y:x', [4, 3, 2, 1]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(x) {x=x|0; var v=i4(1,2,3,4); var w=i4(5,6,7,8); return i4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=x|0; var v=i4(1,2,3,4); var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(1), [5,6,7,8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(v) {v=i4(v); var w=i4(5,6,7,8); return i4(4?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4)), [5,6,7,8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v) {v=ci4(v); var w=i4(5,6,7,8); return ci4(4?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4)), [5,6,7,8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(v, x) {v=i4(v); x=x|0; var w=i4(5,6,7,8); return i4(x?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4), 0), [1,2,3,4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(v, x) {v=ci4(v); x=x|0; var w=i4(5,6,7,8); return ci4(x?w:v);} return f"), this)(SIMD.int32x4(1,2,3,4), 0), [1,2,3,4]);
|
||||||
|
|
||||||
// 1.3.4 Return values
|
// 1.3.4 Return values
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=1; return i4(x)} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1; return ci4(x)} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=1; return i4(x + x)} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1; return ci4(x + x)} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f() {var x=1.; return i4(x)} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {var x=1.; return ci4(x)} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f() {var x=f32(1.); return i4(x)} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + "function f() {var x=f32(1.); return ci4(x)} return f");
|
||||||
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f() {var x=i4(1,2,3,4); return i4(x)} return f"), this)(), [1,2,3,4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f() {var x=i4(1,2,3,4); return ci4(x)} return f"), this)(), [1,2,3,4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f() {var x=f4(1,2,3,4); return f4(x)} return f"), this)(), [1,2,3,4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f() {var x=f4(1,2,3,4); return cf4(x)} return f"), this)(), [1,2,3,4]);
|
||||||
|
|
||||||
// 1.3.5 Coerce and pass arguments
|
// 1.3.5 Coerce and pass arguments
|
||||||
// Via check
|
// Via check
|
||||||
const CHECK_I32 = 'var c=i4.check;';
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4();} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); ci4(x, x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + CHECK_I32 + "function f() {c();} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4(1);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + CHECK_I32 + "function f(x) {x=i4(x); c(x, x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f() {ci4(1.);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + CHECK_I32 + "function f() {c(1);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + "function f() {ci4(f32(1.));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + CHECK_I32 + "function f() {c(1.);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + CF32 + "function f(x) {x=cf4(x); ci4(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + CHECK_I32 + FROUND + "function f() {c(f32(1.));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return 1 + ci4(x) | 0;} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + CHECK_I32 + F32 + "function f(x) {x=f4(x); c(x);} return f");
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + CHECK_I32 + "function f(x) {x=i4(x); return 1 + c(x) | 0;} return f");
|
|
||||||
|
|
||||||
var i32x4 = SIMD.int32x4(1, 3, 3, 7);
|
var i32x4 = SIMD.int32x4(1, 3, 3, 7);
|
||||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + CHECK_I32 + "function f(x) {x=c(x)} return f"), this)(i32x4), undefined);
|
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x)} return f"), this)(i32x4), undefined);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CHECK_I32 + "function f(x) {x=i4(x); return c(x);} return f"), this)(i32x4), [1,3,3,7]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this)(i32x4), [1,3,3,7]);
|
||||||
|
|
||||||
const CHECK_F32 = 'var c=f4.check;';
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4();} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); cf4(x, x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + CHECK_F32 + "function f() {c();} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4(1);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + CHECK_F32 + "function f(x) {x=f4(x); c(x, x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f() {cf4(1.);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + CHECK_F32 + "function f() {c(1);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + FROUND + "function f() {cf4(f32(1.));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + CHECK_F32 + "function f() {c(1.);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + F32 + CF32 + "function f(x) {x=cf4(x); cf4(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + CHECK_F32 + FROUND + "function f() {c(f32(1.));} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return 1 + cf4(x) | 0;} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + CHECK_F32 + I32 + "function f(x) {x=i4(x); c(x);} return f");
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + CHECK_F32 + "function f(x) {x=f4(x); return 1 + c(x) | 0;} return f");
|
|
||||||
|
|
||||||
var f32x4 = SIMD.float32x4(13.37, 42.42, -0, NaN);
|
var f32x4 = SIMD.float32x4(13.37, 42.42, -0, NaN);
|
||||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + CHECK_F32 + "function f(x) {x=c(x)} return f"), this)(f32x4), undefined);
|
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x)} return f"), this)(f32x4), undefined);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CHECK_F32 + "function f(x) {x=c(x); return c(x);} return f"), this)(f32x4),
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return cf4(x);} return f"), this)(f32x4), [13.37, 42.42, -0, NaN].map(Math.fround));
|
||||||
[Math.fround(13.37), Math.fround(42.42), -0, NaN]);
|
|
||||||
|
|
||||||
// Legacy coercions
|
// Legacy coercions
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4();} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4();} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(1,2,3,4);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {x=i4(1,2,3,4);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x,y) {x=i4(y);y=+y} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x,y) {x=i4(y);y=+y} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return i4(x);} return f");
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return +i4(1,2,3,4)} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return +i4(1,2,3,4)} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return 0|i4(1,2,3,4)} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "function f(x) {return 0|i4(1,2,3,4)} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f(x) {return f32(i4(1,2,3,4))} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + "function f(x) {return f32(i4(1,2,3,4))} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(x) {return f4(i4(1,2,3,4))} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "function f(x) {return f4(i4(1,2,3,4))} return f");
|
||||||
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return f4(x);} return f");
|
||||||
|
|
||||||
var i32x4 = SIMD.int32x4(1, 3, 3, 7);
|
|
||||||
assertEq(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(x) {x=i4(x)} return f"), this)(i32x4), undefined);
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + "function f(x) {x=i4(x); return i4(x);} return f"), this)(i32x4), [1,3,3,7]);
|
|
||||||
|
|
||||||
var f32x4 = SIMD.float32x4(13.37, 42.42, -0, NaN);
|
|
||||||
assertEq(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(x) {x=f4(x)} return f"), this)(f32x4), undefined);
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + "function f(x) {x=f4(x); return f4(x);} return f"), this)(f32x4),
|
|
||||||
[Math.fround(13.37), Math.fround(42.42), -0, NaN]);
|
|
||||||
|
|
||||||
function assertCaught(f) {
|
function assertCaught(f) {
|
||||||
var caught = false;
|
var caught = false;
|
||||||
@ -320,14 +312,14 @@ function assertCaught(f) {
|
|||||||
assertEq(caught, true);
|
assertEq(caught, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + F32 + "function f(x) {x=f4(x); return f4(x);} return f"), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + "function f(x) {x=cf4(x); return cf4(x);} return f"), this);
|
||||||
assertCaught(f);
|
assertCaught(f);
|
||||||
assertCaught(f, 1);
|
assertCaught(f, 1);
|
||||||
assertCaught(f, {});
|
assertCaught(f, {});
|
||||||
assertCaught(f, "I sincerely am a SIMD typed object.");
|
assertCaught(f, "I sincerely am a SIMD typed object.");
|
||||||
assertCaught(f, SIMD.int32x4(1,2,3,4));
|
assertCaught(f, SIMD.int32x4(1,2,3,4));
|
||||||
|
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + "function f(x) {x=i4(x); return i4(x);} return f"), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + "function f(x) {x=ci4(x); return ci4(x);} return f"), this);
|
||||||
assertCaught(f);
|
assertCaught(f);
|
||||||
assertCaught(f, 1);
|
assertCaught(f, 1);
|
||||||
assertCaught(f, {});
|
assertCaught(f, {});
|
||||||
@ -345,8 +337,8 @@ assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f(
|
|||||||
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; x=+g;} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; x=+g;} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); x=f32(g);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); x=f32(g);} return f");
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); x=i4(g);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CI32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); x=ci4(g);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); x=f4(g);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); x=cf4(g);} return f");
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0; function f() {var x=i4(1,2,3,4); x=g|0;} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0; function f() {var x=i4(1,2,3,4); x=g|0;} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0.; function f() {var x=i4(1,2,3,4); x=+g;} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "var g=0.; function f() {var x=i4(1,2,3,4); x=+g;} return f");
|
||||||
@ -372,10 +364,10 @@ assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f(
|
|||||||
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; g=+x;} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); function f() {var x=4.; g=+x;} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); g=f32(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + "var g=f4(1., 2., 3., 4.); var f32=glob.Math.fround; function f() {var x=f32(4.); g=f32(x);} return f");
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=i4(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CI32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=ci4(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=f4(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + I32 + CF32 + "var g=f4(1., 2., 3., 4.); function f() {var x=i4(1,2,3,4); g=cf4(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=f4(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=cf4(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=i4(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + "var g=i4(1,2,3,4); function f() {var x=f4(1.,2.,3.,4.); g=ci4(x);} return f");
|
||||||
|
|
||||||
CheckI4('var x=i4(0,0,0,0);', 'x=i4(1,2,3,4)', [1,2,3,4]);
|
CheckI4('var x=i4(0,0,0,0);', 'x=i4(1,2,3,4)', [1,2,3,4]);
|
||||||
CheckF4('var x=f4(0.,0.,0.,0.);', 'x=f4(5.,3.,4.,2.)', [5,3,4,2]);
|
CheckF4('var x=f4(0.,0.,0.,0.);', 'x=f4(5.,3.,4.,2.)', [5,3,4,2]);
|
||||||
@ -385,32 +377,32 @@ CheckF4('var x=f4(0,0,0,0); var y=42; var z=3.9; var w=13.37', 'x=f4(1,2,3,4); y
|
|||||||
|
|
||||||
// 1.3.6.2 Imported globals
|
// 1.3.6.2 Imported globals
|
||||||
// Read
|
// Read
|
||||||
var int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + "var g=i4(ffi.g); function f() {return i4(g)} return f"), this, {g: SIMD.int32x4(1,2,3,4)})();
|
var int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: SIMD.int32x4(1,2,3,4)})();
|
||||||
assertEq(int32x4.x, 1);
|
assertEq(int32x4.x, 1);
|
||||||
assertEq(int32x4.y, 2);
|
assertEq(int32x4.y, 2);
|
||||||
assertEq(int32x4.z, 3);
|
assertEq(int32x4.z, 3);
|
||||||
assertEq(int32x4.w, 4);
|
assertEq(int32x4.w, 4);
|
||||||
|
|
||||||
for (var v of [1, {}, "totally legit SIMD variable", SIMD.float32x4(1,2,3,4)])
|
for (var v of [1, {}, "totally legit SIMD variable", SIMD.float32x4(1,2,3,4)])
|
||||||
assertCaught(asmCompile('glob', 'ffi', USE_ASM + I32 + "var g=i4(ffi.g); function f() {return i4(g)} return f"), this, {g: v});
|
assertCaught(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {return ci4(g)} return f"), this, {g: v});
|
||||||
|
|
||||||
var float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + "var g=f4(ffi.g); function f() {return f4(g)} return f"), this, {g: SIMD.float32x4(1,2,3,4)})();
|
var float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: SIMD.float32x4(1,2,3,4)})();
|
||||||
assertEq(float32x4.x, 1);
|
assertEq(float32x4.x, 1);
|
||||||
assertEq(float32x4.y, 2);
|
assertEq(float32x4.y, 2);
|
||||||
assertEq(float32x4.z, 3);
|
assertEq(float32x4.z, 3);
|
||||||
assertEq(float32x4.w, 4);
|
assertEq(float32x4.w, 4);
|
||||||
|
|
||||||
for (var v of [1, {}, "totally legit SIMD variable", SIMD.int32x4(1,2,3,4)])
|
for (var v of [1, {}, "totally legit SIMD variable", SIMD.int32x4(1,2,3,4)])
|
||||||
assertCaught(asmCompile('glob', 'ffi', USE_ASM + F32 + "var g=f4(ffi.g); function f() {return f4(g)} return f"), this, {g: v});
|
assertCaught(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {return cf4(g)} return f"), this, {g: v});
|
||||||
|
|
||||||
// Write
|
// Write
|
||||||
var int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + "var g=i4(ffi.g); function f() {g=i4(4,5,6,7); return i4(g)} return f"), this, {g: SIMD.int32x4(1,2,3,4)})();
|
var int32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + I32 + CI32 + "var g=ci4(ffi.g); function f() {g=i4(4,5,6,7); return ci4(g)} return f"), this, {g: SIMD.int32x4(1,2,3,4)})();
|
||||||
assertEq(int32x4.x, 4);
|
assertEq(int32x4.x, 4);
|
||||||
assertEq(int32x4.y, 5);
|
assertEq(int32x4.y, 5);
|
||||||
assertEq(int32x4.z, 6);
|
assertEq(int32x4.z, 6);
|
||||||
assertEq(int32x4.w, 7);
|
assertEq(int32x4.w, 7);
|
||||||
|
|
||||||
var float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + "var g=f4(ffi.g); function f() {g=f4(4.,5.,6.,7.); return f4(g)} return f"), this, {g: SIMD.float32x4(1,2,3,4)})();
|
var float32x4 = asmLink(asmCompile('glob', 'ffi', USE_ASM + F32 + CF32 + "var g=cf4(ffi.g); function f() {g=f4(4.,5.,6.,7.); return cf4(g)} return f"), this, {g: SIMD.float32x4(1,2,3,4)})();
|
||||||
assertEq(float32x4.x, 4);
|
assertEq(float32x4.x, 4);
|
||||||
assertEq(float32x4.y, 5);
|
assertEq(float32x4.y, 5);
|
||||||
assertEq(float32x4.z, 6);
|
assertEq(float32x4.z, 6);
|
||||||
@ -458,31 +450,31 @@ assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0
|
|||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=f4a(x, y);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); y=f4a(x, y);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); x=f4a(y, y);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32A + "function f() {var x=i4(0,0,0,0); var y=f4(4,3,2,1); x=f4a(y, y);} return f");
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0; y=i4(x,x)|0} return f');
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0; y=i4a(x,x)|0} return f');
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0.; y=+i4(x,x)} return f');
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32A + 'function f() {var x=i4(1,2,3,4); var y=0.; y=+i4a(x,x)} return f');
|
||||||
|
|
||||||
CheckI4(I32A, 'var z=i4(1,2,3,4); var y=i4(0,1,0,3); var x=i4(0,0,0,0); x=i4a(z,y)', [1,3,3,7]);
|
CheckI4(I32A, 'var z=i4(1,2,3,4); var y=i4(0,1,0,3); var x=i4(0,0,0,0); x=i4a(z,y)', [1,3,3,7]);
|
||||||
CheckI4(I32A, 'var x=i4(2,3,4,5); var y=i4(0,1,0,3); x=i4a(x,y)', [2,4,4,8]);
|
CheckI4(I32A, 'var x=i4(2,3,4,5); var y=i4(0,1,0,3); x=i4a(x,y)', [2,4,4,8]);
|
||||||
CheckI4(I32A, 'var x=i4(1,2,3,4); x=i4a(x,x)', [2,4,6,8]);
|
CheckI4(I32A, 'var x=i4(1,2,3,4); x=i4a(x,x)', [2,4,6,8]);
|
||||||
CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=i4a(x,y)', [INT32_MIN,3,3,7]);
|
CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=i4a(x,y)', [INT32_MIN,3,3,7]);
|
||||||
CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=i4(i4a(x,y))', [INT32_MIN,3,3,7]);
|
CheckI4(I32A, 'var x=i4(' + INT32_MAX + ',2,3,4); var y=i4(1,1,0,3); x=ci4(i4a(x,y))', [INT32_MIN,3,3,7]);
|
||||||
|
|
||||||
CheckF4(F32A, 'var x=f4(1,2,3,4); x=f4a(x,x)', [2,4,6,8]);
|
CheckF4(F32A, 'var x=f4(1,2,3,4); x=f4a(x,x)', [2,4,6,8]);
|
||||||
CheckF4(F32A, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [5,5,8,6]);
|
CheckF4(F32A, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [5,5,8,6]);
|
||||||
CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [Math.fround(13.37) + 4,5,8,6]);
|
CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4a(x,y)', [Math.fround(13.37) + 4,5,8,6]);
|
||||||
CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4(f4a(x,y))', [Math.fround(13.37) + 4,5,8,6]);
|
CheckF4(F32A, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4a(x,y))', [Math.fround(13.37) + 4,5,8,6]);
|
||||||
|
|
||||||
// 2.3.2. Subtracts
|
// 2.3.2. Subtracts
|
||||||
CheckI4(I32S, 'var x=i4(1,2,3,4); var y=i4(-1,1,0,2); x=i4s(x,y)', [2,1,3,2]);
|
CheckI4(I32S, 'var x=i4(1,2,3,4); var y=i4(-1,1,0,2); x=i4s(x,y)', [2,1,3,2]);
|
||||||
CheckI4(I32S, 'var x=i4(5,4,3,2); var y=i4(1,2,3,4); x=i4s(x,y)', [4,2,0,-2]);
|
CheckI4(I32S, 'var x=i4(5,4,3,2); var y=i4(1,2,3,4); x=i4s(x,y)', [4,2,0,-2]);
|
||||||
CheckI4(I32S, 'var x=i4(1,2,3,4); x=i4s(x,x)', [0,0,0,0]);
|
CheckI4(I32S, 'var x=i4(1,2,3,4); x=i4s(x,x)', [0,0,0,0]);
|
||||||
CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=i4s(x,y)', [INT32_MAX,1,3,1]);
|
CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=i4s(x,y)', [INT32_MAX,1,3,1]);
|
||||||
CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=i4(i4s(x,y))', [INT32_MAX,1,3,1]);
|
CheckI4(I32S, 'var x=i4(' + INT32_MIN + ',2,3,4); var y=i4(1,1,0,3); x=ci4(i4s(x,y))', [INT32_MAX,1,3,1]);
|
||||||
|
|
||||||
CheckF4(F32S, 'var x=f4(1,2,3,4); x=f4s(x,x)', [0,0,0,0]);
|
CheckF4(F32S, 'var x=f4(1,2,3,4); x=f4s(x,x)', [0,0,0,0]);
|
||||||
CheckF4(F32S, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [-3,-1,-2,2]);
|
CheckF4(F32S, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [-3,-1,-2,2]);
|
||||||
CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [Math.fround(13.37) - 4,-1,-2,2]);
|
CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4s(x,y)', [Math.fround(13.37) - 4,-1,-2,2]);
|
||||||
CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4(f4s(x,y))', [Math.fround(13.37) - 4,-1,-2,2]);
|
CheckF4(F32S, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4s(x,y))', [Math.fround(13.37) - 4,-1,-2,2]);
|
||||||
|
|
||||||
// 2.3.3. Multiplications / Divisions
|
// 2.3.3. Multiplications / Divisions
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "var f4d=i4.div; function f() {} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "var f4d=i4.div; function f() {} return f");
|
||||||
@ -501,11 +493,11 @@ CheckI4(I32M, 'var x=i4(1,2,3,4); x=i4m(x,x)', [1,4,9,16]);
|
|||||||
CheckF4(F32M, 'var x=f4(1,2,3,4); x=f4m(x,x)', [1,4,9,16]);
|
CheckF4(F32M, 'var x=f4(1,2,3,4); x=f4m(x,x)', [1,4,9,16]);
|
||||||
CheckF4(F32M, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [4,6,15,8]);
|
CheckF4(F32M, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [4,6,15,8]);
|
||||||
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [Math.fround(13.37) * 4,6,15,8]);
|
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4m(x,y)', [Math.fround(13.37) * 4,6,15,8]);
|
||||||
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=f4(f4m(x,y))', [Math.fround(13.37) * 4,6,15,8]);
|
CheckF4(F32M, 'var x=f4(13.37,2,3,4); var y=f4(4,3,5,2); x=cf4(f4m(x,y))', [Math.fround(13.37) * 4,6,15,8]);
|
||||||
|
|
||||||
var f32x4 = SIMD.float32x4(0, NaN, -0, NaN);
|
var f32x4 = SIMD.float32x4(0, NaN, -0, NaN);
|
||||||
var another = SIMD.float32x4(NaN, -1, -0, NaN);
|
var another = SIMD.float32x4(NaN, -1, -0, NaN);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32M + "function f(x, y) {x=f4(x); y=f4(y); x=f4m(x,y); return f4(x);} return f"), this)(f32x4, another), [NaN, NaN, 0, NaN]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32M + CF32 + "function f(x, y) {x=cf4(x); y=cf4(y); x=f4m(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, 0, NaN]);
|
||||||
|
|
||||||
CheckF4(F32D, 'var x=f4(1,2,3,4); x=f4d(x,x)', [1,1,1,1]);
|
CheckF4(F32D, 'var x=f4(1,2,3,4); x=f4d(x,x)', [1,1,1,1]);
|
||||||
CheckF4(F32D, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4d(x,y)', [1/4,2/3,3/5,2]);
|
CheckF4(F32D, 'var x=f4(1,2,3,4); var y=f4(4,3,5,2); x=f4d(x,y)', [1/4,2/3,3/5,2]);
|
||||||
@ -513,11 +505,11 @@ CheckF4(F32D, 'var x=f4(13.37,1,1,4); var y=f4(4,0,-0.,2); x=f4d(x,y)', [Math.fr
|
|||||||
|
|
||||||
var f32x4 = SIMD.float32x4(0, 0, -0, NaN);
|
var f32x4 = SIMD.float32x4(0, 0, -0, NaN);
|
||||||
var another = SIMD.float32x4(0, -0, 0, 0);
|
var another = SIMD.float32x4(0, -0, 0, 0);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32D + "function f(x,y) {x=f4(x); y=f4(y); x=f4d(x,y); return f4(x);} return f"), this)(f32x4, another), [NaN, NaN, NaN, NaN]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32D + CF32 + "function f(x,y) {x=cf4(x); y=cf4(y); x=f4d(x,y); return cf4(x);} return f"), this)(f32x4, another), [NaN, NaN, NaN, NaN]);
|
||||||
|
|
||||||
// Unary arithmetic operators
|
// Unary arithmetic operators
|
||||||
function CheckUnaryF4(op, checkFunc, assertFunc) {
|
function CheckUnaryF4(op, checkFunc, assertFunc) {
|
||||||
var _ = asmLink(asmCompile('glob', USE_ASM + F32 + 'var op=f4.' + op + '; function f(x){x=f4(x); return f4(op(x)); } return f'), this);
|
var _ = asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + 'var op=f4.' + op + '; function f(x){x=cf4(x); return cf4(op(x)); } return f'), this);
|
||||||
return function(input) {
|
return function(input) {
|
||||||
var simd = SIMD.float32x4(input[0], input[1], input[2], input[3]);
|
var simd = SIMD.float32x4(input[0], input[1], input[2], input[3]);
|
||||||
|
|
||||||
@ -528,7 +520,7 @@ function CheckUnaryF4(op, checkFunc, assertFunc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function CheckUnaryI4(op, checkFunc) {
|
function CheckUnaryI4(op, checkFunc) {
|
||||||
var _ = asmLink(asmCompile('glob', USE_ASM + I32 + 'var op=i4.' + op + '; function f(x){x=i4(x); return i4(op(x)); } return f'), this);
|
var _ = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'var op=i4.' + op + '; function f(x){x=ci4(x); return ci4(op(x)); } return f'), this);
|
||||||
return function(input) {
|
return function(input) {
|
||||||
var simd = SIMD.int32x4(input[0], input[1], input[2], input[3]);
|
var simd = SIMD.int32x4(input[0], input[1], input[2], input[3]);
|
||||||
assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return x | 0}));
|
assertEqX4(_(simd), input.map(checkFunc).map(function(x) { return x | 0}));
|
||||||
@ -622,7 +614,6 @@ const WZF = 'var w = f4.withZ;';
|
|||||||
const WWF = 'var w = f4.withW;';
|
const WWF = 'var w = f4.withW;';
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, 1);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, 1);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, 1.0);} return f");
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + "function f() {var x = f4(1,2,3,4); x = w(x, x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1, f32(1));} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1, f32(1));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1., f32(1));} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + WXF + FROUND + "function f() {var x = f4(1,2,3,4); x = w(1., f32(1));} return f");
|
||||||
@ -635,6 +626,11 @@ CheckF4(WZF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, 2, Math.
|
|||||||
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, 2, 3, Math.fround(13.37)]);
|
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37));', [1, 2, 3, Math.fround(13.37)]);
|
||||||
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]);
|
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, f32(13.37) + f32(6.63));', [1, 2, 3, Math.fround(Math.fround(13.37) + Math.fround(6.63))]);
|
||||||
|
|
||||||
|
CheckF4(WXF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [Math.fround(13.37), 2, 3, 4]);
|
||||||
|
CheckF4(WYF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, Math.fround(13.37), 3, 4]);
|
||||||
|
CheckF4(WZF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, 2, Math.fround(13.37), 4]);
|
||||||
|
CheckF4(WWF + FROUND, 'var x = f4(1,2,3,4); x = w(x, 13.37);', [1, 2, 3, Math.fround(13.37)]);
|
||||||
|
|
||||||
const WXI = 'var w = i4.withX;';
|
const WXI = 'var w = i4.withX;';
|
||||||
const WYI = 'var w = i4.withY;';
|
const WYI = 'var w = i4.withY;';
|
||||||
const WZI = 'var w = i4.withZ;';
|
const WZI = 'var w = i4.withZ;';
|
||||||
@ -729,7 +725,7 @@ assertAsmTypeFail('glob', USE_ASM + F32 + "var cvt=f4.fromFloat32x4; return {}")
|
|||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIF + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
|
||||||
|
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTIF + 'function f(x){x=i4(x); var y=f4(0,0,0,0); y=cvt(x); return f4(y);} return f'), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + CI32 + CVTIF + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this);
|
||||||
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4]);
|
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4]);
|
||||||
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MIN), Math.fround(INT32_MAX), -1]);
|
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MIN), Math.fround(INT32_MAX), -1]);
|
||||||
|
|
||||||
@ -738,7 +734,7 @@ assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, Math.fround(INT32_MIN)
|
|||||||
// tests, we assume x86/x64, so a conversion which failed will return the
|
// tests, we assume x86/x64, so a conversion which failed will return the
|
||||||
// undefined int32 value. See also bug 1068028.
|
// undefined int32 value. See also bug 1068028.
|
||||||
const UNDEFINED_INT32 = 0x80000000 | 0;
|
const UNDEFINED_INT32 = 0x80000000 | 0;
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTFI + 'function f(x){x=f4(x); var y=i4(0,0,0,0); y=cvt(x); return i4(y);} return f'), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFI + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this);
|
||||||
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4]);
|
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4]);
|
||||||
assertEqX4(f(SIMD.float32x4(NaN,Infinity,-Infinity,-0)), [UNDEFINED_INT32, UNDEFINED_INT32, UNDEFINED_INT32, 0]);
|
assertEqX4(f(SIMD.float32x4(NaN,Infinity,-Infinity,-0)), [UNDEFINED_INT32, UNDEFINED_INT32, UNDEFINED_INT32, 0]);
|
||||||
|
|
||||||
@ -771,19 +767,19 @@ assertAsmTypeFail('glob', USE_ASM + F32 + "var cvt=f4.fromFloat32x4; return {}")
|
|||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=i4(1,2,3,4); x=cvt(x);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CVTIFB + "function f() {var x=f4(1,2,3,4); x=cvt(x);} return f");
|
||||||
|
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTIFB + 'function f(x){x=i4(x); var y=f4(0,0,0,0); y=cvt(x); return f4(y);} return f'), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); y=cvt(x); return cf4(y);} return f'), this);
|
||||||
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits));
|
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits));
|
||||||
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits));
|
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits));
|
||||||
|
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32A + CVTIFB + 'function f(x){x=i4(x); var y=f4(0,0,0,0); var z=f4(1,1,1,1); y=cvt(x); y=f4a(y, z); return f4(y)} return f'), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32A + CVTIFB + CF32 + CI32 + 'function f(x){x=ci4(x); var y=f4(0,0,0,0); var z=f4(1,1,1,1); y=cvt(x); y=f4a(y, z); return cf4(y)} return f'), this);
|
||||||
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits).map((x) => x+1));
|
assertEqX4(f(SIMD.int32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromInt32Bits).map((x) => x+1));
|
||||||
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits).map((x) => x+1));
|
assertEqX4(f(SIMD.int32x4(0,INT32_MIN,INT32_MAX,-1)), [0, INT32_MIN, INT32_MAX, -1].map(cast.fromInt32Bits).map((x) => x+1));
|
||||||
|
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CVTFIB + 'function f(x){x=f4(x); var y=i4(0,0,0,0); y=cvt(x); return i4(y);} return f'), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); y=cvt(x); return ci4(y);} return f'), this);
|
||||||
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits));
|
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits));
|
||||||
assertEqX4(f(SIMD.float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits));
|
assertEqX4(f(SIMD.float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits));
|
||||||
|
|
||||||
var f = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + I32A + CVTFIB + 'function f(x){x=f4(x); var y=i4(0,0,0,0); var z=i4(1,1,1,1); y=cvt(x); y=i4a(y,z); return i4(y);} return f'), this);
|
var f = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + F32 + CF32 + I32A + CVTFIB + 'function f(x){x=cf4(x); var y=i4(0,0,0,0); var z=i4(1,1,1,1); y=cvt(x); y=i4a(y,z); return ci4(y);} return f'), this);
|
||||||
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits).map((x) => x+1));
|
assertEqX4(f(SIMD.float32x4(1,2,3,4)), [1, 2, 3, 4].map(cast.fromFloat32Bits).map((x) => x+1));
|
||||||
assertEqX4(f(SIMD.float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits).map((x) => x+1));
|
assertEqX4(f(SIMD.float32x4(-0,NaN,+Infinity,-Infinity)), [-0, NaN, +Infinity, -Infinity].map(cast.fromFloat32Bits).map((x) => x+1));
|
||||||
|
|
||||||
@ -826,10 +822,10 @@ const LSHI = 'var lsh=i4.shiftLeftByScalar;'
|
|||||||
const RSHI = 'var rsh=i4.shiftRightArithmeticByScalar;'
|
const RSHI = 'var rsh=i4.shiftRightArithmeticByScalar;'
|
||||||
const URSHI = 'var ursh=i4.shiftRightLogicalByScalar;'
|
const URSHI = 'var ursh=i4.shiftRightLogicalByScalar;'
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return i4(lsh(x,f32(42)));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return ci4(lsh(x,f32(42)));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return i4(lsh(x,42));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + F32 + FROUND + LSHI + "function f() {var x=f4(1,2,3,4); return ci4(lsh(x,42));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return i4(lsh(x,42.0));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return ci4(lsh(x,42.0));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return i4(lsh(x,f32(42)));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + CI32 + FROUND + LSHI + "function f() {var x=i4(1,2,3,4); return ci4(lsh(x,f32(42)));} return f");
|
||||||
|
|
||||||
var input = 'i4(0, 1, ' + INT32_MIN + ', ' + INT32_MAX + ')';
|
var input = 'i4(0, 1, ' + INT32_MIN + ', ' + INT32_MAX + ')';
|
||||||
var vinput = [0, 1, INT32_MIN, INT32_MAX];
|
var vinput = [0, 1, INT32_MIN, INT32_MAX];
|
||||||
@ -841,9 +837,9 @@ function Lsh(i) { if (i > 31) return () => 0; return function(x) { return (x <<
|
|||||||
function Rsh(i) { if (i > 31) return (x) => (x<0)?-1:0; return function(x) { return (x >> i) | 0 } }
|
function Rsh(i) { if (i > 31) return (x) => (x<0)?-1:0; return function(x) { return (x >> i) | 0 } }
|
||||||
function Ursh(i) { if (i > 31) return () => 0; return function(x) { return (x >>> i) | 0 } }
|
function Ursh(i) { if (i > 31) return () => 0; return function(x) { return (x >>> i) | 0 } }
|
||||||
|
|
||||||
var asmLsh = asmLink(asmCompile('glob', USE_ASM + I32 + LSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return i4(lsh(v, x+y))} return f;'), this)
|
var asmLsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + LSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(lsh(v, x+y))} return f;'), this)
|
||||||
var asmRsh = asmLink(asmCompile('glob', USE_ASM + I32 + RSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return i4(rsh(v, x+y))} return f;'), this)
|
var asmRsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + RSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(rsh(v, x+y))} return f;'), this)
|
||||||
var asmUrsh = asmLink(asmCompile('glob', USE_ASM + I32 + URSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return i4(ursh(v, x+y))} return f;'), this)
|
var asmUrsh = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + URSHI + 'function f(x, y){x=x|0;y=y|0; var v=' + input + ';return ci4(ursh(v, x+y))} return f;'), this)
|
||||||
|
|
||||||
for (var i = 1; i < 64; i++) {
|
for (var i = 1; i < 64; i++) {
|
||||||
CheckI4(LSHI, 'var x=' + input + '; x=lsh(x, ' + i + ')', vinput.map(Lsh(i)));
|
CheckI4(LSHI, 'var x=' + input + '; x=lsh(x, ' + i + ')', vinput.map(Lsh(i)));
|
||||||
@ -861,51 +857,51 @@ const F32SEL = 'var f4sel = f4.select;'
|
|||||||
const I32BSEL = 'var i4sel = i4.bitselect;'
|
const I32BSEL = 'var i4sel = i4.bitselect;'
|
||||||
const F32BSEL = 'var f4sel = f4.bitselect;'
|
const F32BSEL = 'var f4sel = f4.bitselect;'
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + I32SEL + "function f() {var x=f4(1,2,3,4); return i4(i4sel(x,x,x));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + I32SEL + "function f() {var x=f4(1,2,3,4); return ci4(i4sel(x,x,x));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return i4(i4sel(m,x,x));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return i4(i4sel(m,x,x));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + I32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); return i4(i4sel(m,x,x));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); return ci4(i4sel(m,x,x));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return i4(i4sel(m,x,y));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return ci4(i4sel(m,x,y));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return i4(i4sel(m,x,y));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CI32 + I32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return ci4(i4sel(m,x,y));} return f");
|
||||||
|
|
||||||
assertAsmTypeFail('glob', USE_ASM + F32 + F32SEL + "function f() {var m=f4(1,2,3,4); return f4(f4sel(x,x,x));} return f");
|
assertAsmTypeFail('glob', USE_ASM + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); return cf4(f4sel(x,x,x));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return f4(f4sel(m,x,x));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=i4(1,2,3,4); return cf4(f4sel(m,x,x));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return f4(f4sel(m,x,x));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=f4(1,2,3,4); var x=f4(1,2,3,4); return cf4(f4sel(m,x,x));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return f4(f4sel(m,x,y));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=f4(1,2,3,4); var y=i4(5,6,7,8); return cf4(f4sel(m,x,y));} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(1,2,3,4); var x=i4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y));} return f");
|
||||||
|
|
||||||
// These pass with select but not bitselect
|
// These pass with select but not bitselect
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(-1,-2,-3,-42); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(-1,-2,-3,-42); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(1,-1,2,-2); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(1,-1,2,-2); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(42,45,-42,-47); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(42,45,-42,-47); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
||||||
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(-1,-2,-3,-42); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(-1,-2,-3,-42); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(1,-1,2,-2); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(1,-1,2,-2); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(42,45,-42,-47); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(42,45,-42,-47); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
||||||
|
|
||||||
// These pass for both select and bitselect
|
// These pass for both select and bitselect
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
||||||
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32SEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32SEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
||||||
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32BSEL + "function f() {var m=i4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32BSEL + "function f() {var m=i4(0,0,0,0); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32BSEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32BSEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32BSEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32BSEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32BSEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return i4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32BSEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=i4(1,2,3,4); var y=i4(5,6,7,8); return ci4(i4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
||||||
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32BSEL + "function f() {var m=i4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32BSEL + "function f() {var m=i4(0,0,0,0); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 7, 8]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32BSEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32BSEL + "function f() {var m=i4(0xffffffff,0xffffffff,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32BSEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32BSEL + "function f() {var m=i4(0,0xffffffff,0,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 2, 7, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32BSEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return f4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CF32 + F32BSEL + "function f() {var m=i4(0,0,0xffffffff,0xffffffff); var x=f4(1,2,3,4); var y=f4(5,6,7,8); return cf4(f4sel(m,x,y)); } return f"), this)(), [5, 6, 3, 4]);
|
||||||
|
|
||||||
// Specific bitselect tests
|
// Specific bitselect tests
|
||||||
var masks = [
|
var masks = [
|
||||||
@ -921,7 +917,7 @@ var inputs = [
|
|||||||
[SIMD.int32x4(-1, 2, INT32_MAX, INT32_MIN), SIMD.int32x4(INT32_MAX, -4, INT32_MIN, 42)]
|
[SIMD.int32x4(-1, 2, INT32_MAX, INT32_MIN), SIMD.int32x4(INT32_MAX, -4, INT32_MIN, 42)]
|
||||||
];
|
];
|
||||||
|
|
||||||
var i32bsel = asmLink(asmCompile('glob', USE_ASM + I32 + I32BSEL + "function f(mask, ifTrue, ifFalse) {mask=i4(mask); ifTrue=i4(ifTrue); ifFalse=i4(ifFalse); return i4(i4sel(mask,ifTrue,ifFalse)); } return f"), this)
|
var i32bsel = asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32BSEL + "function f(mask, ifTrue, ifFalse) {mask=ci4(mask); ifTrue=ci4(ifTrue); ifFalse=ci4(ifFalse); return ci4(i4sel(mask,ifTrue,ifFalse)); } return f"), this)
|
||||||
|
|
||||||
for (var mask of masks) {
|
for (var mask of masks) {
|
||||||
for (var [x, y] of inputs) {
|
for (var [x, y] of inputs) {
|
||||||
@ -935,7 +931,7 @@ inputs = [
|
|||||||
[SIMD.float32x4(1.5,2.75,NaN,Infinity), SIMD.float32x4(-NaN,-Infinity,9.75,16.125)]
|
[SIMD.float32x4(1.5,2.75,NaN,Infinity), SIMD.float32x4(-NaN,-Infinity,9.75,16.125)]
|
||||||
];
|
];
|
||||||
|
|
||||||
var f32bsel = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + F32BSEL + "function f(mask, ifTrue, ifFalse) {mask=i4(mask); ifTrue=f4(ifTrue); ifFalse=f4(ifFalse); return f4(f4sel(mask,ifTrue,ifFalse)); } return f"), this)
|
var f32bsel = asmLink(asmCompile('glob', USE_ASM + I32 + F32 + CI32 + CF32 + F32BSEL + "function f(mask, ifTrue, ifFalse) {mask=ci4(mask); ifTrue=cf4(ifTrue); ifFalse=cf4(ifFalse); return cf4(f4sel(mask,ifTrue,ifFalse)); } return f"), this)
|
||||||
|
|
||||||
for (var mask of masks)
|
for (var mask of masks)
|
||||||
for (var [x, y] of inputs)
|
for (var [x, y] of inputs)
|
||||||
@ -953,28 +949,28 @@ assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2
|
|||||||
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1.0);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + "function f() {var m=i4(1,2,3,4); m=splat(1.0);} return f");
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + FROUND + "function f() {var m=i4(1,2,3,4); m=splat(f32(1.0));} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + I32SPLAT + FROUND + "function f() {var m=i4(1,2,3,4); m=splat(f32(1.0));} return f");
|
||||||
|
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32SPLAT + 'function f(){return i4(splat(42));} return f'), this)(), [42, 42, 42, 42]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32SPLAT + 'function f(){return ci4(splat(42));} return f'), this)(), [42, 42, 42, 42]);
|
||||||
|
|
||||||
const l33t = Math.fround(13.37);
|
const l33t = Math.fround(13.37);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1)));} return f'), this)(), [1, 1, 1, 1]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1)));} return f'), this)(), [1, 1, 1, 1]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(1.0));} return f'), this)(), [1, 1, 1, 1]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(1.0));} return f'), this)(), [1, 1, 1, 1]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1 >>> 0)));} return f'), this)(), [1, 1, 1, 1]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1 >>> 0)));} return f'), this)(), [1, 1, 1, 1]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(13.37)));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(13.37)));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(13.37));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(13.37));} return f'), this)(), [l33t, l33t, l33t, l33t]);
|
||||||
|
|
||||||
var i32view = new Int32Array(heap);
|
var i32view = new Int32Array(heap);
|
||||||
var f32view = new Float32Array(heap);
|
var f32view = new Float32Array(heap);
|
||||||
i32view[0] = 42;
|
i32view[0] = 42;
|
||||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + I32SPLAT + 'var i32=new glob.Int32Array(heap); function f(){return i4(splat(i32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + I32 + CI32 + I32SPLAT + 'var i32=new glob.Int32Array(heap); function f(){return ci4(splat(i32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
|
||||||
f32view[0] = 42;
|
f32view[0] = 42;
|
||||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + F32SPLAT + 'var f32=new glob.Float32Array(heap); function f(){return f4(splat(f32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + F32SPLAT + 'var f32=new glob.Float32Array(heap); function f(){return cf4(splat(f32[0]));} return f'), this, {}, heap)(), [42, 42, 42, 42]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + F32SPLAT + FROUND + 'function f(){return f4(splat(f32(1) + f32(2)));} return f'), this, {}, heap)(), [3, 3, 3, 3]);
|
assertEqX4(asmLink(asmCompile('glob', 'ffi', 'heap', USE_ASM + F32 + CF32 + F32SPLAT + FROUND + 'function f(){return cf4(splat(f32(1) + f32(2)));} return f'), this, {}, heap)(), [3, 3, 3, 3]);
|
||||||
|
|
||||||
// Dead code
|
// Dead code
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); return i4(x); x=i4(5,6,7,8); return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'function f(){var x=i4(1,2,3,4); return ci4(x); x=i4(5,6,7,8); return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + 'function f(){var x=i4(1,2,3,4); var c=0; return i4(x); c=x.x|0; return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); c=x.x|0; return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32A + 'function f(){var x=i4(1,2,3,4); var c=0; return i4(x); x=i4a(x,x); return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32A + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); x=i4a(x,x); return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
|
||||||
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + I32S + 'function f(){var x=i4(1,2,3,4); var c=0; return i4(x); x=i4s(x,x); return i4(x);} return f'), this)(), [1, 2, 3, 4]);
|
assertEqX4(asmLink(asmCompile('glob', USE_ASM + I32 + CI32 + I32S + 'function f(){var x=i4(1,2,3,4); var c=0; return ci4(x); x=i4s(x,x); return ci4(x);} return f'), this)(), [1, 2, 3, 4]);
|
||||||
|
|
||||||
// Swizzle
|
// Swizzle
|
||||||
assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, -1, 0, 0, 0);} return f");
|
assertAsmTypeFail('glob', USE_ASM + I32 + "var swizzle=i4.swizzle; function f() {var x=i4(1,2,3,4); x=swizzle(x, -1, 0, 0, 0);} return f");
|
||||||
@ -1093,7 +1089,7 @@ assertAsmTypeFail('glob', 'ffi', USE_ASM + F32 + "var func=ffi.func; function f(
|
|||||||
// 3.3 Internal calls
|
// 3.3 Internal calls
|
||||||
// asm.js -> asm.js
|
// asm.js -> asm.js
|
||||||
// Retrieving values from asm.js
|
// Retrieving values from asm.js
|
||||||
var code = USE_ASM + I32 + I32A + `
|
var code = USE_ASM + I32 + CI32 + I32A + `
|
||||||
var check = ffi.check;
|
var check = ffi.check;
|
||||||
|
|
||||||
function g() {
|
function g() {
|
||||||
@ -1105,15 +1101,15 @@ var code = USE_ASM + I32 + I32A + `
|
|||||||
y = i4a(z, y);
|
y = i4a(z, y);
|
||||||
y = i4a(w, y);
|
y = i4a(w, y);
|
||||||
check(y.x | 0, y.y | 0, y.z | 0, y.w | 0);
|
check(y.x | 0, y.y | 0, y.z | 0, y.w | 0);
|
||||||
return i4(y);
|
return ci4(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
function f(x) {
|
function f(x) {
|
||||||
x = i4(x);
|
x = ci4(x);
|
||||||
var y = i4(0,0,0,0);
|
var y = i4(0,0,0,0);
|
||||||
y = i4(g());
|
y = ci4(g());
|
||||||
check(y.x | 0, y.y | 0, y.z | 0, y.w | 0);
|
check(y.x | 0, y.y | 0, y.z | 0, y.w | 0);
|
||||||
return i4(x);
|
return ci4(x);
|
||||||
}
|
}
|
||||||
return f;
|
return f;
|
||||||
`;
|
`;
|
||||||
@ -1130,7 +1126,7 @@ assertEqX4(asmLink(asmCompile('glob', 'ffi', code), this, ffi)(v4), [1,2,3,4]);
|
|||||||
|
|
||||||
// Passing arguments from asm.js to asm.js
|
// Passing arguments from asm.js to asm.js
|
||||||
// TODO make this code look better with templatized strings
|
// TODO make this code look better with templatized strings
|
||||||
var code = USE_ASM + I32 + I32A + `
|
var code = USE_ASM + I32 + CI32 + I32A + `
|
||||||
var assertEq = ffi.assertEq;
|
var assertEq = ffi.assertEq;
|
||||||
|
|
||||||
function internal([args]) {
|
function internal([args]) {
|
||||||
@ -1156,7 +1152,7 @@ for (var i = 1; i < 10; ++i) {
|
|||||||
var j = i;
|
var j = i;
|
||||||
args += ((i > 1) ? ', ':'') + 'x' + i;
|
args += ((i > 1) ? ', ':'') + 'x' + i;
|
||||||
decls += 'var x' + i + ' = i4(' + j++ + ', ' + j++ + ', ' + j++ + ', ' + j++ + ');\n';
|
decls += 'var x' + i + ' = i4(' + j++ + ', ' + j++ + ', ' + j++ + ', ' + j++ + ');\n';
|
||||||
coerc += 'x' + i + ' = i4(x' + i + ');\n';
|
coerc += 'x' + i + ' = ci4(x' + i + ');\n';
|
||||||
last = 'x' + i;
|
last = 'x' + i;
|
||||||
var c = code.replace(/\[args\]/g, args)
|
var c = code.replace(/\[args\]/g, args)
|
||||||
.replace(/\[last\]/g, last)
|
.replace(/\[last\]/g, last)
|
||||||
@ -1232,6 +1228,7 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
|||||||
var code = `
|
var code = `
|
||||||
"use asm";
|
"use asm";
|
||||||
var i4 = glob.SIMD.int32x4;
|
var i4 = glob.SIMD.int32x4;
|
||||||
|
var ci4 = i4.check;
|
||||||
function h(
|
function h(
|
||||||
// In registers:
|
// In registers:
|
||||||
gpr1, gpr2, gpr3, gpr4, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8,
|
gpr1, gpr2, gpr3, gpr4, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8,
|
||||||
@ -1254,13 +1251,13 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
|||||||
xmm8=+xmm8;
|
xmm8=+xmm8;
|
||||||
|
|
||||||
sint1=sint1|0;
|
sint1=sint1|0;
|
||||||
ssimd1=i4(ssimd1);
|
ssimd1=ci4(ssimd1);
|
||||||
sdouble1=+sdouble1;
|
sdouble1=+sdouble1;
|
||||||
ssimd2=i4(ssimd2);
|
ssimd2=ci4(ssimd2);
|
||||||
sint2=sint2|0;
|
sint2=sint2|0;
|
||||||
sint3=sint3|0;
|
sint3=sint3|0;
|
||||||
sint4=sint4|0;
|
sint4=sint4|0;
|
||||||
ssimd3=i4(ssimd3);
|
ssimd3=ci4(ssimd3);
|
||||||
sdouble2=+sdouble2;
|
sdouble2=+sdouble2;
|
||||||
|
|
||||||
return (ssimd1.x|0) + (ssimd2.y|0) + (ssimd3.z|0) + sint2 + gpr3 | 0;
|
return (ssimd1.x|0) + (ssimd2.y|0) + (ssimd3.z|0) + sint2 + gpr3 | 0;
|
||||||
@ -1290,6 +1287,7 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
|||||||
"use asm";
|
"use asm";
|
||||||
var i4 = glob.SIMD.int32x4;
|
var i4 = glob.SIMD.int32x4;
|
||||||
var i4a = i4.add;
|
var i4a = i4.add;
|
||||||
|
var ci4 = i4.check;
|
||||||
function _() {
|
function _() {
|
||||||
var i = 0;
|
var i = 0;
|
||||||
var n = i4(0,0,0,0);
|
var n = i4(0,0,0,0);
|
||||||
@ -1297,7 +1295,7 @@ asmLink(asmCompile('glob', 'ffi', code), this, assertEqFFI)();
|
|||||||
for (; (i>>>0) < ` + iters + `; i=(i+1)>>>0) {
|
for (; (i>>>0) < ` + iters + `; i=(i+1)>>>0) {
|
||||||
n = i4a(n, one);
|
n = i4a(n, one);
|
||||||
}
|
}
|
||||||
return i4(n);
|
return ci4(n);
|
||||||
}
|
}
|
||||||
return _;`;
|
return _;`;
|
||||||
// This test relies on the fact that setting the timeout will call the
|
// This test relies on the fact that setting the timeout will call the
|
||||||
|
@ -665,17 +665,26 @@ CodeGenerator::getJumpLabelForBranch(MBasicBlock *block)
|
|||||||
void
|
void
|
||||||
CodeGenerator::visitTestOAndBranch(LTestOAndBranch *lir)
|
CodeGenerator::visitTestOAndBranch(LTestOAndBranch *lir)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(lir->mir()->operandMightEmulateUndefined(),
|
MIRType inputType = lir->mir()->input()->type();
|
||||||
"Objects which can't emulate undefined should have been constant-folded");
|
MOZ_ASSERT(inputType == MIRType_ObjectOrNull || lir->mir()->operandMightEmulateUndefined(),
|
||||||
|
"If the object couldn't emulate undefined, this should have been folded.");
|
||||||
OutOfLineTestObject *ool = new(alloc()) OutOfLineTestObject();
|
|
||||||
addOutOfLineCode(ool, lir->mir());
|
|
||||||
|
|
||||||
Label *truthy = getJumpLabelForBranch(lir->ifTruthy());
|
Label *truthy = getJumpLabelForBranch(lir->ifTruthy());
|
||||||
Label *falsy = getJumpLabelForBranch(lir->ifFalsy());
|
Label *falsy = getJumpLabelForBranch(lir->ifFalsy());
|
||||||
|
Register input = ToRegister(lir->input());
|
||||||
|
|
||||||
testObjectEmulatesUndefined(ToRegister(lir->input()), falsy, truthy,
|
if (lir->mir()->operandMightEmulateUndefined()) {
|
||||||
ToRegister(lir->temp()), ool);
|
if (inputType == MIRType_ObjectOrNull)
|
||||||
|
masm.branchTestPtr(Assembler::Zero, input, input, falsy);
|
||||||
|
|
||||||
|
OutOfLineTestObject *ool = new(alloc()) OutOfLineTestObject();
|
||||||
|
addOutOfLineCode(ool, lir->mir());
|
||||||
|
|
||||||
|
testObjectEmulatesUndefined(input, falsy, truthy, ToRegister(lir->temp()), ool);
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(inputType == MIRType_ObjectOrNull);
|
||||||
|
testZeroEmitBranch(Assembler::NotEqual, input, lir->ifTruthy(), lir->ifFalsy());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2553,14 +2562,23 @@ CodeGenerator::visitTypeBarrierV(LTypeBarrierV *lir)
|
|||||||
void
|
void
|
||||||
CodeGenerator::visitTypeBarrierO(LTypeBarrierO *lir)
|
CodeGenerator::visitTypeBarrierO(LTypeBarrierO *lir)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(lir->mir()->barrierKind() != BarrierKind::TypeTagOnly);
|
|
||||||
|
|
||||||
Register obj = ToRegister(lir->object());
|
Register obj = ToRegister(lir->object());
|
||||||
Register scratch = ToTempRegisterOrInvalid(lir->temp());
|
Register scratch = ToTempRegisterOrInvalid(lir->temp());
|
||||||
|
Label miss, ok;
|
||||||
|
|
||||||
|
if (lir->mir()->type() == MIRType_ObjectOrNull) {
|
||||||
|
Label *nullTarget = lir->mir()->resultTypeSet()->mightBeMIRType(MIRType_Null) ? &ok : &miss;
|
||||||
|
masm.branchTestPtr(Assembler::Zero, obj, obj, nullTarget);
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(lir->mir()->type() == MIRType_Object);
|
||||||
|
MOZ_ASSERT(lir->mir()->barrierKind() != BarrierKind::TypeTagOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lir->mir()->barrierKind() != BarrierKind::TypeTagOnly)
|
||||||
|
masm.guardObjectType(obj, lir->mir()->resultTypeSet(), scratch, &miss);
|
||||||
|
|
||||||
Label miss;
|
|
||||||
masm.guardObjectType(obj, lir->mir()->resultTypeSet(), scratch, &miss);
|
|
||||||
bailoutFrom(&miss, lir->snapshot());
|
bailoutFrom(&miss, lir->snapshot());
|
||||||
|
masm.bind(&ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2519,11 +2519,18 @@ TryEliminateTypeBarrier(MTypeBarrier *barrier, bool *eliminated)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
TryOptimizeLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull *def, MDefinitionVector *peliminateList)
|
TryOptimizeLoadObjectOrNull(MDefinition *def, MDefinitionVector *peliminateList)
|
||||||
{
|
{
|
||||||
if (def->type() != MIRType_Value)
|
if (def->type() != MIRType_Value)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Check if this definition can only produce object or null values.
|
||||||
|
TemporaryTypeSet *types = def->resultTypeSet();
|
||||||
|
if (!types)
|
||||||
|
return true;
|
||||||
|
if (types->baseFlags() & ~(TYPE_FLAG_NULL | TYPE_FLAG_ANYOBJECT))
|
||||||
|
return true;
|
||||||
|
|
||||||
MDefinitionVector eliminateList(def->block()->graph().alloc());
|
MDefinitionVector eliminateList(def->block()->graph().alloc());
|
||||||
|
|
||||||
for (MUseDefIterator iter(def); iter; ++iter) {
|
for (MUseDefIterator iter(def); iter; ++iter) {
|
||||||
@ -2533,6 +2540,8 @@ TryOptimizeLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull *def, MDefinitionVec
|
|||||||
if (ndef->toCompare()->compareType() != MCompare::Compare_Null)
|
if (ndef->toCompare()->compareType() != MCompare::Compare_Null)
|
||||||
return true;
|
return true;
|
||||||
break;
|
break;
|
||||||
|
case MDefinition::Op_Test:
|
||||||
|
break;
|
||||||
case MDefinition::Op_PostWriteBarrier:
|
case MDefinition::Op_PostWriteBarrier:
|
||||||
break;
|
break;
|
||||||
case MDefinition::Op_StoreFixedSlot:
|
case MDefinition::Op_StoreFixedSlot:
|
||||||
@ -2546,13 +2555,42 @@ TryOptimizeLoadUnboxedObjectOrNull(MLoadUnboxedObjectOrNull *def, MDefinitionVec
|
|||||||
case MDefinition::Op_Unbox:
|
case MDefinition::Op_Unbox:
|
||||||
MOZ_ASSERT(ndef->type() == MIRType_Object);
|
MOZ_ASSERT(ndef->type() == MIRType_Object);
|
||||||
break;
|
break;
|
||||||
|
case MDefinition::Op_TypeBarrier:
|
||||||
|
// For now, only handle type barriers which are not consumed
|
||||||
|
// anywhere and only test that the value is null.
|
||||||
|
if (ndef->hasUses() || ndef->resultTypeSet()->getKnownMIRType() != MIRType_Null)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On punboxing systems we are better off leaving the value boxed if it
|
||||||
|
// is only stored back to the heap.
|
||||||
|
#ifdef JS_PUNBOX64
|
||||||
|
bool foundUse = false;
|
||||||
|
for (MUseDefIterator iter(def); iter; ++iter) {
|
||||||
|
MDefinition *ndef = iter.def();
|
||||||
|
if (!ndef->isStoreFixedSlot() && !ndef->isStoreSlot()) {
|
||||||
|
foundUse = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!foundUse)
|
||||||
|
return true;
|
||||||
|
#endif // JS_PUNBOX64
|
||||||
|
|
||||||
def->setResultType(MIRType_ObjectOrNull);
|
def->setResultType(MIRType_ObjectOrNull);
|
||||||
|
|
||||||
|
// Fixup the result type of MTypeBarrier uses.
|
||||||
|
for (MUseDefIterator iter(def); iter; ++iter) {
|
||||||
|
MDefinition *ndef = iter.def();
|
||||||
|
if (ndef->isTypeBarrier())
|
||||||
|
ndef->setResultType(MIRType_ObjectOrNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Eliminate MToObjectOrNull instruction uses.
|
||||||
for (size_t i = 0; i < eliminateList.length(); i++) {
|
for (size_t i = 0; i < eliminateList.length(); i++) {
|
||||||
MDefinition *ndef = eliminateList[i];
|
MDefinition *ndef = eliminateList[i];
|
||||||
ndef->replaceAllUsesWith(def);
|
ndef->replaceAllUsesWith(def);
|
||||||
@ -2627,21 +2665,28 @@ jit::EliminateRedundantChecks(MIRGraph &graph)
|
|||||||
|
|
||||||
bool eliminated = false;
|
bool eliminated = false;
|
||||||
|
|
||||||
if (def->isBoundsCheck()) {
|
switch (def->op()) {
|
||||||
|
case MDefinition::Op_BoundsCheck:
|
||||||
if (!TryEliminateBoundsCheck(checks, index, def->toBoundsCheck(), &eliminated))
|
if (!TryEliminateBoundsCheck(checks, index, def->toBoundsCheck(), &eliminated))
|
||||||
return false;
|
return false;
|
||||||
} else if (def->isTypeBarrier()) {
|
break;
|
||||||
|
case MDefinition::Op_TypeBarrier:
|
||||||
if (!TryEliminateTypeBarrier(def->toTypeBarrier(), &eliminated))
|
if (!TryEliminateTypeBarrier(def->toTypeBarrier(), &eliminated))
|
||||||
return false;
|
return false;
|
||||||
} else if (def->isLoadUnboxedObjectOrNull()) {
|
break;
|
||||||
if (!TryOptimizeLoadUnboxedObjectOrNull(def->toLoadUnboxedObjectOrNull(), &eliminateList))
|
case MDefinition::Op_LoadFixedSlot:
|
||||||
|
case MDefinition::Op_LoadSlot:
|
||||||
|
case MDefinition::Op_LoadUnboxedObjectOrNull:
|
||||||
|
if (!TryOptimizeLoadObjectOrNull(def, &eliminateList))
|
||||||
return false;
|
return false;
|
||||||
} else {
|
break;
|
||||||
|
default:
|
||||||
// Now that code motion passes have finished, replace
|
// Now that code motion passes have finished, replace
|
||||||
// instructions which pass through one of their operands
|
// instructions which pass through one of their operands
|
||||||
// (and perform additional checks) with that operand.
|
// (and perform additional checks) with that operand.
|
||||||
if (MDefinition *passthrough = PassthroughOperand(def))
|
if (MDefinition *passthrough = PassthroughOperand(def))
|
||||||
def->replaceAllUsesWith(passthrough);
|
def->replaceAllUsesWith(passthrough);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eliminated)
|
if (eliminated)
|
||||||
|
@ -658,6 +658,12 @@ LIRGenerator::visitTest(MTest *test)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opd->type() == MIRType_ObjectOrNull) {
|
||||||
|
LDefinition temp0 = test->operandMightEmulateUndefined() ? temp() : LDefinition::BogusTemp();
|
||||||
|
add(new(alloc()) LTestOAndBranch(useRegister(opd), ifTrue, ifFalse, temp0), test);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Objects are truthy, except if it might emulate undefined.
|
// Objects are truthy, except if it might emulate undefined.
|
||||||
if (opd->type() == MIRType_Object) {
|
if (opd->type() == MIRType_Object) {
|
||||||
if (test->operandMightEmulateUndefined())
|
if (test->operandMightEmulateUndefined())
|
||||||
@ -2327,10 +2333,18 @@ LIRGenerator::visitTypeBarrier(MTypeBarrier *ins)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle typebarrier with specific ObjectGroup/SingleObjects.
|
// The payload needs to be tested if it either might be null or might have
|
||||||
|
// an object that should be excluded from the barrier.
|
||||||
|
bool needsObjectBarrier = false;
|
||||||
|
if (inputType == MIRType_ObjectOrNull)
|
||||||
|
needsObjectBarrier = true;
|
||||||
if (inputType == MIRType_Object && !types->hasType(TypeSet::AnyObjectType()) &&
|
if (inputType == MIRType_Object && !types->hasType(TypeSet::AnyObjectType()) &&
|
||||||
ins->barrierKind() != BarrierKind::TypeTagOnly)
|
ins->barrierKind() != BarrierKind::TypeTagOnly)
|
||||||
{
|
{
|
||||||
|
needsObjectBarrier = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsObjectBarrier) {
|
||||||
LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
|
LDefinition tmp = needTemp ? temp() : LDefinition::BogusTemp();
|
||||||
LTypeBarrierO *barrier = new(alloc()) LTypeBarrierO(useRegister(ins->getOperand(0)), tmp);
|
LTypeBarrierO *barrier = new(alloc()) LTypeBarrierO(useRegister(ins->getOperand(0)), tmp);
|
||||||
assignSnapshot(barrier, Bailout_TypeBarrierO);
|
assignSnapshot(barrier, Bailout_TypeBarrierO);
|
||||||
|
@ -3348,7 +3348,7 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
|
|||||||
cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry))
|
cache.lookupGlobal(&ArrayObject::class_, cx->global(), allocKind, &entry))
|
||||||
{
|
{
|
||||||
gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_);
|
gc::InitialHeap heap = GetInitialHeap(newKind, &ArrayObject::class_);
|
||||||
JSObject *obj = cache.newObjectFromHit<NoGC>(cx, entry, heap);
|
JSObject *obj = cache.newObjectFromHit(cx, entry, heap);
|
||||||
if (obj) {
|
if (obj) {
|
||||||
/* Fixup the elements pointer and length, which may be incorrect. */
|
/* Fixup the elements pointer and length, which may be incorrect. */
|
||||||
ArrayObject *arr = &obj->as<ArrayObject>();
|
ArrayObject *arr = &obj->as<ArrayObject>();
|
||||||
@ -3360,9 +3360,6 @@ NewArray(ExclusiveContext *cxArg, uint32_t length,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return arr;
|
return arr;
|
||||||
} else {
|
|
||||||
obj = cache.newObjectFromHit<CanGC>(cx, entry, heap);
|
|
||||||
MOZ_ASSERT(!obj);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gcNumber = rt->gc.gcNumber();
|
gcNumber = rt->gc.gcNumber();
|
||||||
|
@ -1251,13 +1251,9 @@ js::NewObjectWithGivenTaggedProto(ExclusiveContext *cxArg, const Class *clasp,
|
|||||||
!proto.toObject()->is<GlobalObject>())
|
!proto.toObject()->is<GlobalObject>())
|
||||||
{
|
{
|
||||||
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
|
if (cache.lookupProto(clasp, proto.toObject(), allocKind, &entry)) {
|
||||||
JSObject *obj = cache.newObjectFromHit<NoGC>(cx, entry, GetInitialHeap(newKind, clasp));
|
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
|
||||||
if (obj) {
|
if (obj)
|
||||||
return obj;
|
return obj;
|
||||||
} else {
|
|
||||||
obj = cache.newObjectFromHit<CanGC>(cx, entry, GetInitialHeap(newKind, clasp));
|
|
||||||
MOZ_ASSERT(!obj);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
gcNumber = rt->gc.gcNumber();
|
gcNumber = rt->gc.gcNumber();
|
||||||
}
|
}
|
||||||
@ -1424,13 +1420,9 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg, const Class *clasp,
|
|||||||
!cx->compartment()->hasObjectMetadataCallback())
|
!cx->compartment()->hasObjectMetadataCallback())
|
||||||
{
|
{
|
||||||
if (cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry)) {
|
if (cache.lookupGlobal(clasp, &parent->as<GlobalObject>(), allocKind, &entry)) {
|
||||||
JSObject *obj = cache.newObjectFromHit<NoGC>(cx, entry, GetInitialHeap(newKind, clasp));
|
JSObject *obj = cache.newObjectFromHit(cx, entry, GetInitialHeap(newKind, clasp));
|
||||||
if (obj) {
|
if (obj)
|
||||||
return obj;
|
return obj;
|
||||||
} else {
|
|
||||||
obj = cache.newObjectFromHit<CanGC>(cx, entry, GetInitialHeap(newKind, clasp));
|
|
||||||
MOZ_ASSERT(!obj);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
gcNumber = rt->gc.gcNumber();
|
gcNumber = rt->gc.gcNumber();
|
||||||
}
|
}
|
||||||
@ -1478,6 +1470,7 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, HandleObjec
|
|||||||
NewObjectCache &cache = cx->runtime()->newObjectCache;
|
NewObjectCache &cache = cx->runtime()->newObjectCache;
|
||||||
|
|
||||||
NewObjectCache::EntryIndex entry = -1;
|
NewObjectCache::EntryIndex entry = -1;
|
||||||
|
uint64_t gcNumber = 0;
|
||||||
if (group->proto().isObject() &&
|
if (group->proto().isObject() &&
|
||||||
parent == group->proto().toObject()->getParent() &&
|
parent == group->proto().toObject()->getParent() &&
|
||||||
newKind == GenericObject &&
|
newKind == GenericObject &&
|
||||||
@ -1486,13 +1479,12 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, HandleObjec
|
|||||||
!cx->compartment()->hasObjectMetadataCallback())
|
!cx->compartment()->hasObjectMetadataCallback())
|
||||||
{
|
{
|
||||||
if (cache.lookupGroup(group, allocKind, &entry)) {
|
if (cache.lookupGroup(group, allocKind, &entry)) {
|
||||||
JSObject *obj = cache.newObjectFromHit<NoGC>(cx, entry, GetInitialHeap(newKind, group->clasp()));
|
JSObject *obj = cache.newObjectFromHit(cx, entry,
|
||||||
if (obj) {
|
GetInitialHeap(newKind, group->clasp()));
|
||||||
|
if (obj)
|
||||||
return obj;
|
return obj;
|
||||||
} else {
|
} else {
|
||||||
obj = cache.newObjectFromHit<CanGC>(cx, entry, GetInitialHeap(newKind, group->clasp()));
|
gcNumber = cx->runtime()->gc.gcNumber();
|
||||||
MOZ_ASSERT(!obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1500,8 +1492,11 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, HandleObjec
|
|||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots())
|
if (entry != -1 && !obj->as<NativeObject>().hasDynamicSlots() &&
|
||||||
|
cx->runtime()->gc.gcNumber() == gcNumber)
|
||||||
|
{
|
||||||
cache.fillGroup(entry, group, allocKind, &obj->as<NativeObject>());
|
cache.fillGroup(entry, group, allocKind, &obj->as<NativeObject>());
|
||||||
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -9,85 +9,31 @@ function TestInt32x4Ctor() {
|
|||||||
assertEqX4(int32x4(1, 2, 3, 4), [1,2,3,4]);
|
assertEqX4(int32x4(1, 2, 3, 4), [1,2,3,4]);
|
||||||
assertEqX4(int32x4(1, 2, 3), [1,2,3,0]);
|
assertEqX4(int32x4(1, 2, 3), [1,2,3,0]);
|
||||||
assertEqX4(int32x4(1, 2), [1,2,0,0]);
|
assertEqX4(int32x4(1, 2), [1,2,0,0]);
|
||||||
// The 1-argument form is reserved for coercions.
|
assertEqX4(int32x4(1), [1,0,0,0]);
|
||||||
assertEqX4(int32x4(), [0,0,0,0]);
|
assertEqX4(int32x4(), [0,0,0,0]);
|
||||||
assertEqX4(int32x4(1, 2, 3, 4, 5), [1,2,3,4]);
|
assertEqX4(int32x4(1, 2, 3, 4, 5), [1,2,3,4]);
|
||||||
assertEqX4(int32x4(1, 2, 3, 4, 5, 6), [1,2,3,4]);
|
assertEqX4(int32x4(1, 2, 3, 4, 5, 6), [1,2,3,4]);
|
||||||
|
|
||||||
// Constructors used as coercion.
|
|
||||||
var x = int32x4(1, 2, 3, 4);
|
|
||||||
var y = int32x4(x);
|
|
||||||
|
|
||||||
assertEq(x, y);
|
|
||||||
|
|
||||||
assertEq(y.x, x.x);
|
|
||||||
assertEq(y.x, 1);
|
|
||||||
assertEq(y.y, x.y);
|
|
||||||
assertEq(y.y, 2);
|
|
||||||
assertEq(y.z, x.z);
|
|
||||||
assertEq(y.z, 3);
|
|
||||||
assertEq(y.w, x.w);
|
|
||||||
assertEq(y.w, 4);
|
|
||||||
|
|
||||||
assertThrowsInstanceOf(() => int32x4(3), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => int32x4(float32x4(1,2,3,4)), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => int32x4(float64x2(1,2)), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => int32x4('pony x 4'), TypeError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function TestFloat32x4Ctor() {
|
function TestFloat32x4Ctor() {
|
||||||
assertEqX4(float32x4(1, 2, 3, 4), [1,2,3,4]);
|
assertEqX4(float32x4(1, 2, 3, 4), [1,2,3,4]);
|
||||||
assertEqX4(float32x4(1, 2, 3), [1,2,3,NaN]);
|
assertEqX4(float32x4(1, 2, 3), [1,2,3,NaN]);
|
||||||
assertEqX4(float32x4(1, 2), [1,2,NaN,NaN]);
|
assertEqX4(float32x4(1, 2), [1,2,NaN,NaN]);
|
||||||
// The 1-argument form is reserved for coercions.
|
assertEqX4(float32x4(1), [1,NaN,NaN,NaN]);
|
||||||
assertEqX4(float32x4(), [NaN,NaN,NaN,NaN]);
|
assertEqX4(float32x4(), [NaN,NaN,NaN,NaN]);
|
||||||
assertEqX4(float32x4(1, 2, 3, 4, 5), [1,2,3,4]);
|
assertEqX4(float32x4(1, 2, 3, 4, 5), [1,2,3,4]);
|
||||||
assertEqX4(float32x4(1, 2, 3, 4, 5, 6), [1,2,3,4]);
|
assertEqX4(float32x4(1, 2, 3, 4, 5, 6), [1,2,3,4]);
|
||||||
|
|
||||||
var x = float32x4(NaN, 13.37, -Infinity, 4);
|
|
||||||
var y = float32x4(x);
|
|
||||||
|
|
||||||
assertEq(x, y);
|
|
||||||
|
|
||||||
assertEq(y.x, x.x);
|
|
||||||
assertEq(y.x, Math.fround(NaN));
|
|
||||||
assertEq(y.y, x.y);
|
|
||||||
assertEq(y.y, Math.fround(13.37));
|
|
||||||
assertEq(y.z, x.z);
|
|
||||||
assertEq(y.z, Math.fround(-Infinity));
|
|
||||||
assertEq(y.w, x.w);
|
|
||||||
assertEq(y.w, Math.fround(4));
|
|
||||||
|
|
||||||
assertThrowsInstanceOf(() => float32x4(3), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => float32x4(int32x4(1,2,3,4)), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => float32x4(float64x2(1,2)), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => float32x4('pony x 4'), TypeError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function TestFloat64x2Ctor() {
|
function TestFloat64x2Ctor() {
|
||||||
assertEqX2(float64x2(1, 2), [1,2]);
|
assertEqX2(float64x2(1, 2), [1,2]);
|
||||||
// The 1-argument form is reserved for coercions.
|
assertEqX2(float64x2(1), [1,NaN]);
|
||||||
assertEqX2(float64x2(), [NaN,NaN]);
|
assertEqX2(float64x2(), [NaN,NaN]);
|
||||||
assertEqX2(float64x2(1, 2, 3), [1,2]);
|
assertEqX2(float64x2(1, 2, 3), [1,2]);
|
||||||
assertEqX2(float64x2(1, 2, 3, 4), [1,2]);
|
assertEqX2(float64x2(1, 2, 3, 4), [1,2]);
|
||||||
assertEqX2(float64x2(1, 2, 3, 4, 5), [1,2]);
|
assertEqX2(float64x2(1, 2, 3, 4, 5), [1,2]);
|
||||||
assertEqX2(float64x2(1, 2, 3, 4, 5), [1,2]);
|
assertEqX2(float64x2(1, 2, 3, 4, 5), [1,2]);
|
||||||
assertEqX2(float64x2(1, 2, 3, 4, 5, 6), [1,2]);
|
assertEqX2(float64x2(1, 2, 3, 4, 5, 6), [1,2]);
|
||||||
|
|
||||||
var x = float64x2(NaN, 13.37);
|
|
||||||
var y = float64x2(x);
|
|
||||||
|
|
||||||
assertEq(x, y);
|
|
||||||
|
|
||||||
assertEq(y.x, x.x);
|
|
||||||
assertEq(y.x, NaN);
|
|
||||||
assertEq(y.y, x.y);
|
|
||||||
assertEq(y.y, 13.37);
|
|
||||||
|
|
||||||
assertThrowsInstanceOf(() => float64x2(3), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => float64x2(int32x4(1,2,3,4)), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => float64x2(float32x4(1,2,3,4)), TypeError);
|
|
||||||
assertThrowsInstanceOf(() => float64x2('pony x 4'), TypeError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
|
||||||
var BUGNUMBER = 946042;
|
|
||||||
var float32x4 = SIMD.float32x4;
|
|
||||||
var int32x4 = SIMD.int32x4;
|
|
||||||
|
|
||||||
var summary = 'float32x4 with';
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
print(BUGNUMBER + ": " + summary);
|
|
||||||
|
|
||||||
var a = float32x4(1, 2, 3, 4);
|
|
||||||
var x = SIMD.float32x4.withX(a, 5);
|
|
||||||
var y = SIMD.float32x4.withY(a, 5);
|
|
||||||
var z = SIMD.float32x4.withZ(a, 5);
|
|
||||||
var w = SIMD.float32x4.withW(a, 5);
|
|
||||||
assertEq(x.x, 5);
|
|
||||||
assertEq(x.y, 2);
|
|
||||||
assertEq(x.z, 3);
|
|
||||||
assertEq(x.w, 4);
|
|
||||||
|
|
||||||
assertEq(y.x, 1);
|
|
||||||
assertEq(y.y, 5);
|
|
||||||
assertEq(y.z, 3);
|
|
||||||
assertEq(y.w, 4);
|
|
||||||
|
|
||||||
assertEq(z.x, 1);
|
|
||||||
assertEq(z.y, 2);
|
|
||||||
assertEq(z.z, 5);
|
|
||||||
assertEq(z.w, 4);
|
|
||||||
|
|
||||||
assertEq(w.x, 1);
|
|
||||||
assertEq(w.y, 2);
|
|
||||||
assertEq(w.z, 3);
|
|
||||||
assertEq(w.w, 5);
|
|
||||||
|
|
||||||
var b = float32x4(1.87, 2.08, 3.84, 4.17);
|
|
||||||
var x1 = SIMD.float32x4.withX(b, 5.38);
|
|
||||||
var y1 = SIMD.float32x4.withY(b, 5.19);
|
|
||||||
var z1 = SIMD.float32x4.withZ(b, 5.11);
|
|
||||||
var w1 = SIMD.float32x4.withW(b, 5.07);
|
|
||||||
assertEq(x1.x, Math.fround(5.38));
|
|
||||||
assertEq(x1.y, Math.fround(2.08));
|
|
||||||
assertEq(x1.z, Math.fround(3.84));
|
|
||||||
assertEq(x1.w, Math.fround(4.17));
|
|
||||||
|
|
||||||
assertEq(y1.x, Math.fround(1.87));
|
|
||||||
assertEq(y1.y, Math.fround(5.19));
|
|
||||||
assertEq(y1.z, Math.fround(3.84));
|
|
||||||
assertEq(y1.w, Math.fround(4.17));
|
|
||||||
|
|
||||||
assertEq(z1.x, Math.fround(1.87));
|
|
||||||
assertEq(z1.y, Math.fround(2.08));
|
|
||||||
assertEq(z1.z, Math.fround(5.11));
|
|
||||||
assertEq(z1.w, Math.fround(4.17));
|
|
||||||
|
|
||||||
assertEq(w1.x, Math.fround(1.87));
|
|
||||||
assertEq(w1.y, Math.fround(2.08));
|
|
||||||
assertEq(w1.z, Math.fround(3.84));
|
|
||||||
assertEq(w1.w, Math.fround(5.07));
|
|
||||||
|
|
||||||
var c = float32x4(NaN, -0, Infinity, -Infinity);
|
|
||||||
var x2 = SIMD.float32x4.withX(c, 0);
|
|
||||||
var y2 = SIMD.float32x4.withY(c, 0);
|
|
||||||
var z2 = SIMD.float32x4.withZ(c, 0);
|
|
||||||
var w2 = SIMD.float32x4.withW(c, 0);
|
|
||||||
assertEq(x2.x, 0);
|
|
||||||
assertEq(x2.y, -0);
|
|
||||||
assertEq(x2.z, Infinity);
|
|
||||||
assertEq(x2.w, -Infinity);
|
|
||||||
|
|
||||||
assertEq(y2.x, NaN);
|
|
||||||
assertEq(y2.y, 0);
|
|
||||||
assertEq(y2.z, Infinity);
|
|
||||||
assertEq(y2.w, -Infinity);
|
|
||||||
|
|
||||||
assertEq(z2.x, NaN);
|
|
||||||
assertEq(z2.y, -0);
|
|
||||||
assertEq(z2.z, 0);
|
|
||||||
assertEq(z2.w, -Infinity);
|
|
||||||
|
|
||||||
assertEq(w2.x, NaN);
|
|
||||||
assertEq(w2.y, -0);
|
|
||||||
assertEq(w2.z, Infinity);
|
|
||||||
assertEq(w2.w, 0);
|
|
||||||
|
|
||||||
if (typeof reportCompare === "function")
|
|
||||||
reportCompare(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
test();
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
|
||||||
var BUGNUMBER = 1031203;
|
|
||||||
var float64x2 = SIMD.float64x2;
|
|
||||||
|
|
||||||
var summary = 'float64x2 with';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Any copyright is dedicated to the Public Domain.
|
|
||||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
|
||||||
*/
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
print(BUGNUMBER + ": " + summary);
|
|
||||||
|
|
||||||
var a = float64x2(1, 2);
|
|
||||||
var x = float64x2.withX(a, 5);
|
|
||||||
var y = float64x2.withY(a, 5);
|
|
||||||
assertEq(x.x, 5);
|
|
||||||
assertEq(x.y, 2);
|
|
||||||
assertEq(y.x, 1);
|
|
||||||
assertEq(y.y, 5);
|
|
||||||
|
|
||||||
var b = float64x2(NaN, -0);
|
|
||||||
var x1 = float64x2.withX(b, Infinity);
|
|
||||||
var y1 = float64x2.withY(b, -Infinity);
|
|
||||||
assertEq(x1.x, Infinity);
|
|
||||||
assertEq(x1.y, -0);
|
|
||||||
assertEq(y1.x, NaN);
|
|
||||||
assertEq(y1.y, -Infinity);
|
|
||||||
|
|
||||||
if (typeof reportCompare === "function")
|
|
||||||
reportCompare(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
test();
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
|||||||
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
|
||||||
var BUGNUMBER = 946042;
|
|
||||||
var float32x4 = SIMD.float32x4;
|
|
||||||
var int32x4 = SIMD.int32x4;
|
|
||||||
|
|
||||||
var summary = 'int32x4 with';
|
|
||||||
|
|
||||||
function test() {
|
|
||||||
print(BUGNUMBER + ": " + summary);
|
|
||||||
|
|
||||||
var INT32_MAX = Math.pow(2, 31) - 1;
|
|
||||||
|
|
||||||
var a = int32x4(1, 2, 3, 4);
|
|
||||||
var x = SIMD.int32x4.withX(a, 5);
|
|
||||||
var y = SIMD.int32x4.withY(a, 5);
|
|
||||||
var z = SIMD.int32x4.withZ(a, 5);
|
|
||||||
var w = SIMD.int32x4.withW(a, INT32_MAX + 1);
|
|
||||||
assertEq(x.x, 5);
|
|
||||||
assertEq(y.y, 5);
|
|
||||||
assertEq(z.z, 5);
|
|
||||||
assertEq(w.w, (INT32_MAX + 1) | 0);
|
|
||||||
|
|
||||||
if (typeof reportCompare === "function")
|
|
||||||
reportCompare(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
test();
|
|
||||||
|
|
@ -18,6 +18,11 @@ function ursh(a, b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function test() {
|
function test() {
|
||||||
|
function TestError() {};
|
||||||
|
|
||||||
|
var good = {valueOf: () => 21};
|
||||||
|
var bad = {valueOf: () => {throw new TestError(); }};
|
||||||
|
|
||||||
for (var v of [
|
for (var v of [
|
||||||
int32x4(-1, 2, -3, 4),
|
int32x4(-1, 2, -3, 4),
|
||||||
int32x4(INT32_MAX, INT32_MIN, INT32_MAX - 1, INT32_MIN + 1)
|
int32x4(INT32_MAX, INT32_MIN, INT32_MAX - 1, INT32_MIN + 1)
|
||||||
@ -28,8 +33,17 @@ function test() {
|
|||||||
testBinaryScalarFunc(v, bits, int32x4.shiftRightArithmeticByScalar, rsh);
|
testBinaryScalarFunc(v, bits, int32x4.shiftRightArithmeticByScalar, rsh);
|
||||||
testBinaryScalarFunc(v, bits, int32x4.shiftRightLogicalByScalar, ursh);
|
testBinaryScalarFunc(v, bits, int32x4.shiftRightLogicalByScalar, ursh);
|
||||||
}
|
}
|
||||||
|
// Test that the shift count is coerced to an int32.
|
||||||
|
testBinaryScalarFunc(v, undefined, int32x4.shiftLeftByScalar, lsh);
|
||||||
|
testBinaryScalarFunc(v, 3.5, int32x4.shiftLeftByScalar, lsh);
|
||||||
|
testBinaryScalarFunc(v, good, int32x4.shiftLeftByScalar, lsh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var v = SIMD.int32x4(1,2,3,4);
|
||||||
|
assertThrowsInstanceOf(() => SIMD.int32x4.shiftLeftByScalar(v, bad), TestError);
|
||||||
|
assertThrowsInstanceOf(() => SIMD.int32x4.shiftRightArithmeticByScalar(v, bad), TestError);
|
||||||
|
assertThrowsInstanceOf(() => SIMD.int32x4.shiftRightLogicalByScalar(v, bad), TestError);
|
||||||
|
|
||||||
if (typeof reportCompare === "function")
|
if (typeof reportCompare === "function")
|
||||||
reportCompare(true, true);
|
reportCompare(true, true);
|
||||||
}
|
}
|
||||||
|
38
js/src/tests/ecma_7/SIMD/splat.js
Normal file
38
js/src/tests/ecma_7/SIMD/splat.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||||
|
|
||||||
|
var float64x2 = SIMD.float64x2;
|
||||||
|
var float32x4 = SIMD.float32x4;
|
||||||
|
var int32x4 = SIMD.int32x4;
|
||||||
|
|
||||||
|
function TestSplatX4(type, inputs, coerceFunc) {
|
||||||
|
for (var x of inputs) {
|
||||||
|
assertEqX4(SIMD[type].splat(x), [x, x, x, x].map(coerceFunc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function TestSplatX2(type, inputs, coerceFunc) {
|
||||||
|
for (var x of inputs) {
|
||||||
|
assertEqX2(SIMD[type].splat(x), [x, x].map(coerceFunc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
function TestError(){};
|
||||||
|
|
||||||
|
var good = {valueOf: () => 19.89};
|
||||||
|
var bad = {valueOf: () => { throw new TestError(); }};
|
||||||
|
|
||||||
|
TestSplatX4('int32x4', [0, undefined, 3.5, 42, -1337, INT32_MAX, INT32_MAX + 1, good], (x) => x | 0);
|
||||||
|
assertThrowsInstanceOf(() => SIMD.int32x4.splat(bad), TestError);
|
||||||
|
|
||||||
|
TestSplatX4('float32x4', [0, undefined, 3.5, 42, -13.37, Infinity, NaN, -0, good], (x) => Math.fround(x));
|
||||||
|
assertThrowsInstanceOf(() => SIMD.float32x4.splat(bad), TestError);
|
||||||
|
|
||||||
|
TestSplatX2('float64x2', [0, undefined, 3.5, 42, -13.37, Infinity, NaN, -0, good], (x) => +x);
|
||||||
|
assertThrowsInstanceOf(() => SIMD.float64x2.splat(bad), TestError);
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
test();
|
90
js/src/tests/ecma_7/SIMD/with.js
Normal file
90
js/src/tests/ecma_7/SIMD/with.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// |reftest| skip-if(!this.hasOwnProperty("SIMD"))
|
||||||
|
var BUGNUMBER = 946042;
|
||||||
|
var float32x4 = SIMD.float32x4;
|
||||||
|
var int32x4 = SIMD.int32x4;
|
||||||
|
var float64x2 = SIMD.float64x2;
|
||||||
|
|
||||||
|
var summary = 'with{X,Y,Z,W}';
|
||||||
|
|
||||||
|
function withX(arr, x) {
|
||||||
|
if (arr.length == 2)
|
||||||
|
return [x, arr[1]];
|
||||||
|
return [x, arr[1], arr[2], arr[3]];
|
||||||
|
}
|
||||||
|
function withY(arr, x) {
|
||||||
|
if (arr.length == 2)
|
||||||
|
return [arr[0], x];
|
||||||
|
return [arr[0], x, arr[2], arr[3]];
|
||||||
|
}
|
||||||
|
function withZ(arr, x) {
|
||||||
|
return [arr[0], arr[1], x, arr[3]];
|
||||||
|
}
|
||||||
|
function withW(arr, x) {
|
||||||
|
return [arr[0], arr[1], arr[2], x];
|
||||||
|
}
|
||||||
|
|
||||||
|
function testWith(vec, scalar, simdFunc, func) {
|
||||||
|
var varr = simdToArray(vec);
|
||||||
|
var observed = simdToArray(simdFunc(vec, scalar));
|
||||||
|
var expected = func(varr, scalar);
|
||||||
|
for (var i = 0; i < observed.length; i++)
|
||||||
|
assertEq(observed[i], expected[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
print(BUGNUMBER + ": " + summary);
|
||||||
|
|
||||||
|
function testType(type, inputs) {
|
||||||
|
var length = simdToArray(inputs[0][0]).length;
|
||||||
|
for (var [vec, s] of inputs) {
|
||||||
|
testWith(vec, s, SIMD[type].withX, withX);
|
||||||
|
testWith(vec, s, SIMD[type].withY, withY);
|
||||||
|
if (length <= 2)
|
||||||
|
continue;
|
||||||
|
testWith(vec, s, SIMD[type].withZ, withZ);
|
||||||
|
testWith(vec, s, SIMD[type].withW, withW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function TestError(){};
|
||||||
|
var good = {valueOf: () => 42};
|
||||||
|
var bad = {valueOf: () => {throw new TestError(); }};
|
||||||
|
|
||||||
|
var float32x4inputs = [
|
||||||
|
[float32x4(1, 2, 3, 4), 5],
|
||||||
|
[float32x4(1.87, 2.08, 3.84, 4.17), Math.fround(13.37)],
|
||||||
|
[float32x4(NaN, -0, Infinity, -Infinity), 0]
|
||||||
|
];
|
||||||
|
testType('float32x4', float32x4inputs);
|
||||||
|
|
||||||
|
var v = float32x4inputs[1][0];
|
||||||
|
assertEqX4(float32x4.withX(v, good), withX(simdToArray(v), good | 0));
|
||||||
|
assertThrowsInstanceOf(() => float32x4.withX(v, bad), TestError);
|
||||||
|
|
||||||
|
var float64x2inputs = [
|
||||||
|
[float64x2(1, 2), 5],
|
||||||
|
[float64x2(1.87, 2.08), Math.fround(13.37)],
|
||||||
|
[float64x2(NaN, -0), 0]
|
||||||
|
];
|
||||||
|
testType('float64x2', float64x2inputs);
|
||||||
|
|
||||||
|
var v = float64x2inputs[1][0];
|
||||||
|
assertEqX4(float64x2.withX(v, good), withX(simdToArray(v), good | 0));
|
||||||
|
assertThrowsInstanceOf(() => float64x2.withX(v, bad), TestError);
|
||||||
|
|
||||||
|
var int32x4inputs = [
|
||||||
|
[int32x4(1, 2, 3, 4), 5],
|
||||||
|
[int32x4(INT32_MIN, INT32_MAX, 3, 4), INT32_MIN],
|
||||||
|
];
|
||||||
|
testType('int32x4', int32x4inputs);
|
||||||
|
|
||||||
|
var v = int32x4inputs[1][0];
|
||||||
|
assertEqX4(int32x4.withX(v, good), withX(simdToArray(v), good | 0));
|
||||||
|
assertThrowsInstanceOf(() => int32x4.withX(v, bad), TestError);
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
test();
|
||||||
|
|
@ -38,15 +38,14 @@ NewObjectCache::fillGlobal(EntryIndex entry, const Class *clasp, js::GlobalObjec
|
|||||||
return fill(entry, clasp, global, kind, obj);
|
return fill(entry, clasp, global, kind, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline JSObject *
|
inline JSObject *
|
||||||
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::InitialHeap heap)
|
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entryIndex, js::gc::InitialHeap heap)
|
||||||
{
|
{
|
||||||
// The new object cache does not account for metadata attached via callbacks.
|
// The new object cache does not account for metadata attached via callbacks.
|
||||||
MOZ_ASSERT(!cx->compartment()->hasObjectMetadataCallback());
|
MOZ_ASSERT(!cx->compartment()->hasObjectMetadataCallback());
|
||||||
|
|
||||||
MOZ_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
|
MOZ_ASSERT(unsigned(entryIndex) < mozilla::ArrayLength(entries));
|
||||||
Entry *entry = &entries[entry_];
|
Entry *entry = &entries[entryIndex];
|
||||||
|
|
||||||
JSObject *templateObj = reinterpret_cast<JSObject *>(&entry->templateObject);
|
JSObject *templateObj = reinterpret_cast<JSObject *>(&entry->templateObject);
|
||||||
|
|
||||||
@ -60,16 +59,6 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::Initi
|
|||||||
if (cx->runtime()->gc.upcomingZealousGC())
|
if (cx->runtime()->gc.upcomingZealousGC())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Trigger an identical allocation to the one that notified us of OOM
|
|
||||||
// so that we trigger the right kind of GC automatically.
|
|
||||||
if (allowGC) {
|
|
||||||
mozilla::DebugOnly<JSObject *> obj =
|
|
||||||
js::gc::AllocateObjectForCacheHit<allowGC>(cx, entry->kind, heap, group->clasp());
|
|
||||||
MOZ_ASSERT(!obj);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(allowGC == NoGC);
|
|
||||||
JSObject *obj = js::gc::AllocateObjectForCacheHit<NoGC>(cx, entry->kind, heap, group->clasp());
|
JSObject *obj = js::gc::AllocateObjectForCacheHit<NoGC>(cx, entry->kind, heap, group->clasp());
|
||||||
if (obj) {
|
if (obj) {
|
||||||
copyCachedToObject(obj, templateObj, entry->kind);
|
copyCachedToObject(obj, templateObj, entry->kind);
|
||||||
@ -78,6 +67,11 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::Initi
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger an identical allocation to the one that notified us of OOM
|
||||||
|
// so that we trigger the right kind of GC automatically.
|
||||||
|
mozilla::DebugOnly<JSObject *> obj2 =
|
||||||
|
js::gc::AllocateObjectForCacheHit<CanGC>(cx, entry->kind, heap, group->clasp());
|
||||||
|
MOZ_ASSERT(!obj2);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +296,6 @@ class NewObjectCache
|
|||||||
* nullptr if returning the object could possibly trigger GC (does not
|
* nullptr if returning the object could possibly trigger GC (does not
|
||||||
* indicate failure).
|
* indicate failure).
|
||||||
*/
|
*/
|
||||||
template <AllowGC allowGC>
|
|
||||||
inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry, js::gc::InitialHeap heap);
|
inline JSObject *newObjectFromHit(JSContext *cx, EntryIndex entry, js::gc::InitialHeap heap);
|
||||||
|
|
||||||
/* Fill an entry after a cache miss. */
|
/* Fill an entry after a cache miss. */
|
||||||
|
@ -237,7 +237,15 @@ class MOZ_STACK_CLASS ComponentLoaderInfo {
|
|||||||
nsIChannel* ScriptChannel() { MOZ_ASSERT(mScriptChannel); return mScriptChannel; }
|
nsIChannel* ScriptChannel() { MOZ_ASSERT(mScriptChannel); return mScriptChannel; }
|
||||||
nsresult EnsureScriptChannel() {
|
nsresult EnsureScriptChannel() {
|
||||||
BEGIN_ENSURE(ScriptChannel, IOService, URI);
|
BEGIN_ENSURE(ScriptChannel, IOService, URI);
|
||||||
return mIOService->NewChannelFromURI(mURI, getter_AddRefs(mScriptChannel));
|
return NS_NewChannel(getter_AddRefs(mScriptChannel),
|
||||||
|
mURI,
|
||||||
|
nsContentUtils::GetSystemPrincipal(),
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_SCRIPT,
|
||||||
|
nullptr, // aLoadGroup
|
||||||
|
nullptr, // aCallbacks
|
||||||
|
nsIRequest::LOAD_NORMAL,
|
||||||
|
mIOService);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIURI* ResolvedURI() { MOZ_ASSERT(mResolvedURI); return mResolvedURI; }
|
nsIURI* ResolvedURI() { MOZ_ASSERT(mResolvedURI); return mResolvedURI; }
|
||||||
|
@ -696,6 +696,7 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
|
|||||||
/* static */ FrameMetrics
|
/* static */ FrameMetrics
|
||||||
nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame,
|
nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame,
|
||||||
nsIFrame* aScrollFrame,
|
nsIFrame* aScrollFrame,
|
||||||
|
nsIContent* aContent,
|
||||||
const nsIFrame* aReferenceFrame,
|
const nsIFrame* aReferenceFrame,
|
||||||
Layer* aLayer,
|
Layer* aLayer,
|
||||||
ViewID aScrollParentId,
|
ViewID aScrollParentId,
|
||||||
@ -711,20 +712,19 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame,
|
|||||||
metrics.SetViewport(CSSRect::FromAppUnits(aViewport));
|
metrics.SetViewport(CSSRect::FromAppUnits(aViewport));
|
||||||
|
|
||||||
ViewID scrollId = FrameMetrics::NULL_SCROLL_ID;
|
ViewID scrollId = FrameMetrics::NULL_SCROLL_ID;
|
||||||
nsIContent* content = aScrollFrame ? aScrollFrame->GetContent() : nullptr;
|
if (aContent) {
|
||||||
if (content) {
|
scrollId = nsLayoutUtils::FindOrCreateIDFor(aContent);
|
||||||
scrollId = nsLayoutUtils::FindOrCreateIDFor(content);
|
|
||||||
nsRect dp;
|
nsRect dp;
|
||||||
if (nsLayoutUtils::GetDisplayPort(content, &dp)) {
|
if (nsLayoutUtils::GetDisplayPort(aContent, &dp)) {
|
||||||
metrics.SetDisplayPort(CSSRect::FromAppUnits(dp));
|
metrics.SetDisplayPort(CSSRect::FromAppUnits(dp));
|
||||||
nsLayoutUtils::LogTestDataForPaint(aLayer->Manager(), scrollId, "displayport",
|
nsLayoutUtils::LogTestDataForPaint(aLayer->Manager(), scrollId, "displayport",
|
||||||
metrics.GetDisplayPort());
|
metrics.GetDisplayPort());
|
||||||
}
|
}
|
||||||
if (nsLayoutUtils::GetCriticalDisplayPort(content, &dp)) {
|
if (nsLayoutUtils::GetCriticalDisplayPort(aContent, &dp)) {
|
||||||
metrics.SetCriticalDisplayPort(CSSRect::FromAppUnits(dp));
|
metrics.SetCriticalDisplayPort(CSSRect::FromAppUnits(dp));
|
||||||
}
|
}
|
||||||
DisplayPortMarginsPropertyData* marginsData =
|
DisplayPortMarginsPropertyData* marginsData =
|
||||||
static_cast<DisplayPortMarginsPropertyData*>(content->GetProperty(nsGkAtoms::DisplayPortMargins));
|
static_cast<DisplayPortMarginsPropertyData*>(aContent->GetProperty(nsGkAtoms::DisplayPortMargins));
|
||||||
if (marginsData) {
|
if (marginsData) {
|
||||||
metrics.SetDisplayPortMargins(marginsData->mMargins);
|
metrics.SetDisplayPortMargins(marginsData->mMargins);
|
||||||
}
|
}
|
||||||
@ -1634,15 +1634,31 @@ already_AddRefed<LayerManager> nsDisplayList::PaintRoot(nsDisplayListBuilder* aB
|
|||||||
root->SetEventRegionsOverride(EventRegionsOverride::ForceDispatchToContent);
|
root->SetEventRegionsOverride(EventRegionsOverride::ForceDispatchToContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gfxPrefs::LayoutUseContainersForRootFrames()) {
|
// If we're using containerless scrolling, there is still one case where we
|
||||||
|
// want the root container layer to have metrics. If the parent process is
|
||||||
|
// using XUL windows, there is no root scrollframe, and without explicitly
|
||||||
|
// creating metrics there will be no guaranteed top-level APZC.
|
||||||
|
if (gfxPrefs::LayoutUseContainersForRootFrames() ||
|
||||||
|
(XRE_IsParentProcess() && !presShell->GetRootScrollFrame()))
|
||||||
|
{
|
||||||
bool isRoot = presContext->IsRootContentDocument();
|
bool isRoot = presContext->IsRootContentDocument();
|
||||||
|
|
||||||
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
|
|
||||||
|
|
||||||
nsRect viewport(aBuilder->ToReferenceFrame(frame), frame->GetSize());
|
nsRect viewport(aBuilder->ToReferenceFrame(frame), frame->GetSize());
|
||||||
|
|
||||||
|
nsIFrame* scrollFrame = presShell->GetRootScrollFrame();
|
||||||
|
nsIContent* content = nullptr;
|
||||||
|
if (scrollFrame) {
|
||||||
|
content = scrollFrame->GetContent();
|
||||||
|
} else if (!gfxPrefs::LayoutUseContainersForRootFrames()) {
|
||||||
|
// If there is no root scroll frame, and we're using containerless
|
||||||
|
// scrolling, pick the document element instead.
|
||||||
|
content = document->GetDocumentElement();
|
||||||
|
}
|
||||||
|
|
||||||
root->SetFrameMetrics(
|
root->SetFrameMetrics(
|
||||||
nsDisplayScrollLayer::ComputeFrameMetrics(frame, rootScrollFrame,
|
nsDisplayScrollLayer::ComputeFrameMetrics(frame,
|
||||||
|
presShell->GetRootScrollFrame(),
|
||||||
|
content,
|
||||||
aBuilder->FindReferenceFrameFor(frame),
|
aBuilder->FindReferenceFrameFor(frame),
|
||||||
root, FrameMetrics::NULL_SCROLL_ID, viewport,
|
root, FrameMetrics::NULL_SCROLL_ID, viewport,
|
||||||
isRoot, containerParameters));
|
isRoot, containerParameters));
|
||||||
@ -4121,9 +4137,10 @@ nsDisplaySubDocument::ComputeFrameMetrics(Layer* aLayer,
|
|||||||
mFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
mFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
||||||
|
|
||||||
return MakeUnique<FrameMetrics>(
|
return MakeUnique<FrameMetrics>(
|
||||||
nsDisplayScrollLayer::ComputeFrameMetrics(mFrame, rootScrollFrame, ReferenceFrame(),
|
nsDisplayScrollLayer::ComputeFrameMetrics(
|
||||||
aLayer, mScrollParentId, viewport,
|
mFrame, rootScrollFrame, rootScrollFrame->GetContent(), ReferenceFrame(),
|
||||||
isRootContentDocument, params));
|
aLayer, mScrollParentId, viewport,
|
||||||
|
isRootContentDocument, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -4456,8 +4473,10 @@ nsDisplayScrollLayer::ComputeFrameMetrics(Layer* aLayer,
|
|||||||
mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
mScrollFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
||||||
|
|
||||||
return UniquePtr<FrameMetrics>(new FrameMetrics(
|
return UniquePtr<FrameMetrics>(new FrameMetrics(
|
||||||
ComputeFrameMetrics(mScrolledFrame, mScrollFrame, ReferenceFrame(), aLayer,
|
ComputeFrameMetrics(
|
||||||
mScrollParentId, viewport, false, params)));
|
mScrolledFrame, mScrollFrame, mScrollFrame->GetContent(),
|
||||||
|
ReferenceFrame(), aLayer,
|
||||||
|
mScrollParentId, viewport, false, params)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -3175,6 +3175,7 @@ public:
|
|||||||
|
|
||||||
static FrameMetrics ComputeFrameMetrics(nsIFrame* aForFrame,
|
static FrameMetrics ComputeFrameMetrics(nsIFrame* aForFrame,
|
||||||
nsIFrame* aScrollFrame,
|
nsIFrame* aScrollFrame,
|
||||||
|
nsIContent* aContent,
|
||||||
const nsIFrame* aReferenceFrame,
|
const nsIFrame* aReferenceFrame,
|
||||||
Layer* aLayer,
|
Layer* aLayer,
|
||||||
ViewID aScrollParentId,
|
ViewID aScrollParentId,
|
||||||
|
@ -867,6 +867,11 @@ GetDisplayPortFromMarginsData(nsIContent* aContent,
|
|||||||
// We want the scroll frame, the root scroll frame differs from all
|
// We want the scroll frame, the root scroll frame differs from all
|
||||||
// others in that the primary frame is not the scroll frame.
|
// others in that the primary frame is not the scroll frame.
|
||||||
frame = frame->PresContext()->PresShell()->GetRootScrollFrame();
|
frame = frame->PresContext()->PresShell()->GetRootScrollFrame();
|
||||||
|
if (!frame) {
|
||||||
|
// If there is no root scrollframe, just exit.
|
||||||
|
return ApplyRectMultiplier(base, aMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
isRoot = true;
|
isRoot = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3177,7 +3177,8 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer,
|
|||||||
bool isRoot = mIsRoot && mOuter->PresContext()->IsRootContentDocument();
|
bool isRoot = mIsRoot && mOuter->PresContext()->IsRootContentDocument();
|
||||||
|
|
||||||
*aOutput->AppendElement() =
|
*aOutput->AppendElement() =
|
||||||
nsDisplayScrollLayer::ComputeFrameMetrics(mScrolledFrame, mOuter,
|
nsDisplayScrollLayer::ComputeFrameMetrics(
|
||||||
|
mScrolledFrame, mOuter, mOuter->GetContent(),
|
||||||
aContainerReferenceFrame, aLayer, mScrollParentID,
|
aContainerReferenceFrame, aLayer, mScrollParentID,
|
||||||
scrollport, isRoot, aParameters);
|
scrollport, isRoot, aParameters);
|
||||||
}
|
}
|
||||||
|
@ -649,8 +649,8 @@ nsChangeHint nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const
|
|||||||
(outlineIsVisible && (mOutlineOffset != aOther.mOutlineOffset ||
|
(outlineIsVisible && (mOutlineOffset != aOther.mOutlineOffset ||
|
||||||
mOutlineWidth != aOther.mOutlineWidth ||
|
mOutlineWidth != aOther.mOutlineWidth ||
|
||||||
mTwipsPerPixel != aOther.mTwipsPerPixel))) {
|
mTwipsPerPixel != aOther.mTwipsPerPixel))) {
|
||||||
return NS_CombineHint(nsChangeHint_AllReflowHints,
|
return NS_CombineHint(nsChangeHint_UpdateOverflow,
|
||||||
nsChangeHint_RepaintFrame);
|
nsChangeHint_SchedulePaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mOutlineStyle != aOther.mOutlineStyle) ||
|
if ((mOutlineStyle != aOther.mOutlineStyle) ||
|
||||||
|
@ -1065,15 +1065,15 @@ struct nsStyleOutline {
|
|||||||
void RecalcData(nsPresContext* aContext);
|
void RecalcData(nsPresContext* aContext);
|
||||||
nsChangeHint CalcDifference(const nsStyleOutline& aOther) const;
|
nsChangeHint CalcDifference(const nsStyleOutline& aOther) const;
|
||||||
static nsChangeHint MaxDifference() {
|
static nsChangeHint MaxDifference() {
|
||||||
return NS_CombineHint(nsChangeHint_AllReflowHints,
|
return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateOverflow,
|
||||||
|
nsChangeHint_SchedulePaint),
|
||||||
NS_CombineHint(nsChangeHint_RepaintFrame,
|
NS_CombineHint(nsChangeHint_RepaintFrame,
|
||||||
nsChangeHint_NeutralChange));
|
nsChangeHint_NeutralChange));
|
||||||
}
|
}
|
||||||
static nsChangeHint MaxDifferenceNeverInherited() {
|
static nsChangeHint MaxDifferenceNeverInherited() {
|
||||||
// CalcDifference never returns nsChangeHint_NeedReflow or
|
// CalcDifference never returns nsChangeHint_NeedReflow or
|
||||||
// nsChangeHint_ClearAncestorIntrinsics as inherited hints.
|
// nsChangeHint_ClearAncestorIntrinsics at all.
|
||||||
return NS_CombineHint(nsChangeHint_NeedReflow,
|
return nsChangeHint(0);
|
||||||
nsChangeHint_ClearAncestorIntrinsics);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsStyleCorners mOutlineRadius; // [reset] coord, percent, calc
|
nsStyleCorners mOutlineRadius; // [reset] coord, percent, calc
|
||||||
|
@ -131,6 +131,7 @@ skip-if = toolkit == 'android' #bug 536603
|
|||||||
[test_descriptor_storage.html]
|
[test_descriptor_storage.html]
|
||||||
[test_descriptor_syntax_errors.html]
|
[test_descriptor_syntax_errors.html]
|
||||||
[test_dont_use_document_colors.html]
|
[test_dont_use_document_colors.html]
|
||||||
|
[test_dynamic_change_causing_reflow.html]
|
||||||
[test_exposed_prop_accessors.html]
|
[test_exposed_prop_accessors.html]
|
||||||
[test_extra_inherit_initial.html]
|
[test_extra_inherit_initial.html]
|
||||||
[test_flexbox_align_self_auto.html]
|
[test_flexbox_align_self_auto.html]
|
||||||
|
143
layout/style/test/test_dynamic_change_causing_reflow.html
Normal file
143
layout/style/test/test_dynamic_change_causing_reflow.html
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1131371
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Test for Bug 1131371</title>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1131371">Mozilla Bug 1131371</a>
|
||||||
|
<div id="display">
|
||||||
|
<div id="content">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript;version=1.7">
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/** Test for Bug 1131371 **/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This test verifies that certain style changes do or don't cause reflow
|
||||||
|
* and/or frame construction. We do this by checking the framesReflowed &
|
||||||
|
* framesConstructed counts, before & after a style-change, and verifying
|
||||||
|
* that any change to these counts is in line with our expectations.
|
||||||
|
*
|
||||||
|
* Each entry in gTestcases contains these member-values:
|
||||||
|
* - beforeStyle (optional): initial value to use for "style" attribute.
|
||||||
|
* - afterStyle: value to change the "style" attribute to.
|
||||||
|
*
|
||||||
|
* Testcases may also include two optional member-values to express that reflow
|
||||||
|
* and/or frame construction *are* in fact expected:
|
||||||
|
* - expectConstruction (optional): if set to something truthy, then we expect
|
||||||
|
* frame construction to occur when afterStyle is set. Otherwise, we
|
||||||
|
* expect that frame construction should *not* occur.
|
||||||
|
* - expectReflow (optional): if set to something truthy, then we expect
|
||||||
|
* reflow to occur when afterStyle is set. Otherwise, we expect that
|
||||||
|
* reflow should *not* occur.
|
||||||
|
*/
|
||||||
|
const gTestcases = [
|
||||||
|
// Things that shouldn't cause reflow:
|
||||||
|
// -----------------------------------
|
||||||
|
// * Adding an outline (e.g. for focus ring).
|
||||||
|
{
|
||||||
|
afterStyle: "outline: 1px dotted black",
|
||||||
|
},
|
||||||
|
|
||||||
|
// * Changing between completely-different outlines.
|
||||||
|
{
|
||||||
|
beforeStyle: "outline: 2px solid black",
|
||||||
|
afterStyle: "outline: 6px dashed yellow",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Things that *should* cause reflow:
|
||||||
|
// ----------------------------------
|
||||||
|
// (e.g. to make sure our counts are actually measuring something)
|
||||||
|
|
||||||
|
// * Changing 'height' should cause reflow, but not frame construction.
|
||||||
|
{
|
||||||
|
beforeStyle: "height: 10px",
|
||||||
|
afterStyle: "height: 15px",
|
||||||
|
expectReflow: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// * Changing 'display' should cause frame construction and reflow.
|
||||||
|
{
|
||||||
|
beforeStyle: "display: inline",
|
||||||
|
afterStyle: "display: table",
|
||||||
|
expectConstruction: true,
|
||||||
|
expectReflow: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
// Helper function to let us call either "is" or "isnot" & assemble
|
||||||
|
// the failure message, based on the provided parameters.
|
||||||
|
function checkFinalCount(aFinalCount, aExpectedCount,
|
||||||
|
aExpectChange, aMsgPrefix, aCountDescription)
|
||||||
|
{
|
||||||
|
let compareFunc;
|
||||||
|
let msg = aMsgPrefix;
|
||||||
|
if (aExpectChange) {
|
||||||
|
compareFunc = isnot;
|
||||||
|
msg += "should cause " + aCountDescription;
|
||||||
|
} else {
|
||||||
|
compareFunc = is;
|
||||||
|
msg += "should not cause " + aCountDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
compareFunc(aFinalCount, aExpectedCount, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vars used in runOneTest that we really only have to look up once:
|
||||||
|
const gUtils = SpecialPowers.getDOMWindowUtils(window);
|
||||||
|
const gElem = document.getElementById("content");
|
||||||
|
|
||||||
|
function runOneTest(aTestcase)
|
||||||
|
{
|
||||||
|
// sanity-check that we have the one main thing we need:
|
||||||
|
if (!aTestcase.afterStyle) {
|
||||||
|
ok(false, "testcase is missing an 'afterStyle' to change to");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the "before" style, and compose the first part of the message
|
||||||
|
// to be used in our "is"/"isnot" invocations:
|
||||||
|
let msgPrefix = "Changing style ";
|
||||||
|
if (aTestcase.beforeStyle) {
|
||||||
|
gElem.setAttribute("style", aTestcase.beforeStyle);
|
||||||
|
msgPrefix += "from '" + aTestcase.beforeStyle + "' ";
|
||||||
|
}
|
||||||
|
msgPrefix += "to '" + aTestcase.afterStyle + "' ";
|
||||||
|
|
||||||
|
// Establish initial counts:
|
||||||
|
let unusedVal = gElem.offsetHeight; // flush layout
|
||||||
|
let origFramesConstructed = gUtils.framesConstructed;
|
||||||
|
let origFramesReflowed = gUtils.framesReflowed;
|
||||||
|
|
||||||
|
// Make the change and flush:
|
||||||
|
gElem.setAttribute("style", aTestcase.afterStyle);
|
||||||
|
unusedVal = gElem.offsetHeight; // flush layout
|
||||||
|
|
||||||
|
// Make our is/isnot assertions about whether things should have changed:
|
||||||
|
checkFinalCount(gUtils.framesConstructed, origFramesConstructed,
|
||||||
|
aTestcase.expectConstruction, msgPrefix,
|
||||||
|
"frame construction");
|
||||||
|
checkFinalCount(gUtils.framesReflowed, origFramesReflowed,
|
||||||
|
aTestcase.expectReflow, msgPrefix,
|
||||||
|
"reflow");
|
||||||
|
|
||||||
|
// Clean up!
|
||||||
|
gElem.removeAttribute("style");
|
||||||
|
}
|
||||||
|
|
||||||
|
gTestcases.forEach(runOneTest);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -366,8 +366,10 @@ void NrIceCtx::trickle_cb(void *arg, nr_ice_ctx *ice_ctx,
|
|||||||
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
||||||
RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
|
RefPtr<NrIceMediaStream> s = ctx->FindStream(stream);
|
||||||
|
|
||||||
// Streams which do not exist shouldn't have candidates.
|
if (!s) {
|
||||||
MOZ_ASSERT(s);
|
// This stream has been removed because it is inactive
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Format the candidate.
|
// Format the candidate.
|
||||||
char candidate_str[NR_ICE_MAX_ATTRIBUTE_SIZE];
|
char candidate_str[NR_ICE_MAX_ATTRIBUTE_SIZE];
|
||||||
@ -668,32 +670,26 @@ abort:
|
|||||||
|
|
||||||
nsresult NrIceCtx::StartGathering() {
|
nsresult NrIceCtx::StartGathering() {
|
||||||
ASSERT_ON_THREAD(sts_target_);
|
ASSERT_ON_THREAD(sts_target_);
|
||||||
MOZ_ASSERT(connection_state_ == ICE_CTX_INIT);
|
// This might start gathering for the first time, or again after
|
||||||
if (connection_state_ != ICE_CTX_INIT) {
|
// renegotiation, or might do nothing at all if gathering has already
|
||||||
MOZ_MTLOG(ML_ERROR, "ICE ctx in the wrong state for gathering: '"
|
// finished.
|
||||||
<< name_ << "' state: " << connection_state_);
|
int r = nr_ice_gather(ctx_, &NrIceCtx::gather_cb, this);
|
||||||
|
|
||||||
|
if (r && (r != R_WOULDBLOCK)) {
|
||||||
|
MOZ_MTLOG(ML_ERROR, "Couldn't gather ICE candidates for '"
|
||||||
|
<< name_ << "', error=" << r);
|
||||||
SetConnectionState(ICE_CTX_FAILED);
|
SetConnectionState(ICE_CTX_FAILED);
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int r = nr_ice_initialize(ctx_, &NrIceCtx::initialized_cb, this);
|
|
||||||
|
|
||||||
if (r && r != R_WOULDBLOCK) {
|
|
||||||
MOZ_MTLOG(ML_ERROR, "Couldn't gather ICE candidates for '"
|
|
||||||
<< name_ << "'");
|
|
||||||
SetConnectionState(ICE_CTX_FAILED);
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetGatheringState(ICE_CTX_GATHER_STARTED);
|
SetGatheringState(ICE_CTX_GATHER_STARTED);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<NrIceMediaStream> NrIceCtx::FindStream(
|
RefPtr<NrIceMediaStream> NrIceCtx::FindStream(
|
||||||
nr_ice_media_stream *stream) {
|
nr_ice_media_stream *stream) {
|
||||||
for (size_t i=0; i<streams_.size(); ++i) {
|
for (size_t i=0; i<streams_.size(); ++i) {
|
||||||
if (streams_[i]->stream() == stream) {
|
if (streams_[i] && (streams_[i]->stream() == stream)) {
|
||||||
return streams_[i];
|
return streams_[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -771,7 +767,7 @@ nsresult NrIceCtx::StartChecks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void NrIceCtx::initialized_cb(NR_SOCKET s, int h, void *arg) {
|
void NrIceCtx::gather_cb(NR_SOCKET s, int h, void *arg) {
|
||||||
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
NrIceCtx *ctx = static_cast<NrIceCtx *>(arg);
|
||||||
|
|
||||||
ctx->SetGatheringState(ICE_CTX_GATHER_COMPLETE);
|
ctx->SetGatheringState(ICE_CTX_GATHER_COMPLETE);
|
||||||
|
@ -225,7 +225,7 @@ class NrIceCtx {
|
|||||||
|
|
||||||
// Create a media stream
|
// Create a media stream
|
||||||
RefPtr<NrIceMediaStream> CreateStream(const std::string& name,
|
RefPtr<NrIceMediaStream> CreateStream(const std::string& name,
|
||||||
int components);
|
int components);
|
||||||
|
|
||||||
RefPtr<NrIceMediaStream> GetStream(size_t index) {
|
RefPtr<NrIceMediaStream> GetStream(size_t index) {
|
||||||
if (index < streams_.size()) {
|
if (index < streams_.size()) {
|
||||||
@ -234,6 +234,11 @@ class NrIceCtx {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoveStream(size_t index)
|
||||||
|
{
|
||||||
|
streams_[index] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// The name of the ctx
|
// The name of the ctx
|
||||||
const std::string& name() const { return name_; }
|
const std::string& name() const { return name_; }
|
||||||
|
|
||||||
@ -325,7 +330,7 @@ class NrIceCtx {
|
|||||||
DISALLOW_COPY_ASSIGN(NrIceCtx);
|
DISALLOW_COPY_ASSIGN(NrIceCtx);
|
||||||
|
|
||||||
// Callbacks for nICEr
|
// Callbacks for nICEr
|
||||||
static void initialized_cb(NR_SOCKET s, int h, void *arg); // ICE initialized
|
static void gather_cb(NR_SOCKET s, int h, void *arg); // ICE gather complete
|
||||||
|
|
||||||
// Handler implementation
|
// Handler implementation
|
||||||
static int select_pair(void *obj,nr_ice_media_stream *stream,
|
static int select_pair(void *obj,nr_ice_media_stream *stream,
|
||||||
|
@ -209,6 +209,7 @@ nsresult NrIceMediaStream::ParseAttributes(std::vector<std::string>&
|
|||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_parsed_attrs_ = true;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ class NrIceMediaStream {
|
|||||||
|
|
||||||
// Parse remote attributes
|
// Parse remote attributes
|
||||||
nsresult ParseAttributes(std::vector<std::string>& candidates);
|
nsresult ParseAttributes(std::vector<std::string>& candidates);
|
||||||
|
bool HasParsedAttributes() const { return has_parsed_attrs_; }
|
||||||
|
|
||||||
// Parse trickle ICE candidate
|
// Parse trickle ICE candidate
|
||||||
nsresult ParseTrickleCandidate(const std::string& candidate);
|
nsresult ParseTrickleCandidate(const std::string& candidate);
|
||||||
@ -198,7 +199,8 @@ class NrIceMediaStream {
|
|||||||
name_(name),
|
name_(name),
|
||||||
components_(components),
|
components_(components),
|
||||||
stream_(nullptr),
|
stream_(nullptr),
|
||||||
level_(0) {}
|
level_(0),
|
||||||
|
has_parsed_attrs_(false) {}
|
||||||
|
|
||||||
~NrIceMediaStream();
|
~NrIceMediaStream();
|
||||||
|
|
||||||
@ -210,6 +212,7 @@ class NrIceMediaStream {
|
|||||||
const size_t components_;
|
const size_t components_;
|
||||||
nr_ice_media_stream *stream_;
|
nr_ice_media_stream *stream_;
|
||||||
uint16_t level_;
|
uint16_t level_;
|
||||||
|
bool has_parsed_attrs_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
PR_Sleep(1000);
|
PR_Sleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddStream(int components) {
|
void AddStream_s(int components) {
|
||||||
char name[100];
|
char name[100];
|
||||||
snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
|
snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(),
|
||||||
(int)streams_.size());
|
(int)streams_.size());
|
||||||
@ -281,6 +281,14 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
|
stream->SignalPacketReceived.connect(this, &IceTestPeer::PacketReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddStream(int components)
|
||||||
|
{
|
||||||
|
test_utils->sts_target()->Dispatch(WrapRunnable(this,
|
||||||
|
&IceTestPeer::AddStream_s,
|
||||||
|
components),
|
||||||
|
NS_DISPATCH_SYNC);
|
||||||
|
}
|
||||||
|
|
||||||
void SetStunServer(const std::string addr, uint16_t port) {
|
void SetStunServer(const std::string addr, uint16_t port) {
|
||||||
if (addr.empty()) {
|
if (addr.empty()) {
|
||||||
// Happens when MOZ_DISABLE_NONLOCAL_CONNECTIONS is set
|
// Happens when MOZ_DISABLE_NONLOCAL_CONNECTIONS is set
|
||||||
@ -410,9 +418,17 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
|
|
||||||
bool gathering_complete() { return gathering_complete_; }
|
bool gathering_complete() { return gathering_complete_; }
|
||||||
int ready_ct() { return ready_ct_; }
|
int ready_ct() { return ready_ct_; }
|
||||||
bool is_ready(size_t stream) {
|
bool is_ready_s(size_t stream) {
|
||||||
return streams_[stream]->state() == NrIceMediaStream::ICE_OPEN;
|
return streams_[stream]->state() == NrIceMediaStream::ICE_OPEN;
|
||||||
}
|
}
|
||||||
|
bool is_ready(size_t stream)
|
||||||
|
{
|
||||||
|
bool result;
|
||||||
|
test_utils->sts_target()->Dispatch(
|
||||||
|
WrapRunnableRet(this, &IceTestPeer::is_ready_s, stream, &result),
|
||||||
|
NS_DISPATCH_SYNC);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
bool ice_complete() { return ice_complete_; }
|
bool ice_complete() { return ice_complete_; }
|
||||||
bool ice_reached_checking() { return ice_reached_checking_; }
|
bool ice_reached_checking() { return ice_reached_checking_; }
|
||||||
size_t received() { return received_; }
|
size_t received() { return received_; }
|
||||||
@ -426,12 +442,16 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
remote_ = remote;
|
remote_ = remote;
|
||||||
|
|
||||||
trickle_mode_ = trickle_mode;
|
trickle_mode_ = trickle_mode;
|
||||||
|
ice_complete_ = false;
|
||||||
res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
|
res = ice_ctx_->ParseGlobalAttributes(remote->GetGlobalAttributes());
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
|
|
||||||
if (trickle_mode == TRICKLE_NONE ||
|
if (trickle_mode == TRICKLE_NONE ||
|
||||||
trickle_mode == TRICKLE_REAL) {
|
trickle_mode == TRICKLE_REAL) {
|
||||||
for (size_t i=0; i<streams_.size(); ++i) {
|
for (size_t i=0; i<streams_.size(); ++i) {
|
||||||
|
if (streams_[i]->HasParsedAttributes()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
std::vector<std::string> candidates =
|
std::vector<std::string> candidates =
|
||||||
remote->GetCandidates(i);
|
remote->GetCandidates(i);
|
||||||
|
|
||||||
@ -444,7 +464,11 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
} else {
|
} else {
|
||||||
// Parse empty attributes and then trickle them out later
|
// Parse empty attributes and then trickle them out later
|
||||||
for (size_t i=0; i<streams_.size(); ++i) {
|
for (size_t i=0; i<streams_.size(); ++i) {
|
||||||
|
if (streams_[i]->HasParsedAttributes()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
std::vector<std::string> empty_attrs;
|
std::vector<std::string> empty_attrs;
|
||||||
|
std::cout << "Calling ParseAttributes on stream " << i << std::endl;
|
||||||
res = streams_[i]->ParseAttributes(empty_attrs);
|
res = streams_[i]->ParseAttributes(empty_attrs);
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
}
|
}
|
||||||
@ -470,6 +494,8 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
// If we are in trickle deferred mode, now trickle in the candidates
|
// If we are in trickle deferred mode, now trickle in the candidates
|
||||||
// for |stream|
|
// for |stream|
|
||||||
|
|
||||||
|
// The size of streams_ is not going to change out from under us, so should
|
||||||
|
// be safe here.
|
||||||
ASSERT_GT(remote_->streams_.size(), stream);
|
ASSERT_GT(remote_->streams_.size(), stream);
|
||||||
|
|
||||||
std::vector<SchedulableTrickleCandidate*>& candidates =
|
std::vector<SchedulableTrickleCandidate*>& candidates =
|
||||||
@ -602,6 +628,16 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ice_ctx_ = nullptr;
|
ice_ctx_ = nullptr;
|
||||||
|
|
||||||
|
if (remote_) {
|
||||||
|
remote_->UnsetRemote();
|
||||||
|
remote_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnsetRemote()
|
||||||
|
{
|
||||||
|
remote_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StartChecks() {
|
void StartChecks() {
|
||||||
@ -649,7 +685,7 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
|
|
||||||
// If we are connected, then try to trickle to the
|
// If we are connected, then try to trickle to the
|
||||||
// other side.
|
// other side.
|
||||||
if (remote_ && remote_->remote_) {
|
if (remote_ && remote_->remote_ && (trickle_mode_ != TRICKLE_SIMULATE)) {
|
||||||
std::vector<mozilla::RefPtr<NrIceMediaStream> >::iterator it =
|
std::vector<mozilla::RefPtr<NrIceMediaStream> >::iterator it =
|
||||||
std::find(streams_.begin(), streams_.end(), stream);
|
std::find(streams_.begin(), streams_.end(), stream);
|
||||||
ASSERT_NE(streams_.end(), it);
|
ASSERT_NE(streams_.end(), it);
|
||||||
@ -663,8 +699,9 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult GetCandidatePairs(size_t stream_index,
|
nsresult GetCandidatePairs_s(size_t stream_index,
|
||||||
std::vector<NrIceCandidatePair>* pairs) {
|
std::vector<NrIceCandidatePair>* pairs)
|
||||||
|
{
|
||||||
MOZ_ASSERT(pairs);
|
MOZ_ASSERT(pairs);
|
||||||
if (stream_index >= streams_.size()) {
|
if (stream_index >= streams_.size()) {
|
||||||
// Is there a better error for "no such index"?
|
// Is there a better error for "no such index"?
|
||||||
@ -672,14 +709,20 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult res;
|
return streams_[stream_index]->GetCandidatePairs(pairs);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult GetCandidatePairs(size_t stream_index,
|
||||||
|
std::vector<NrIceCandidatePair>* pairs) {
|
||||||
|
nsresult v;
|
||||||
test_utils->sts_target()->Dispatch(
|
test_utils->sts_target()->Dispatch(
|
||||||
WrapRunnableRet(streams_[stream_index],
|
WrapRunnableRet(this,
|
||||||
&NrIceMediaStream::GetCandidatePairs,
|
&IceTestPeer::GetCandidatePairs_s,
|
||||||
|
stream_index,
|
||||||
pairs,
|
pairs,
|
||||||
&res),
|
&v),
|
||||||
NS_DISPATCH_SYNC);
|
NS_DISPATCH_SYNC);
|
||||||
return res;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpCandidatePair(const NrIceCandidatePair& pair) {
|
void DumpCandidatePair(const NrIceCandidatePair& pair) {
|
||||||
@ -693,7 +736,7 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
<< " codeword = " << pair.codeword << std::endl;
|
<< " codeword = " << pair.codeword << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpCandidatePairs(NrIceMediaStream *stream) {
|
void DumpCandidatePairs_s(NrIceMediaStream *stream) {
|
||||||
std::vector<NrIceCandidatePair> pairs;
|
std::vector<NrIceCandidatePair> pairs;
|
||||||
nsresult res = stream->GetCandidatePairs(&pairs);
|
nsresult res = stream->GetCandidatePairs(&pairs);
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
@ -707,10 +750,10 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
std::cerr << "]" << std::endl;
|
std::cerr << "]" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpCandidatePairs() {
|
void DumpCandidatePairs_s() {
|
||||||
std::cerr << "Dumping candidate pairs for all streams [" << std::endl;
|
std::cerr << "Dumping candidate pairs for all streams [" << std::endl;
|
||||||
for (size_t s = 0; s < streams_.size(); ++s) {
|
for (size_t s = 0; s < streams_.size(); ++s) {
|
||||||
DumpCandidatePairs(streams_[s]);
|
DumpCandidatePairs_s(streams_[s]);
|
||||||
}
|
}
|
||||||
std::cerr << "]" << std::endl;
|
std::cerr << "]" << std::endl;
|
||||||
}
|
}
|
||||||
@ -790,11 +833,11 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
void StreamReady(NrIceMediaStream *stream) {
|
void StreamReady(NrIceMediaStream *stream) {
|
||||||
++ready_ct_;
|
++ready_ct_;
|
||||||
std::cerr << "Stream ready " << stream->name() << " ct=" << ready_ct_ << std::endl;
|
std::cerr << "Stream ready " << stream->name() << " ct=" << ready_ct_ << std::endl;
|
||||||
DumpCandidatePairs(stream);
|
DumpCandidatePairs_s(stream);
|
||||||
}
|
}
|
||||||
void StreamFailed(NrIceMediaStream *stream) {
|
void StreamFailed(NrIceMediaStream *stream) {
|
||||||
std::cerr << "Stream failed " << stream->name() << " ct=" << ready_ct_ << std::endl;
|
std::cerr << "Stream failed " << stream->name() << " ct=" << ready_ct_ << std::endl;
|
||||||
DumpCandidatePairs(stream);
|
DumpCandidatePairs_s(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionStateChange(NrIceCtx* ctx,
|
void ConnectionStateChange(NrIceCtx* ctx,
|
||||||
@ -834,20 +877,39 @@ class IceTestPeer : public sigslot::has_slots<> {
|
|||||||
candidate_filter_ = filter;
|
candidate_filter_ = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow us to parse candidates directly on the current thread.
|
void ParseCandidate_s(size_t i, const std::string& candidate) {
|
||||||
void ParseCandidate(size_t i, const std::string& candidate) {
|
|
||||||
std::vector<std::string> attributes;
|
std::vector<std::string> attributes;
|
||||||
|
|
||||||
attributes.push_back(candidate);
|
attributes.push_back(candidate);
|
||||||
streams_[i]->ParseAttributes(attributes);
|
streams_[i]->ParseAttributes(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisableComponent(size_t stream, int component_id) {
|
void ParseCandidate(size_t i, const std::string& candidate)
|
||||||
|
{
|
||||||
|
test_utils->sts_target()->Dispatch(
|
||||||
|
WrapRunnable(this,
|
||||||
|
&IceTestPeer::ParseCandidate_s,
|
||||||
|
i,
|
||||||
|
candidate),
|
||||||
|
NS_DISPATCH_SYNC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisableComponent_s(size_t stream, int component_id) {
|
||||||
ASSERT_LT(stream, streams_.size());
|
ASSERT_LT(stream, streams_.size());
|
||||||
nsresult res = streams_[stream]->DisableComponent(component_id);
|
nsresult res = streams_[stream]->DisableComponent(component_id);
|
||||||
ASSERT_TRUE(NS_SUCCEEDED(res));
|
ASSERT_TRUE(NS_SUCCEEDED(res));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisableComponent(size_t stream, int component_id)
|
||||||
|
{
|
||||||
|
test_utils->sts_target()->Dispatch(
|
||||||
|
WrapRunnable(this,
|
||||||
|
&IceTestPeer::DisableComponent_s,
|
||||||
|
stream,
|
||||||
|
component_id),
|
||||||
|
NS_DISPATCH_SYNC);
|
||||||
|
}
|
||||||
|
|
||||||
int trickled() { return trickled_; }
|
int trickled() { return trickled_; }
|
||||||
|
|
||||||
void SetControlling(NrIceCtx::Controlling controlling) {
|
void SetControlling(NrIceCtx::Controlling controlling) {
|
||||||
@ -1612,6 +1674,64 @@ TEST_F(IceConnectTest, TestConnectTrickleTwoStreamsOneComponent) {
|
|||||||
AssertCheckingReached();
|
AssertCheckingReached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RealisticTrickleDelay(
|
||||||
|
std::vector<SchedulableTrickleCandidate*>& candidates) {
|
||||||
|
for (size_t i = 0; i < candidates.size(); ++i) {
|
||||||
|
SchedulableTrickleCandidate* cand = candidates[i];
|
||||||
|
if (cand->IsHost()) {
|
||||||
|
cand->Schedule(i*10);
|
||||||
|
} else if (cand->IsReflexive()) {
|
||||||
|
cand->Schedule(i*10 + 100);
|
||||||
|
} else if (cand->IsRelay()) {
|
||||||
|
cand->Schedule(i*10 + 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DelayRelayCandidates(
|
||||||
|
std::vector<SchedulableTrickleCandidate*>& candidates,
|
||||||
|
unsigned int ms) {
|
||||||
|
for (auto i = candidates.begin(); i != candidates.end(); ++i) {
|
||||||
|
if ((*i)->IsRelay()) {
|
||||||
|
(*i)->Schedule(ms);
|
||||||
|
} else {
|
||||||
|
(*i)->Schedule(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IceConnectTest, TestConnectTrickleAddStreamDuringICE) {
|
||||||
|
AddStream("first", 1);
|
||||||
|
ASSERT_TRUE(Gather());
|
||||||
|
ConnectTrickle();
|
||||||
|
RealisticTrickleDelay(p1_->ControlTrickle(0));
|
||||||
|
RealisticTrickleDelay(p2_->ControlTrickle(0));
|
||||||
|
AddStream("second", 1);
|
||||||
|
RealisticTrickleDelay(p1_->ControlTrickle(1));
|
||||||
|
RealisticTrickleDelay(p2_->ControlTrickle(1));
|
||||||
|
ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
|
||||||
|
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
|
||||||
|
AssertCheckingReached();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(IceConnectTest, TestConnectTrickleAddStreamAfterICE) {
|
||||||
|
AddStream("first", 1);
|
||||||
|
ASSERT_TRUE(Gather());
|
||||||
|
ConnectTrickle();
|
||||||
|
RealisticTrickleDelay(p1_->ControlTrickle(0));
|
||||||
|
RealisticTrickleDelay(p2_->ControlTrickle(0));
|
||||||
|
ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
|
||||||
|
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
|
||||||
|
AddStream("second", 1);
|
||||||
|
ASSERT_TRUE(Gather());
|
||||||
|
ConnectTrickle();
|
||||||
|
RealisticTrickleDelay(p1_->ControlTrickle(1));
|
||||||
|
RealisticTrickleDelay(p2_->ControlTrickle(1));
|
||||||
|
ASSERT_TRUE_WAIT(p1_->ice_complete(), 1000);
|
||||||
|
ASSERT_TRUE_WAIT(p2_->ice_complete(), 1000);
|
||||||
|
AssertCheckingReached();
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
|
TEST_F(IceConnectTest, TestConnectRealTrickleOneStreamOneComponent) {
|
||||||
AddStream("first", 1);
|
AddStream("first", 1);
|
||||||
AddStream("second", 1);
|
AddStream("second", 1);
|
||||||
@ -1657,32 +1777,6 @@ TEST_F(IceConnectTest, TestConnectTurnWithDelay) {
|
|||||||
WaitForComplete();
|
WaitForComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RealisticTrickleDelay(
|
|
||||||
std::vector<SchedulableTrickleCandidate*>& candidates) {
|
|
||||||
for (size_t i = 0; i < candidates.size(); ++i) {
|
|
||||||
SchedulableTrickleCandidate* cand = candidates[i];
|
|
||||||
if (cand->IsHost()) {
|
|
||||||
cand->Schedule(i*10);
|
|
||||||
} else if (cand->IsReflexive()) {
|
|
||||||
cand->Schedule(i*10 + 100);
|
|
||||||
} else if (cand->IsRelay()) {
|
|
||||||
cand->Schedule(i*10 + 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DelayRelayCandidates(
|
|
||||||
std::vector<SchedulableTrickleCandidate*>& candidates,
|
|
||||||
unsigned int ms) {
|
|
||||||
for (auto i = candidates.begin(); i != candidates.end(); ++i) {
|
|
||||||
if ((*i)->IsRelay()) {
|
|
||||||
(*i)->Schedule(ms);
|
|
||||||
} else {
|
|
||||||
(*i)->Schedule(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelay) {
|
TEST_F(IceConnectTest, TestConnectTurnWithNormalTrickleDelay) {
|
||||||
if (g_turn_server.empty())
|
if (g_turn_server.empty())
|
||||||
return;
|
return;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user