зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team
This commit is contained in:
Коммит
90db5d3cce
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
||||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||||
# don't change CLOBBER for WebIDL changes any more.
|
# don't change CLOBBER for WebIDL changes any more.
|
||||||
|
|
||||||
Bug 1061335 - CLOBBER for Win32 compiler update.
|
Bug 609976 - CLOBBER
|
||||||
|
|
|
@ -28,7 +28,6 @@ html xul|scrollbar {
|
||||||
background-image: none !important;
|
background-image: none !important;
|
||||||
border: 0px solid transparent !important;
|
border: 0px solid transparent !important;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xul|scrollbar[orient="vertical"] {
|
xul|scrollbar[orient="vertical"] {
|
||||||
|
@ -56,7 +55,6 @@ xul|scrollbar[orient="horizontal"] xul|thumb {
|
||||||
xul|scrollbar:not([active="true"]),
|
xul|scrollbar:not([active="true"]),
|
||||||
xul|scrollbar[disabled] {
|
xul|scrollbar[disabled] {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 1s ease;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xul|scrollbarbutton {
|
xul|scrollbarbutton {
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<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="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<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="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||||
</project>
|
</project>
|
||||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<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="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
||||||
|
|
|
@ -4,6 +4,6 @@
|
||||||
"remote": "",
|
"remote": "",
|
||||||
"branch": ""
|
"branch": ""
|
||||||
},
|
},
|
||||||
"revision": "63436aa17e7fa3ad521fdeffdc22b81c36e5d69b",
|
"revision": "934b8c3014a3e20dd5d90ecf95f4b6b704dddb1e",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
</project>
|
</project>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
<project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<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="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||||
|
|
|
@ -74,3 +74,13 @@ tabpanels {
|
||||||
browser[pending] {
|
browser[pending] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
browser[pendingpaint] {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tabbrowser[pendingpaint] {
|
||||||
|
background-image: url(chrome://global/skin/spinner.png);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center center;
|
||||||
|
}
|
||||||
|
|
|
@ -136,6 +136,10 @@
|
||||||
""
|
""
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
|
<field name="_contentWaitingCount">
|
||||||
|
0
|
||||||
|
</field>
|
||||||
|
|
||||||
<property name="_numPinnedTabs" readonly="true">
|
<property name="_numPinnedTabs" readonly="true">
|
||||||
<getter><![CDATA[
|
<getter><![CDATA[
|
||||||
for (var i = 0; i < this.tabs.length; i++) {
|
for (var i = 0; i < this.tabs.length; i++) {
|
||||||
|
@ -3228,6 +3232,31 @@
|
||||||
</body>
|
</body>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<method name="_showBusySpinnerRemoteBrowser">
|
||||||
|
<parameter name="aBrowser"/>
|
||||||
|
<body><![CDATA[
|
||||||
|
aBrowser.setAttribute("pendingpaint", "true");
|
||||||
|
if (this._contentWaitingCount <= 0) {
|
||||||
|
// We are not currently spinning
|
||||||
|
this.setAttribute("pendingpaint", "true");
|
||||||
|
this._contentWaitingCount = 1;
|
||||||
|
} else {
|
||||||
|
this._contentWaitingCount++;
|
||||||
|
}
|
||||||
|
]]></body>
|
||||||
|
</method>
|
||||||
|
|
||||||
|
<method name="_hideBusySpinnerRemoteBrowser">
|
||||||
|
<parameter name="aBrowser"/>
|
||||||
|
<body><![CDATA[
|
||||||
|
aBrowser.removeAttribute("pendingpaint");
|
||||||
|
this._contentWaitingCount--;
|
||||||
|
if (this._contentWaitingCount <= 0) {
|
||||||
|
this.removeAttribute("pendingpaint");
|
||||||
|
}
|
||||||
|
]]></body>
|
||||||
|
</method>
|
||||||
|
|
||||||
<method name="_prepareForTabSwitch">
|
<method name="_prepareForTabSwitch">
|
||||||
<parameter name="toTab"/>
|
<parameter name="toTab"/>
|
||||||
<parameter name="fromTab"/>
|
<parameter name="fromTab"/>
|
||||||
|
@ -3266,16 +3295,19 @@
|
||||||
|
|
||||||
let timeoutPromise = new Promise((aResolve, aReject) => {
|
let timeoutPromise = new Promise((aResolve, aReject) => {
|
||||||
timeoutId = setTimeout(() => {
|
timeoutId = setTimeout(() => {
|
||||||
|
this._showBusySpinnerRemoteBrowser(toBrowser);
|
||||||
attemptTabSwitch(aResolve, aReject);
|
attemptTabSwitch(aResolve, aReject);
|
||||||
}, kTabSwitchTimeout);
|
}, kTabSwitchTimeout);
|
||||||
});
|
});
|
||||||
|
|
||||||
let paintPromise = new Promise((aResolve, aReject) => {
|
let paintPromise = new Promise((aResolve, aReject) => {
|
||||||
toBrowser.addEventListener("MozAfterRemotePaint", function onRemotePaint() {
|
let onRemotePaint = () => {
|
||||||
toBrowser.removeEventListener("MozAfterRemotePaint", onRemotePaint);
|
toBrowser.removeEventListener("MozAfterRemotePaint", onRemotePaint);
|
||||||
|
this._hideBusySpinnerRemoteBrowser(toBrowser);
|
||||||
clearTimeout(timeoutId);
|
clearTimeout(timeoutId);
|
||||||
attemptTabSwitch(aResolve, aReject);
|
attemptTabSwitch(aResolve, aReject);
|
||||||
});
|
};
|
||||||
|
toBrowser.addEventListener("MozAfterRemotePaint", onRemotePaint);
|
||||||
toBrowser.QueryInterface(Ci.nsIFrameLoaderOwner)
|
toBrowser.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||||
.frameLoader
|
.frameLoader
|
||||||
.requestNotifyAfterRemotePaint();
|
.requestNotifyAfterRemotePaint();
|
||||||
|
|
|
@ -1376,7 +1376,7 @@ PlacesToolbar.prototype = {
|
||||||
elt.localName != "menupopup") {
|
elt.localName != "menupopup") {
|
||||||
let eltRect = elt.getBoundingClientRect();
|
let eltRect = elt.getBoundingClientRect();
|
||||||
let eltIndex = Array.indexOf(this._rootElt.childNodes, elt);
|
let eltIndex = Array.indexOf(this._rootElt.childNodes, elt);
|
||||||
if (PlacesUIUtils.nodeIsFolder(elt._placesNode) &&
|
if (PlacesUtils.nodeIsFolder(elt._placesNode) &&
|
||||||
!PlacesUIUtils.isContentsReadOnly(elt._placesNode)) {
|
!PlacesUIUtils.isContentsReadOnly(elt._placesNode)) {
|
||||||
// This is a folder.
|
// This is a folder.
|
||||||
// If we are in the middle of it, drop inside it.
|
// If we are in the middle of it, drop inside it.
|
||||||
|
|
|
@ -137,6 +137,9 @@ DEFINES += -DMOZ_ICU_DBG_SUFFIX=$(MOZ_ICU_DBG_SUFFIX)
|
||||||
ifdef CLANG_CXX
|
ifdef CLANG_CXX
|
||||||
DEFINES += -DCLANG_CXX
|
DEFINES += -DCLANG_CXX
|
||||||
endif
|
endif
|
||||||
|
ifdef CLANG_CL
|
||||||
|
DEFINES += -DCLANG_CL
|
||||||
|
endif
|
||||||
|
|
||||||
libs::
|
libs::
|
||||||
$(MAKE) -C $(DEPTH)/browser/locales langpack
|
$(MAKE) -C $(DEPTH)/browser/locales langpack
|
||||||
|
|
|
@ -921,4 +921,7 @@ bin/libfreebl_32int64_3.so
|
||||||
#ifdef CLANG_CXX
|
#ifdef CLANG_CXX
|
||||||
@BINPATH@/llvm-symbolizer
|
@BINPATH@/llvm-symbolizer
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CLANG_CL
|
||||||
|
@BINPATH@/clang_rt.asan_dynamic-i386.dll
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -94,6 +94,9 @@ PluginContent.prototype = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Services.telemetry.canSend) {
|
||||||
|
this._finishRecordingFlashPluginTelemetry();
|
||||||
|
}
|
||||||
this.clearPluginDataCache();
|
this.clearPluginDataCache();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -378,6 +381,11 @@ PluginContent.prototype = {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Services.telemetry.canSend && this._getPluginInfo(plugin).mimetype ===
|
||||||
|
"application/x-shockwave-flash") {
|
||||||
|
this._recordFlashPluginTelemetry(eventType, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
// Show the in-content UI if it's not too big. The crashed plugin handler already did this.
|
// Show the in-content UI if it's not too big. The crashed plugin handler already did this.
|
||||||
if (eventType != "PluginCrashed") {
|
if (eventType != "PluginCrashed") {
|
||||||
let overlay = this.getPluginUI(plugin, "main");
|
let overlay = this.getPluginUI(plugin, "main");
|
||||||
|
@ -407,6 +415,42 @@ PluginContent.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_recordFlashPluginTelemetry: function (eventType, plugin) {
|
||||||
|
if (!this.flashPluginStats) {
|
||||||
|
this.flashPluginStats = {
|
||||||
|
instancesCount: 0,
|
||||||
|
plugins: new WeakSet()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.flashPluginStats.plugins.has(plugin)) {
|
||||||
|
// Reporting plugin instance and its dimensions only once.
|
||||||
|
this.flashPluginStats.plugins.add(plugin);
|
||||||
|
|
||||||
|
this.flashPluginStats.instancesCount++;
|
||||||
|
|
||||||
|
let pluginRect = plugin.getBoundingClientRect();
|
||||||
|
Services.telemetry.getHistogramById('FLASH_PLUGIN_WIDTH')
|
||||||
|
.add(pluginRect.width);
|
||||||
|
Services.telemetry.getHistogramById('FLASH_PLUGIN_HEIGHT')
|
||||||
|
.add(pluginRect.height);
|
||||||
|
Services.telemetry.getHistogramById('FLASH_PLUGIN_AREA')
|
||||||
|
.add(pluginRect.width * pluginRect.height);
|
||||||
|
|
||||||
|
let state = this._getPluginInfo(plugin).fallbackType;
|
||||||
|
Services.telemetry.getHistogramById('FLASH_PLUGIN_STATES')
|
||||||
|
.add(state);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_finishRecordingFlashPluginTelemetry: function () {
|
||||||
|
if (this.flashPluginStats) {
|
||||||
|
Services.telemetry.getHistogramById('FLASH_PLUGIN_INSTANCES_ON_PAGE')
|
||||||
|
.add(this.flashPluginStats.instancesCount);
|
||||||
|
delete this.flashPluginStats;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
isKnownPlugin: function (objLoadingContent) {
|
isKnownPlugin: function (objLoadingContent) {
|
||||||
return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
|
return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
|
||||||
Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
||||||
|
|
|
@ -66,6 +66,13 @@ LLDBINIT_FINAL_TARGET_FILES := $(DEPTH)/.lldbinit
|
||||||
LLDBINIT_FINAL_TARGET_DEST = $(FINAL_TARGET)
|
LLDBINIT_FINAL_TARGET_DEST = $(FINAL_TARGET)
|
||||||
INSTALL_TARGETS += LLDBINIT_FINAL_TARGET
|
INSTALL_TARGETS += LLDBINIT_FINAL_TARGET
|
||||||
|
|
||||||
|
ifeq (1_1,$(MOZ_ASAN)_$(CLANG_CL))
|
||||||
|
# Install the clang-cl runtime library for ASAN next to the binaries we produce.
|
||||||
|
CLANG_RT_ASAN_FILES := $(MOZ_CLANG_RT_ASAN_LIB_PATH)
|
||||||
|
CLANG_RT_ASAN_DEST = $(FINAL_TARGET)
|
||||||
|
INSTALL_TARGETS += CLANG_RT_ASAN
|
||||||
|
endif
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
TARGET_DEPTH = ..
|
TARGET_DEPTH = ..
|
||||||
|
|
23
configure.in
23
configure.in
|
@ -506,6 +506,11 @@ case "$target" in
|
||||||
if test -z "$CLANG_CL"; then
|
if test -z "$CLANG_CL"; then
|
||||||
AC_DEFINE(HAVE_SEH_EXCEPTIONS)
|
AC_DEFINE(HAVE_SEH_EXCEPTIONS)
|
||||||
else
|
else
|
||||||
|
# Build on clang-cl with MSVC 2013 with fallback emulation.
|
||||||
|
CFLAGS="$CFLAGS -fmsc-version=1800 -fallback"
|
||||||
|
CXXFLAGS="$CXXFLAGS -fmsc-version=1800 -fallback"
|
||||||
|
# Send our CFLAGS to NSS too
|
||||||
|
MOZ_CFLAGS_NSS=1
|
||||||
AC_DEFINE_UNQUOTED(GTEST_HAS_SEH, 0)
|
AC_DEFINE_UNQUOTED(GTEST_HAS_SEH, 0)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1260,6 +1265,16 @@ MOZ_ARG_ENABLE_BOOL(address-sanitizer,
|
||||||
MOZ_ASAN= )
|
MOZ_ASAN= )
|
||||||
if test -n "$MOZ_ASAN"; then
|
if test -n "$MOZ_ASAN"; then
|
||||||
MOZ_LLVM_HACKS=1
|
MOZ_LLVM_HACKS=1
|
||||||
|
if test -n "$CLANG_CL"; then
|
||||||
|
# Look for clang_rt.asan_dynamic-i386.dll
|
||||||
|
MOZ_CLANG_RT_ASAN_LIB=clang_rt.asan_dynamic-i386.dll
|
||||||
|
# We use MOZ_PATH_PROG in order to get a Windows style path.
|
||||||
|
MOZ_PATH_PROG(MOZ_CLANG_RT_ASAN_LIB_PATH, $MOZ_CLANG_RT_ASAN_LIB)
|
||||||
|
if test -z "$MOZ_CLANG_RT_ASAN_LIB_PATH"; then
|
||||||
|
AC_MSG_ERROR([Couldn't find $MOZ_CLANG_RT_ASAN_LIB. It should be available in the same location as clang-cl.])
|
||||||
|
fi
|
||||||
|
AC_SUBST(MOZ_CLANG_RT_ASAN_LIB_PATH)
|
||||||
|
fi
|
||||||
AC_DEFINE(MOZ_ASAN)
|
AC_DEFINE(MOZ_ASAN)
|
||||||
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
||||||
fi
|
fi
|
||||||
|
@ -3796,11 +3811,6 @@ dnl system libffi Support
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
MOZ_CONFIG_FFI()
|
MOZ_CONFIG_FFI()
|
||||||
|
|
||||||
# split JS out by default to avoid VS2005 PGO crash (bug 591836).
|
|
||||||
if test "$OS_ARCH" = "WINNT"; then
|
|
||||||
JS_SHARED_LIBRARY=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
MOZ_ARG_ENABLE_BOOL(shared-js,
|
MOZ_ARG_ENABLE_BOOL(shared-js,
|
||||||
[ --enable-shared-js
|
[ --enable-shared-js
|
||||||
Create a shared JavaScript library.],
|
Create a shared JavaScript library.],
|
||||||
|
@ -7953,8 +7963,7 @@ dnl =
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
MOZ_ARG_HEADER(Static build options)
|
MOZ_ARG_HEADER(Static build options)
|
||||||
|
|
||||||
if test "$OS_ARCH" = "WINNT"; then
|
if test -n "$GKMEDIAS_SHARED_LIBRARY"; then
|
||||||
GKMEDIAS_SHARED_LIBRARY=1
|
|
||||||
AC_DEFINE(GKMEDIAS_SHARED_LIBRARY)
|
AC_DEFINE(GKMEDIAS_SHARED_LIBRARY)
|
||||||
fi
|
fi
|
||||||
AC_SUBST(GKMEDIAS_SHARED_LIBRARY)
|
AC_SUBST(GKMEDIAS_SHARED_LIBRARY)
|
||||||
|
|
|
@ -412,7 +412,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Web components custom element data.
|
* Web components custom element data.
|
||||||
*/
|
*/
|
||||||
nsAutoPtr<CustomElementData> mCustomElementData;
|
nsRefPtr<CustomElementData> mCustomElementData;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -238,18 +238,15 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
|
||||||
|
|
||||||
// Create a fake channel
|
// Create a fake channel
|
||||||
nsCOMPtr<nsIChannel> parserChannel;
|
nsCOMPtr<nsIChannel> parserChannel;
|
||||||
NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mDocumentURI, nullptr,
|
NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
|
||||||
nsDependentCString(contentType), nullptr);
|
mDocumentURI,
|
||||||
|
nullptr, // aStream
|
||||||
|
mOriginalPrincipal,
|
||||||
|
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
nsDependentCString(contentType));
|
||||||
NS_ENSURE_STATE(parserChannel);
|
NS_ENSURE_STATE(parserChannel);
|
||||||
|
|
||||||
// More principal-faking here
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
|
||||||
new LoadInfo(mOriginalPrincipal,
|
|
||||||
nullptr,
|
|
||||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
|
||||||
nsIContentPolicy::TYPE_OTHER);
|
|
||||||
parserChannel->SetLoadInfo(loadInfo);
|
|
||||||
|
|
||||||
if (charset) {
|
if (charset) {
|
||||||
parserChannel->SetContentCharset(nsDependentCString(charset));
|
parserChannel->SetContentCharset(nsDependentCString(charset));
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,6 +193,8 @@ public:
|
||||||
WorkerPrivate* mWorkerPrivate;
|
WorkerPrivate* mWorkerPrivate;
|
||||||
nsAutoPtr<WorkerFeature> mWorkerFeature;
|
nsAutoPtr<WorkerFeature> mWorkerFeature;
|
||||||
|
|
||||||
|
nsWeakPtr mWeakLoadGroup;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~WebSocketImpl()
|
~WebSocketImpl()
|
||||||
{
|
{
|
||||||
|
@ -528,8 +530,7 @@ WebSocketImpl::DisconnectInternal()
|
||||||
{
|
{
|
||||||
AssertIsOnMainThread();
|
AssertIsOnMainThread();
|
||||||
|
|
||||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
|
||||||
GetLoadGroup(getter_AddRefs(loadGroup));
|
|
||||||
if (loadGroup) {
|
if (loadGroup) {
|
||||||
loadGroup->RemoveRequest(this, nullptr, NS_OK);
|
loadGroup->RemoveRequest(this, nullptr, NS_OK);
|
||||||
}
|
}
|
||||||
|
@ -1390,6 +1391,8 @@ WebSocketImpl::InitializeConnection()
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
rv = loadGroup->AddRequest(this, nullptr);
|
rv = loadGroup->AddRequest(this, nullptr);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
mWeakLoadGroup = do_GetWeakReference(loadGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// manually adding loadinfo to the channel since it
|
// manually adding loadinfo to the channel since it
|
||||||
|
|
|
@ -5844,12 +5844,7 @@ nsDocument::ProcessTopElementQueue(bool aIsBaseQueue)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
||||||
|
|
||||||
if (sProcessingStack.isNothing()) {
|
nsTArray<nsRefPtr<CustomElementData>>& stack = *sProcessingStack;
|
||||||
// If XPCOM shutdown has reset the processing stack, don't do anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsTArray<CustomElementData*>& stack = *sProcessingStack;
|
|
||||||
uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
|
uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
|
||||||
|
|
||||||
if (aIsBaseQueue && firstQueue != 0) {
|
if (aIsBaseQueue && firstQueue != 0) {
|
||||||
|
@ -5886,7 +5881,7 @@ nsDocument::RegisterEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Maybe<nsTArray<mozilla::dom::CustomElementData*>>
|
Maybe<nsTArray<nsRefPtr<mozilla::dom::CustomElementData>>>
|
||||||
nsDocument::sProcessingStack;
|
nsDocument::sProcessingStack;
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
|
@ -325,6 +325,8 @@ private:
|
||||||
// being created flag.
|
// being created flag.
|
||||||
struct CustomElementData
|
struct CustomElementData
|
||||||
{
|
{
|
||||||
|
NS_INLINE_DECL_REFCOUNTING(CustomElementData)
|
||||||
|
|
||||||
explicit CustomElementData(nsIAtom* aType);
|
explicit CustomElementData(nsIAtom* aType);
|
||||||
// Objects in this array are transient and empty after each microtask
|
// Objects in this array are transient and empty after each microtask
|
||||||
// checkpoint.
|
// checkpoint.
|
||||||
|
@ -346,6 +348,9 @@ struct CustomElementData
|
||||||
|
|
||||||
// Empties the callback queue.
|
// Empties the callback queue.
|
||||||
void RunCallbackQueue();
|
void RunCallbackQueue();
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual ~CustomElementData() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// The required information for a custom element as defined in:
|
// The required information for a custom element as defined in:
|
||||||
|
@ -1520,7 +1525,7 @@ private:
|
||||||
// CustomElementData in this array, separated by nullptr that
|
// CustomElementData in this array, separated by nullptr that
|
||||||
// represent the boundaries of the items in the stack. The first
|
// represent the boundaries of the items in the stack. The first
|
||||||
// queue in the stack is the base element queue.
|
// queue in the stack is the base element queue.
|
||||||
static mozilla::Maybe<nsTArray<mozilla::dom::CustomElementData*>> sProcessingStack;
|
static mozilla::Maybe<nsTArray<nsRefPtr<mozilla::dom::CustomElementData>>> sProcessingStack;
|
||||||
|
|
||||||
// Flag to prevent re-entrance into base element queue as described in the
|
// Flag to prevent re-entrance into base element queue as described in the
|
||||||
// custom elements speicification.
|
// custom elements speicification.
|
||||||
|
|
|
@ -519,7 +519,11 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||||
uri,
|
uri,
|
||||||
stream);
|
stream,
|
||||||
|
info->mPrincipal,
|
||||||
|
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER);
|
||||||
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsString type;
|
nsString type;
|
||||||
|
@ -537,12 +541,6 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
||||||
return error.ErrorCode();
|
return error.ErrorCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
|
||||||
new mozilla::LoadInfo(info->mPrincipal,
|
|
||||||
nullptr,
|
|
||||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
|
||||||
nsIContentPolicy::TYPE_OTHER);
|
|
||||||
channel->SetLoadInfo(loadInfo);
|
|
||||||
channel->SetOriginalURI(uri);
|
channel->SetOriginalURI(uri);
|
||||||
channel->SetContentType(NS_ConvertUTF16toUTF8(type));
|
channel->SetContentType(NS_ConvertUTF16toUTF8(type));
|
||||||
channel->SetContentLength(size);
|
channel->SetContentLength(size);
|
||||||
|
|
|
@ -12,6 +12,9 @@ var is_remote;
|
||||||
error_reporting_test();
|
error_reporting_test();
|
||||||
dom_test();
|
dom_test();
|
||||||
xray_test();
|
xray_test();
|
||||||
|
if (typeof Symbol === "function") {
|
||||||
|
symbol_test();
|
||||||
|
}
|
||||||
compartment_test();
|
compartment_test();
|
||||||
regexp_test();
|
regexp_test();
|
||||||
sync_test();
|
sync_test();
|
||||||
|
@ -119,15 +122,13 @@ function symbol_test()
|
||||||
{
|
{
|
||||||
let iterator = Symbol.iterator;
|
let iterator = Symbol.iterator;
|
||||||
let named = Symbol.for("cpow-test");
|
let named = Symbol.for("cpow-test");
|
||||||
// let unique = Symbol();
|
|
||||||
|
|
||||||
let object = {
|
let object = {
|
||||||
[iterator]: iterator,
|
[iterator]: iterator,
|
||||||
[named]: named,
|
[named]: named,
|
||||||
// [unique]: unique,
|
|
||||||
// "unique": unique
|
|
||||||
};
|
};
|
||||||
sendSyncMessage("cpows:symbol_test", {}, object);
|
let test = ['a'];
|
||||||
|
sendSyncMessage("cpows:symbol_test", {}, {object: object, test: test});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parent->Child references should go X->parent.privilegedJunkScope->child.privilegedJunkScope->Y
|
// Parent->Child references should go X->parent.privilegedJunkScope->child.privilegedJunkScope->Y
|
||||||
|
|
|
@ -206,10 +206,16 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function recvSymbolTest(message) {
|
function recvSymbolTest(message) {
|
||||||
let object = message.objects;
|
let object = message.objects.object;
|
||||||
is(object[Symbol.iterator], Symbol.iterator, "Should use Symbol.iterator");
|
is(object[Symbol.iterator], Symbol.iterator, "Should use Symbol.iterator");
|
||||||
is(Symbol.keyFor(object[Symbol.for("cpow-test")]), "cpow-test", "Symbols aren't registered correctly");
|
is(Symbol.keyFor(object[Symbol.for("cpow-test")]), "cpow-test", "Symbols aren't registered correctly");
|
||||||
// is(object.unique, object[object.unique], "Unique symbols as ids and values don't seem to work");
|
let symbols = Object.getOwnPropertySymbols(object);
|
||||||
|
is(symbols.length, 2, "Object should have two symbol keys");
|
||||||
|
let test = undefined;
|
||||||
|
for (let x of message.objects.test) {
|
||||||
|
test = x;
|
||||||
|
}
|
||||||
|
is(test, "a", "for .. of iteration should work");
|
||||||
}
|
}
|
||||||
|
|
||||||
let systemGlobal = this;
|
let systemGlobal = this;
|
||||||
|
@ -307,7 +313,9 @@
|
||||||
mm.addMessageListener("cpows:dom_test", recvDomTest);
|
mm.addMessageListener("cpows:dom_test", recvDomTest);
|
||||||
mm.addMessageListener("cpows:dom_test_after_gc", recvDomTestAfterGC);
|
mm.addMessageListener("cpows:dom_test_after_gc", recvDomTestAfterGC);
|
||||||
mm.addMessageListener("cpows:xray_test", recvXrayTest);
|
mm.addMessageListener("cpows:xray_test", recvXrayTest);
|
||||||
mm.addMessageListener("cpows:symbol_test", recvSymbolTest);
|
if (typeof Symbol === "function") {
|
||||||
|
mm.addMessageListener("cpows:symbol_test", recvSymbolTest);
|
||||||
|
}
|
||||||
mm.addMessageListener("cpows:compartment_test", recvCompartmentTest);
|
mm.addMessageListener("cpows:compartment_test", recvCompartmentTest);
|
||||||
mm.addMessageListener("cpows:regexp_test", recvRegExpTest);
|
mm.addMessageListener("cpows:regexp_test", recvRegExpTest);
|
||||||
mm.addMessageListener("cpows:lifetime_test_1", recvLifetimeTest1);
|
mm.addMessageListener("cpows:lifetime_test_1", recvLifetimeTest1);
|
||||||
|
|
|
@ -1655,12 +1655,25 @@ nsDocShell::LoadStream(nsIInputStream *aStream, nsIURI * aURI,
|
||||||
|
|
||||||
mLoadType = loadType;
|
mLoadType = loadType;
|
||||||
|
|
||||||
|
nsCOMPtr<nsISupports> owner;
|
||||||
|
aLoadInfo->GetOwner(getter_AddRefs(owner));
|
||||||
|
nsCOMPtr<nsIPrincipal> requestingPrincipal = do_QueryInterface(owner);
|
||||||
|
if (!requestingPrincipal) {
|
||||||
|
requestingPrincipal = nsContentUtils::GetSystemPrincipal();
|
||||||
|
}
|
||||||
|
|
||||||
// build up a channel for this stream.
|
// build up a channel for this stream.
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
NS_ENSURE_SUCCESS(NS_NewInputStreamChannel
|
nsresult rv =
|
||||||
(getter_AddRefs(channel), uri, aStream,
|
NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||||
aContentType, aContentCharset),
|
uri,
|
||||||
NS_ERROR_FAILURE);
|
aStream,
|
||||||
|
requestingPrincipal,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
aContentType,
|
||||||
|
aContentCharset);
|
||||||
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsCOMPtr<nsIURILoader>
|
nsCOMPtr<nsIURILoader>
|
||||||
uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID));
|
uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID));
|
||||||
|
@ -10266,25 +10279,28 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
||||||
rv = vsh->NewSrcdocChannel(aURI, aSrcdoc, aBaseURI,
|
rv = vsh->NewSrcdocChannel(aURI, aSrcdoc, aBaseURI,
|
||||||
getter_AddRefs(channel));
|
getter_AddRefs(channel));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||||
|
new LoadInfo(requestingPrincipal,
|
||||||
|
requestingNode,
|
||||||
|
securityFlags,
|
||||||
|
aContentPolicyType);
|
||||||
|
channel->SetLoadInfo(loadInfo);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),aURI,
|
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
|
||||||
aSrcdoc,
|
aURI,
|
||||||
NS_LITERAL_CSTRING("text/html"),
|
aSrcdoc,
|
||||||
true);
|
NS_LITERAL_CSTRING("text/html"),
|
||||||
|
requestingNode,
|
||||||
|
requestingPrincipal,
|
||||||
|
securityFlags,
|
||||||
|
aContentPolicyType,
|
||||||
|
true);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
|
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
|
||||||
MOZ_ASSERT(isc);
|
MOZ_ASSERT(isc);
|
||||||
isc->SetBaseURI(aBaseURI);
|
isc->SetBaseURI(aBaseURI);
|
||||||
}
|
}
|
||||||
// NS_NewInputStreamChannel does not yet attach the loadInfo in nsNetutil.h,
|
|
||||||
// hence we have to manually attach the loadInfo for that channel.
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
|
||||||
new LoadInfo(requestingPrincipal,
|
|
||||||
requestingNode,
|
|
||||||
securityFlags,
|
|
||||||
aContentPolicyType);
|
|
||||||
channel->SetLoadInfo(loadInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
|
nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
|
||||||
|
|
|
@ -599,20 +599,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const char *className(JSContext *cx,
|
// Standard internal methods
|
||||||
JS::Handle<JSObject*> wrapper) const MOZ_OVERRIDE;
|
|
||||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
// Fundamental traps
|
|
||||||
virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
|
|
||||||
const MOZ_OVERRIDE;
|
|
||||||
virtual bool preventExtensions(JSContext *cx,
|
|
||||||
JS::Handle<JSObject*> proxy) const MOZ_OVERRIDE;
|
|
||||||
virtual bool getPropertyDescriptor(JSContext* cx,
|
|
||||||
JS::Handle<JSObject*> proxy,
|
|
||||||
JS::Handle<jsid> id,
|
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc)
|
|
||||||
const MOZ_OVERRIDE;
|
|
||||||
virtual bool getOwnPropertyDescriptor(JSContext* cx,
|
virtual bool getOwnPropertyDescriptor(JSContext* cx,
|
||||||
JS::Handle<JSObject*> proxy,
|
JS::Handle<JSObject*> proxy,
|
||||||
JS::Handle<jsid> id,
|
JS::Handle<jsid> id,
|
||||||
|
@ -631,23 +618,12 @@ public:
|
||||||
bool *bp) const MOZ_OVERRIDE;
|
bool *bp) const MOZ_OVERRIDE;
|
||||||
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||||
|
virtual bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
|
||||||
virtual bool watch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
const MOZ_OVERRIDE;
|
||||||
JS::Handle<jsid> id, JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
|
virtual bool preventExtensions(JSContext *cx,
|
||||||
virtual bool unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
JS::Handle<JSObject*> proxy) const MOZ_OVERRIDE;
|
||||||
JS::Handle<jsid> id) const MOZ_OVERRIDE;
|
|
||||||
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Derived traps
|
|
||||||
virtual bool has(JSContext *cx, JS::Handle<JSObject*> proxy,
|
virtual bool has(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
|
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
|
||||||
virtual bool hasOwn(JSContext *cx, JS::Handle<JSObject*> proxy,
|
|
||||||
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
|
|
||||||
virtual bool get(JSContext *cx, JS::Handle<JSObject*> proxy,
|
virtual bool get(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::Handle<JSObject*> receiver,
|
JS::Handle<JSObject*> receiver,
|
||||||
JS::Handle<jsid> id,
|
JS::Handle<jsid> id,
|
||||||
|
@ -657,11 +633,36 @@ public:
|
||||||
JS::Handle<jsid> id,
|
JS::Handle<jsid> id,
|
||||||
bool strict,
|
bool strict,
|
||||||
JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
|
JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
|
||||||
virtual bool keys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
|
||||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
// SpiderMonkey extensions
|
||||||
|
virtual bool getPropertyDescriptor(JSContext* cx,
|
||||||
|
JS::Handle<JSObject*> proxy,
|
||||||
|
JS::Handle<jsid> id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc)
|
||||||
|
const MOZ_OVERRIDE;
|
||||||
|
virtual bool hasOwn(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::Handle<jsid> id, bool *bp) const MOZ_OVERRIDE;
|
||||||
|
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||||
virtual bool iterate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
virtual bool iterate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
unsigned flags,
|
unsigned flags,
|
||||||
JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
|
JS::MutableHandle<JS::Value> vp) const MOZ_OVERRIDE;
|
||||||
|
virtual const char *className(JSContext *cx,
|
||||||
|
JS::Handle<JSObject*> wrapper) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual void finalize(JSFreeOp *fop, JSObject *proxy) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool watch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::Handle<jsid> id, JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
|
||||||
|
virtual bool unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::Handle<jsid> id) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
static void ObjectMoved(JSObject *obj, const JSObject *old);
|
static void ObjectMoved(JSObject *obj, const JSObject *old);
|
||||||
|
|
||||||
|
@ -930,12 +931,12 @@ nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsOuterWindowProxy::keys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
nsOuterWindowProxy::getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::AutoIdVector &props) const
|
JS::AutoIdVector &props) const
|
||||||
{
|
{
|
||||||
// BaseProxyHandler::keys seems to do what we want here: call
|
// BaseProxyHandler::keys seems to do what we want here: call
|
||||||
// ownPropertyKeys and then filter out the non-enumerable properties.
|
// ownPropertyKeys and then filter out the non-enumerable properties.
|
||||||
return js::BaseProxyHandler::keys(cx, proxy, props);
|
return js::BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -82,6 +82,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||||
[test_urlutils_stringify.html]
|
[test_urlutils_stringify.html]
|
||||||
[test_window_constructor.html]
|
[test_window_constructor.html]
|
||||||
[test_window_cross_origin_props.html]
|
[test_window_cross_origin_props.html]
|
||||||
|
[test_window_define_symbol.html]
|
||||||
[test_window_enumeration.html]
|
[test_window_enumeration.html]
|
||||||
[test_window_extensible.html]
|
[test_window_extensible.html]
|
||||||
[test_window_indexing.html]
|
[test_window_indexing.html]
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=1082672
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Test for Bug 1082672 part 2</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=1082672">Mozilla Bug 1082672</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
var sym = Symbol("ponies");
|
||||||
|
Object.defineProperty(window, sym, {configurable: true, value: 3});
|
||||||
|
is(window[sym], 3);
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1406,8 +1406,11 @@ XrayAttributeOrMethodKeys(JSContext* cx, JS::Handle<JSObject*> wrapper,
|
||||||
// looking at now.
|
// looking at now.
|
||||||
size_t i = list->specs - specList;
|
size_t i = list->specs - specList;
|
||||||
for ( ; ids[i] != JSID_VOID; ++i) {
|
for ( ; ids[i] != JSID_VOID; ++i) {
|
||||||
|
// Skip non-enumerable properties and symbol-keyed properties unless
|
||||||
|
// they are specially requested via flags.
|
||||||
if (((flags & JSITER_HIDDEN) ||
|
if (((flags & JSITER_HIDDEN) ||
|
||||||
(specList[i].flags & JSPROP_ENUMERATE)) &&
|
(specList[i].flags & JSPROP_ENUMERATE)) &&
|
||||||
|
((flags & JSITER_SYMBOLS) || !JSID_IS_SYMBOL(ids[i])) &&
|
||||||
!props.append(ids[i])) {
|
!props.append(ids[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1685,7 +1685,7 @@ InitIds(JSContext* cx, const Prefable<Spec>* prefableSpecs, jsid* ids)
|
||||||
// because this is only done once per application runtime.
|
// because this is only done once per application runtime.
|
||||||
Spec* spec = prefableSpecs->specs;
|
Spec* spec = prefableSpecs->specs;
|
||||||
do {
|
do {
|
||||||
if (!InternJSString(cx, *ids, spec->name)) {
|
if (!JS::PropertySpecNameToPermanentId(cx, spec->name, ids)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} while (++ids, (++spec)->name);
|
} while (++ids, (++spec)->name);
|
||||||
|
|
|
@ -277,7 +277,7 @@ BaseDOMProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
if (!JS_GetPrototype(cx, proxy, &proto)) {
|
if (!JS_GetPrototype(cx, proxy, &proto)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return keys(cx, proxy, props) &&
|
return getOwnEnumerablePropertyKeys(cx, proxy, props) &&
|
||||||
(!proto || js::GetPropertyKeys(cx, proto, 0, &props));
|
(!proto || js::GetPropertyKeys(cx, proto, 0, &props));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,13 +299,13 @@ BaseDOMProxyHandler::ownPropertyKeys(JSContext* cx,
|
||||||
JS::Handle<JSObject*> proxy,
|
JS::Handle<JSObject*> proxy,
|
||||||
JS::AutoIdVector& props) const
|
JS::AutoIdVector& props) const
|
||||||
{
|
{
|
||||||
return ownPropNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props);
|
return ownPropNames(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BaseDOMProxyHandler::keys(JSContext* cx,
|
BaseDOMProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
|
||||||
JS::Handle<JSObject*> proxy,
|
JS::Handle<JSObject*> proxy,
|
||||||
JS::AutoIdVector& props) const
|
JS::AutoIdVector& props) const
|
||||||
{
|
{
|
||||||
return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
|
return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
|
||||||
}
|
}
|
||||||
|
@ -345,7 +345,8 @@ IdToInt32(JSContext* cx, JS::Handle<jsid> id)
|
||||||
JS::Rooted<JS::Value> idval(cx);
|
JS::Rooted<JS::Value> idval(cx);
|
||||||
double array_index;
|
double array_index;
|
||||||
int32_t i;
|
int32_t i;
|
||||||
if (!::JS_IdToValue(cx, id, &idval) ||
|
if (JSID_IS_SYMBOL(id) ||
|
||||||
|
!::JS_IdToValue(cx, id, &idval) ||
|
||||||
!JS::ToNumber(cx, idval, &array_index) ||
|
!JS::ToNumber(cx, idval, &array_index) ||
|
||||||
!::JS_DoubleIsInt32(array_index, &i)) {
|
!::JS_DoubleIsInt32(array_index, &i)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -50,34 +50,38 @@ public:
|
||||||
: js::BaseProxyHandler(aProxyFamily, aHasPrototype)
|
: js::BaseProxyHandler(aProxyFamily, aHasPrototype)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Implementations of traps that can be implemented in terms of
|
// Implementations of methods that can be implemented in terms of
|
||||||
// fundamental traps.
|
// other lower-level methods.
|
||||||
bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|
||||||
JS::AutoIdVector& props) const MOZ_OVERRIDE;
|
|
||||||
bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|
||||||
JS::Handle<jsid> id,
|
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
|
||||||
bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
|
bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::Handle<jsid> id,
|
JS::Handle<jsid> id,
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||||
|
virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||||
|
bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::AutoIdVector& props) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
bool getPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::Handle<jsid> id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
|
||||||
|
// We override getOwnEnumerablePropertyKeys() and implement it directly
|
||||||
|
// instead of using the default implementation, which would call
|
||||||
|
// ownPropertyKeys and then filter out the non-enumerable ones. This avoids
|
||||||
|
// unnecessary work during enumeration.
|
||||||
|
virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||||
JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
|
JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
|
||||||
bool unwatch(JSContext* cx, JS::Handle<JSObject*> proxy,
|
bool unwatch(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
JS::Handle<jsid> id) const MOZ_OVERRIDE;
|
JS::Handle<jsid> id) const MOZ_OVERRIDE;
|
||||||
virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|
||||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
|
||||||
// We override keys() and implement it directly instead of using the
|
|
||||||
// default implementation, which would getOwnPropertyNames and then
|
|
||||||
// filter out the non-enumerable ones. This avoids doing
|
|
||||||
// unnecessary work during enumeration.
|
|
||||||
virtual bool keys(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|
||||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Hook for subclasses to implement shared ownPropertyKeys()/keys()
|
// Hook for subclasses to implement shared ownPropertyKeys()/keys()
|
||||||
// functionality. The "flags" argument is either JSITER_OWNONLY (for keys())
|
// functionality. The "flags" argument is either JSITER_OWNONLY (for keys())
|
||||||
// or JSITER_OWNONLY | JSITER_HIDDEN (for ownPropertyKeys()).
|
// or JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS (for
|
||||||
|
// ownPropertyKeys()).
|
||||||
virtual bool ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy,
|
virtual bool ownPropNames(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
unsigned flags,
|
unsigned flags,
|
||||||
JS::AutoIdVector& props) const = 0;
|
JS::AutoIdVector& props) const = 0;
|
||||||
|
@ -100,7 +104,6 @@ public:
|
||||||
: BaseDOMProxyHandler(&family)
|
: BaseDOMProxyHandler(&family)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy) const MOZ_OVERRIDE;
|
|
||||||
bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE
|
JS::MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
|
@ -110,15 +113,16 @@ public:
|
||||||
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
virtual bool defineProperty(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
|
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
|
||||||
const;
|
const;
|
||||||
|
bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||||
|
JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE;
|
||||||
|
bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
|
||||||
|
const MOZ_OVERRIDE;
|
||||||
|
bool preventExtensions(JSContext *cx, JS::Handle<JSObject*> proxy) const MOZ_OVERRIDE;
|
||||||
|
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||||
|
bool* bp) const MOZ_OVERRIDE;
|
||||||
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
|
bool set(JSContext *cx, JS::Handle<JSObject*> proxy, JS::Handle<JSObject*> receiver,
|
||||||
JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp)
|
JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp)
|
||||||
const MOZ_OVERRIDE;
|
const MOZ_OVERRIDE;
|
||||||
bool delete_(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|
||||||
JS::Handle<jsid> id, bool* bp) const MOZ_OVERRIDE;
|
|
||||||
bool has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
|
||||||
bool* bp) const MOZ_OVERRIDE;
|
|
||||||
bool isExtensible(JSContext *cx, JS::Handle<JSObject*> proxy, bool *extensible)
|
|
||||||
const MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If assigning to proxy[id] hits a named setter with OverrideBuiltins or
|
* If assigning to proxy[id] hits a named setter with OverrideBuiltins or
|
||||||
|
|
|
@ -39,4 +39,9 @@
|
||||||
/* CHLD values */
|
/* CHLD values */
|
||||||
#define BTA_AG_CHLD_VAL "(0,1,2,3)"
|
#define BTA_AG_CHLD_VAL "(0,1,2,3)"
|
||||||
|
|
||||||
|
/* BLE Feature */
|
||||||
|
#define BTA_GATT_INCLUDED TRUE
|
||||||
|
#define BLE_INCLUDED TRUE
|
||||||
|
#define SMP_INCLUDED TRUE
|
||||||
|
|
||||||
#endif /* B2G_BDROID_BUILDCFG_H */
|
#endif /* B2G_BDROID_BUILDCFG_H */
|
||||||
|
|
|
@ -66,7 +66,11 @@ public:
|
||||||
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
||||||
GLsizei depth);
|
GLsizei depth);
|
||||||
|
void TexImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLsizei depth,
|
||||||
|
GLint border, GLenum format, GLenum type,
|
||||||
|
const Nullable<dom::ArrayBufferView> &pixels,
|
||||||
|
ErrorResult& rv);
|
||||||
void TexSubImage3D(GLenum target, GLint level,
|
void TexSubImage3D(GLenum target, GLint level,
|
||||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||||
GLsizei width, GLsizei height, GLsizei depth,
|
GLsizei width, GLsizei height, GLsizei depth,
|
||||||
|
|
|
@ -204,6 +204,119 @@ WebGL2Context::TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
WebGL2Context::TexImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLsizei depth,
|
||||||
|
GLint border, GLenum format, GLenum type,
|
||||||
|
const Nullable<dom::ArrayBufferView> &pixels,
|
||||||
|
ErrorResult& rv)
|
||||||
|
{
|
||||||
|
if (IsContextLost())
|
||||||
|
return;
|
||||||
|
|
||||||
|
void* data;
|
||||||
|
size_t dataLength;
|
||||||
|
js::Scalar::Type jsArrayType;
|
||||||
|
if (pixels.IsNull()) {
|
||||||
|
data = nullptr;
|
||||||
|
dataLength = 0;
|
||||||
|
jsArrayType = js::Scalar::TypeMax;
|
||||||
|
} else {
|
||||||
|
const ArrayBufferView& view = pixels.Value();
|
||||||
|
view.ComputeLengthAndData();
|
||||||
|
|
||||||
|
data = view.Data();
|
||||||
|
dataLength = view.Length();
|
||||||
|
jsArrayType = JS_GetArrayBufferViewType(view.Obj());
|
||||||
|
}
|
||||||
|
|
||||||
|
const WebGLTexImageFunc func = WebGLTexImageFunc::TexImage;
|
||||||
|
const WebGLTexDimensions dims = WebGLTexDimensions::Tex3D;
|
||||||
|
|
||||||
|
if (!ValidateTexImageTarget(target, func, dims))
|
||||||
|
return;
|
||||||
|
|
||||||
|
TexImageTarget texImageTarget = target;
|
||||||
|
|
||||||
|
if (!ValidateTexImage(texImageTarget, level, internalformat,
|
||||||
|
0, 0, 0,
|
||||||
|
width, height, depth,
|
||||||
|
border, format, type, func, dims))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ValidateTexInputData(type, jsArrayType, func, dims))
|
||||||
|
return;
|
||||||
|
|
||||||
|
TexInternalFormat effectiveInternalFormat =
|
||||||
|
EffectiveInternalFormatFromInternalFormatAndType(internalformat, type);
|
||||||
|
|
||||||
|
if (effectiveInternalFormat == LOCAL_GL_NONE) {
|
||||||
|
return ErrorInvalidOperation("texImage3D: bad combination of internalformat and type");
|
||||||
|
}
|
||||||
|
|
||||||
|
// we need to find the exact sized format of the source data. Slightly abusing
|
||||||
|
// EffectiveInternalFormatFromInternalFormatAndType for that purpose. Really, an unsized source format
|
||||||
|
// is the same thing as an unsized internalformat.
|
||||||
|
TexInternalFormat effectiveSourceFormat =
|
||||||
|
EffectiveInternalFormatFromInternalFormatAndType(format, type);
|
||||||
|
MOZ_ASSERT(effectiveSourceFormat != LOCAL_GL_NONE); // should have validated format/type combo earlier
|
||||||
|
const size_t srcbitsPerTexel = GetBitsPerTexel(effectiveSourceFormat);
|
||||||
|
MOZ_ASSERT((srcbitsPerTexel % 8) == 0); // should not have compressed formats here.
|
||||||
|
size_t srcTexelSize = srcbitsPerTexel / 8;
|
||||||
|
|
||||||
|
CheckedUint32 checked_neededByteLength =
|
||||||
|
GetImageSize(height, width, depth, srcTexelSize, mPixelStoreUnpackAlignment);
|
||||||
|
|
||||||
|
if (!checked_neededByteLength.isValid())
|
||||||
|
return ErrorInvalidOperation("texSubImage2D: integer overflow computing the needed buffer size");
|
||||||
|
|
||||||
|
uint32_t bytesNeeded = checked_neededByteLength.value();
|
||||||
|
|
||||||
|
if (dataLength && dataLength < bytesNeeded)
|
||||||
|
return ErrorInvalidOperation("texImage3D: not enough data for operation (need %d, have %d)",
|
||||||
|
bytesNeeded, dataLength);
|
||||||
|
|
||||||
|
WebGLTexture* tex = activeBoundTextureForTexImageTarget(texImageTarget);
|
||||||
|
|
||||||
|
if (!tex)
|
||||||
|
return ErrorInvalidOperation("texImage3D: no texture is bound to this target");
|
||||||
|
|
||||||
|
if (tex->IsImmutable()) {
|
||||||
|
return ErrorInvalidOperation(
|
||||||
|
"texImage3D: disallowed because the texture "
|
||||||
|
"bound to this target has already been made immutable by texStorage3D");
|
||||||
|
}
|
||||||
|
|
||||||
|
GLenum driverType = LOCAL_GL_NONE;
|
||||||
|
GLenum driverInternalFormat = LOCAL_GL_NONE;
|
||||||
|
GLenum driverFormat = LOCAL_GL_NONE;
|
||||||
|
DriverFormatsFromEffectiveInternalFormat(gl,
|
||||||
|
effectiveInternalFormat,
|
||||||
|
&driverInternalFormat,
|
||||||
|
&driverFormat,
|
||||||
|
&driverType);
|
||||||
|
|
||||||
|
MakeContextCurrent();
|
||||||
|
GetAndFlushUnderlyingGLErrors();
|
||||||
|
gl->fTexImage3D(texImageTarget.get(), level,
|
||||||
|
driverInternalFormat,
|
||||||
|
width, height, depth,
|
||||||
|
0, driverFormat, driverType,
|
||||||
|
data);
|
||||||
|
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||||
|
if (error) {
|
||||||
|
return GenerateWarning("texImage3D generated error %s", ErrorName(error));
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->SetImageInfo(texImageTarget, level,
|
||||||
|
width, height, depth,
|
||||||
|
effectiveInternalFormat,
|
||||||
|
data ? WebGLImageDataStatus::InitializedImageData
|
||||||
|
: WebGLImageDataStatus::UninitializedImageData);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
|
WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
|
||||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||||
|
|
|
@ -922,7 +922,11 @@ WebGLContext::GenerateMipmap(GLenum rawTarget)
|
||||||
const TexImageTarget imageTarget = (target == LOCAL_GL_TEXTURE_2D)
|
const TexImageTarget imageTarget = (target == LOCAL_GL_TEXTURE_2D)
|
||||||
? LOCAL_GL_TEXTURE_2D
|
? LOCAL_GL_TEXTURE_2D
|
||||||
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
: LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X;
|
||||||
if (!tex->HasImageInfoAt(imageTarget, tex->GetBaseMipmapLevel()))
|
if (!tex->IsMipmapRangeValid())
|
||||||
|
{
|
||||||
|
return ErrorInvalidOperation("generateMipmap: Texture does not have a valid mipmap range.");
|
||||||
|
}
|
||||||
|
if (!tex->HasImageInfoAt(imageTarget, tex->EffectiveBaseMipmapLevel()))
|
||||||
{
|
{
|
||||||
return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
|
return ErrorInvalidOperation("generateMipmap: Level zero of texture is not defined.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -867,6 +867,7 @@ InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims)
|
||||||
}
|
}
|
||||||
case WebGLTexDimensions::Tex3D:
|
case WebGLTexDimensions::Tex3D:
|
||||||
switch (func) {
|
switch (func) {
|
||||||
|
case WebGLTexImageFunc::TexImage: return "texImage3D";
|
||||||
case WebGLTexImageFunc::TexSubImage: return "texSubImage3D";
|
case WebGLTexImageFunc::TexSubImage: return "texSubImage3D";
|
||||||
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage3D";
|
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage3D";
|
||||||
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage3D";
|
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage3D";
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "WebGLTexelConversions.h"
|
#include "WebGLTexelConversions.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include "mozilla/MathAlgorithms.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
|
@ -64,36 +65,50 @@ WebGLTexture::MemoryUsage() const {
|
||||||
return 0;
|
return 0;
|
||||||
size_t result = 0;
|
size_t result = 0;
|
||||||
for(size_t face = 0; face < mFacesCount; face++) {
|
for(size_t face = 0; face < mFacesCount; face++) {
|
||||||
for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++)
|
for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++)
|
||||||
result += ImageInfoAtFace(face, level).MemoryUsage();
|
result += ImageInfoAtFace(face, level).MemoryUsage();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline size_t
|
||||||
|
MipmapLevelsForSize(const WebGLTexture::ImageInfo &info)
|
||||||
|
{
|
||||||
|
GLsizei size = std::max(std::max(info.Width(), info.Height()), info.Depth());
|
||||||
|
|
||||||
|
// Find floor(log2(size)). (ES 3.0.4, 3.8 - Mipmapping).
|
||||||
|
return mozilla::FloorLog2(size);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const
|
WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const
|
||||||
{
|
{
|
||||||
|
// We could not have generated a mipmap if the base image wasn't defined.
|
||||||
if (mHaveGeneratedMipmap)
|
if (mHaveGeneratedMipmap)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (GetMaxMipmapLevel() < GetBaseMipmapLevel())
|
if (!IsMipmapRangeValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We want a copy here so we can modify it temporarily.
|
// We want a copy here so we can modify it temporarily.
|
||||||
ImageInfo expected = ImageInfoAt(texImageTarget, GetBaseMipmapLevel());
|
ImageInfo expected = ImageInfoAt(texImageTarget, EffectiveBaseMipmapLevel());
|
||||||
|
if (!expected.IsPositive())
|
||||||
|
return false;
|
||||||
|
|
||||||
// checks if custom level>0 images are all defined up to the highest level defined
|
// If Level{max} is > mMaxLevelWithCustomImages, then check if we are
|
||||||
// and have the expected dimensions
|
// missing any image levels.
|
||||||
for (size_t level = GetBaseMipmapLevel(); level <= GetMaxMipmapLevel(); ++level) {
|
if (mMaxMipmapLevel > mMaxLevelWithCustomImages) {
|
||||||
|
if (MipmapLevelsForSize(expected) > mMaxLevelWithCustomImages)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if custom images are all defined up to the highest level and
|
||||||
|
// have the expected dimensions.
|
||||||
|
for (size_t level = EffectiveBaseMipmapLevel(); level <= EffectiveMaxMipmapLevel(); ++level) {
|
||||||
const ImageInfo& actual = ImageInfoAt(texImageTarget, level);
|
const ImageInfo& actual = ImageInfoAt(texImageTarget, level);
|
||||||
if (actual != expected)
|
if (actual != expected)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Check the raw value here, not the clamped one, since we don't want
|
|
||||||
// to terminate early if there aren't enough levels defined.
|
|
||||||
if (level == mMaxMipmapLevel)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
expected.mWidth = std::max(1, expected.mWidth / 2);
|
expected.mWidth = std::max(1, expected.mWidth / 2);
|
||||||
expected.mHeight = std::max(1, expected.mHeight / 2);
|
expected.mHeight = std::max(1, expected.mHeight / 2);
|
||||||
expected.mDepth = std::max(1, expected.mDepth / 2);
|
expected.mDepth = std::max(1, expected.mDepth / 2);
|
||||||
|
@ -108,8 +123,7 @@ WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImage
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we're here, we've exhausted all levels without finding a 1x1 image
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -177,25 +191,19 @@ WebGLTexture::SetGeneratedMipmap() {
|
||||||
void
|
void
|
||||||
WebGLTexture::SetCustomMipmap() {
|
WebGLTexture::SetCustomMipmap() {
|
||||||
if (mHaveGeneratedMipmap) {
|
if (mHaveGeneratedMipmap) {
|
||||||
// if we were in GeneratedMipmap mode and are now switching to CustomMipmap mode,
|
if (!IsMipmapRangeValid())
|
||||||
// we need to compute now all the mipmap image info.
|
return;
|
||||||
|
|
||||||
// since we were in GeneratedMipmap mode, we know that the level 0 images all have the same info,
|
// If we were in GeneratedMipmap mode and are now switching to CustomMipmap mode,
|
||||||
// and are power-of-two.
|
// we now need to compute all the mipmap image info.
|
||||||
ImageInfo imageInfo = ImageInfoAtFace(0, GetBaseMipmapLevel());
|
ImageInfo imageInfo = ImageInfoAtFace(0, EffectiveBaseMipmapLevel());
|
||||||
NS_ASSERTION(mContext->IsWebGL2() || imageInfo.IsPowerOfTwo(),
|
NS_ASSERTION(mContext->IsWebGL2() || imageInfo.IsPowerOfTwo(),
|
||||||
"this texture is NPOT, so how could GenerateMipmap() ever accept it?");
|
"this texture is NPOT, so how could GenerateMipmap() ever accept it?");
|
||||||
|
|
||||||
GLsizei size = std::max(std::max(imageInfo.mWidth, imageInfo.mHeight), imageInfo.mDepth);
|
size_t maxLevel = MipmapLevelsForSize(imageInfo);
|
||||||
|
EnsureMaxLevelWithCustomImagesAtLeast(EffectiveBaseMipmapLevel() + maxLevel);
|
||||||
|
|
||||||
// Find floor(log2(size)). (ES 3.0.4, 3.8 - Mipmapping).
|
for (size_t level = EffectiveBaseMipmapLevel() + 1; level <= EffectiveMaxMipmapLevel(); ++level) {
|
||||||
size_t maxLevel = 0;
|
|
||||||
for (GLsizei n = size; n > 1; n >>= 1)
|
|
||||||
++maxLevel;
|
|
||||||
|
|
||||||
EnsureMaxLevelWithCustomImagesAtLeast(maxLevel);
|
|
||||||
|
|
||||||
for (size_t level = GetBaseMipmapLevel() + 1; level <= GetMaxMipmapLevel(); ++level) {
|
|
||||||
imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1);
|
imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1);
|
||||||
imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1);
|
imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1);
|
||||||
imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1);
|
imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1);
|
||||||
|
@ -219,11 +227,6 @@ bool
|
||||||
WebGLTexture::IsMipmapComplete() const {
|
WebGLTexture::IsMipmapComplete() const {
|
||||||
MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_2D ||
|
MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_2D ||
|
||||||
mTarget == LOCAL_GL_TEXTURE_3D);
|
mTarget == LOCAL_GL_TEXTURE_3D);
|
||||||
|
|
||||||
if (!ImageInfoAtFace(0, GetBaseMipmapLevel()).IsPositive())
|
|
||||||
return false;
|
|
||||||
if (mHaveGeneratedMipmap)
|
|
||||||
return true;
|
|
||||||
return DoesMipmapHaveAllLevelsConsistentlyDefined(LOCAL_GL_TEXTURE_2D);
|
return DoesMipmapHaveAllLevelsConsistentlyDefined(LOCAL_GL_TEXTURE_2D);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,6 +252,17 @@ WebGLTexture::IsMipmapCubeComplete() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WebGLTexture::IsMipmapRangeValid() const
|
||||||
|
{
|
||||||
|
// In ES3, if a texture is immutable, the mipmap levels are clamped.
|
||||||
|
if (IsImmutable())
|
||||||
|
return true;
|
||||||
|
if (mBaseMipmapLevel > std::min(mMaxLevelWithCustomImages, mMaxMipmapLevel))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
WebGLTextureFakeBlackStatus
|
WebGLTextureFakeBlackStatus
|
||||||
WebGLTexture::ResolvedFakeBlackStatus() {
|
WebGLTexture::ResolvedFakeBlackStatus() {
|
||||||
if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) {
|
if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) {
|
||||||
|
@ -256,10 +270,14 @@ WebGLTexture::ResolvedFakeBlackStatus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if the texture needs to be faked as a black texture.
|
// Determine if the texture needs to be faked as a black texture.
|
||||||
// See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec.
|
// See 3.8.2 Shader Execution in the OpenGL ES 2.0.24 spec, and 3.8.13 in
|
||||||
|
// the OpenGL ES 3.0.4 spec.
|
||||||
|
if (!IsMipmapRangeValid()) {
|
||||||
|
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||||
|
return mFakeBlackStatus;
|
||||||
|
}
|
||||||
for (size_t face = 0; face < mFacesCount; ++face) {
|
for (size_t face = 0; face < mFacesCount; ++face) {
|
||||||
if (ImageInfoAtFace(face, GetBaseMipmapLevel()).mImageDataStatus == WebGLImageDataStatus::NoImageData) {
|
if (ImageInfoAtFace(face, EffectiveBaseMipmapLevel()).mImageDataStatus == WebGLImageDataStatus::NoImageData) {
|
||||||
// In case of undefined texture image, we don't print any message because this is a very common
|
// In case of undefined texture image, we don't print any message because this is a very common
|
||||||
// and often legitimate case (asynchronous texture loading).
|
// and often legitimate case (asynchronous texture loading).
|
||||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "mozilla/LinkedList.h"
|
#include "mozilla/LinkedList.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include "nsAlgorithm.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
@ -286,16 +287,22 @@ public:
|
||||||
bool IsImmutable() const { return mImmutable; }
|
bool IsImmutable() const { return mImmutable; }
|
||||||
void SetImmutable() { mImmutable = true; }
|
void SetImmutable() { mImmutable = true; }
|
||||||
|
|
||||||
void SetBaseMipmapLevel(unsigned level) { mBaseMipmapLevel = level; }
|
void SetBaseMipmapLevel(size_t level) { mBaseMipmapLevel = level; }
|
||||||
void SetMaxMipmapLevel(unsigned level) { mMaxMipmapLevel = level; }
|
void SetMaxMipmapLevel(size_t level) { mMaxMipmapLevel = level; }
|
||||||
size_t GetBaseMipmapLevel() const {
|
|
||||||
// Clamp to [0, levels - 1]
|
// Clamping (from ES 3.0.4, section 3.8 - Texturing). When not immutable,
|
||||||
return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
|
// the ranges must be guarded.
|
||||||
|
size_t EffectiveBaseMipmapLevel() const {
|
||||||
|
if (IsImmutable())
|
||||||
|
return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
|
||||||
|
return mBaseMipmapLevel;
|
||||||
}
|
}
|
||||||
size_t GetMaxMipmapLevel() const {
|
size_t EffectiveMaxMipmapLevel() const {
|
||||||
// Clamp to [base, levels - 1]
|
if (IsImmutable())
|
||||||
|
return mozilla::clamped(mMaxMipmapLevel, EffectiveBaseMipmapLevel(), mMaxLevelWithCustomImages);
|
||||||
return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages);
|
return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages);
|
||||||
}
|
}
|
||||||
|
bool IsMipmapRangeValid() const;
|
||||||
|
|
||||||
size_t MaxLevelWithCustomImages() const { return mMaxLevelWithCustomImages; }
|
size_t MaxLevelWithCustomImages() const { return mMaxLevelWithCustomImages; }
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "nsCRTGlue.h"
|
#include "nsCRTGlue.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
|
#include "nsNullPrincipal.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -409,9 +410,19 @@ nsJSON::DecodeInternal(JSContext* cx,
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult rv =
|
nsresult rv;
|
||||||
NS_NewInputStreamChannel(getter_AddRefs(jsonChannel), mURI, aStream,
|
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||||
NS_LITERAL_CSTRING("application/json"));
|
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = NS_NewInputStreamChannel(getter_AddRefs(jsonChannel),
|
||||||
|
mURI,
|
||||||
|
aStream,
|
||||||
|
nullPrincipal,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
NS_LITERAL_CSTRING("application/json"));
|
||||||
|
|
||||||
if (!jsonChannel || NS_FAILED(rv))
|
if (!jsonChannel || NS_FAILED(rv))
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include "nsIContentViewer.h"
|
#include "nsIContentViewer.h"
|
||||||
#include "nsIXPConnect.h"
|
#include "nsIXPConnect.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsNullPrincipal.h"
|
||||||
#include "nsJSUtils.h"
|
#include "nsJSUtils.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsIScriptChannel.h"
|
#include "nsIScriptChannel.h"
|
||||||
|
@ -427,9 +428,18 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
|
||||||
// and the underlying Input Stream will not be created...
|
// and the underlying Input Stream will not be created...
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
|
|
||||||
|
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||||
|
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// If the resultant script evaluation actually does return a value, we
|
// If the resultant script evaluation actually does return a value, we
|
||||||
// treat it as html.
|
// treat it as html.
|
||||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), aURI, mIOThunk,
|
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||||
|
aURI,
|
||||||
|
mIOThunk,
|
||||||
|
nullPrincipal,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
NS_LITERAL_CSTRING("text/html"));
|
NS_LITERAL_CSTRING("text/html"));
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ interface MediaKeySession : EventTarget {
|
||||||
|
|
||||||
readonly attribute unrestricted double expiration;
|
readonly attribute unrestricted double expiration;
|
||||||
|
|
||||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
|
||||||
readonly attribute Promise<void> closed;
|
readonly attribute Promise<void> closed;
|
||||||
|
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
|
@ -31,15 +30,12 @@ interface MediaKeySession : EventTarget {
|
||||||
Promise<boolean> load(DOMString sessionId);
|
Promise<boolean> load(DOMString sessionId);
|
||||||
|
|
||||||
// session operations
|
// session operations
|
||||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
Promise<void> update((ArrayBufferView or ArrayBuffer) response);
|
Promise<void> update((ArrayBufferView or ArrayBuffer) response);
|
||||||
|
|
||||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
Promise<void> close();
|
Promise<void> close();
|
||||||
|
|
||||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
Promise<void> remove();
|
Promise<void> remove();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@ interface MediaKeys {
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
MediaKeySession createSession(optional SessionType sessionType = "temporary");
|
MediaKeySession createSession(optional SessionType sessionType = "temporary");
|
||||||
|
|
||||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
|
||||||
[NewObject, Throws]
|
[NewObject, Throws]
|
||||||
Promise<void> setServerCertificate((ArrayBufferView or ArrayBuffer) serverCertificate);
|
Promise<void> setServerCertificate((ArrayBufferView or ArrayBuffer) serverCertificate);
|
||||||
|
|
||||||
|
|
|
@ -342,6 +342,11 @@ interface WebGL2RenderingContext : WebGLRenderingContext
|
||||||
void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
void texStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||||
void texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
void texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
||||||
GLsizei depth);
|
GLsizei depth);
|
||||||
|
[Throws]
|
||||||
|
void texImage3D(GLenum target, GLint level, GLenum internalformat,
|
||||||
|
GLsizei width, GLsizei height, GLsizei depth,
|
||||||
|
GLint border, GLenum format,
|
||||||
|
GLenum type, ArrayBufferView? pixels);
|
||||||
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
[Throws] void texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
|
||||||
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
|
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
|
||||||
ArrayBufferView? pixels);
|
ArrayBufferView? pixels);
|
||||||
|
|
|
@ -72,6 +72,11 @@ nsresult
|
||||||
nsHTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
|
nsHTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
|
||||||
{
|
{
|
||||||
nsHTMLEditor* htmlEditor = GetHTMLEditor();
|
nsHTMLEditor* htmlEditor = GetHTMLEditor();
|
||||||
|
// Contenteditable should disregard mousedowns outside it.
|
||||||
|
// IsAcceptableInputEvent() checks it for a mouse event.
|
||||||
|
if (!htmlEditor->IsAcceptableInputEvent(aMouseEvent)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Detect only "context menu" click
|
// Detect only "context menu" click
|
||||||
// XXX This should be easier to do!
|
// XXX This should be easier to do!
|
||||||
|
@ -93,11 +98,6 @@ nsHTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
|
||||||
NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
|
NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
|
||||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(target);
|
||||||
|
|
||||||
// Contenteditable should disregard mousedowns outside it
|
|
||||||
if (element && !htmlEditor->IsDescendantOfEditorRoot(element)) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isContextClick || (buttonNumber == 0 && clickCount == 2)) {
|
if (isContextClick || (buttonNumber == 0 && clickCount == 2)) {
|
||||||
nsCOMPtr<nsISelection> selection;
|
nsCOMPtr<nsISelection> selection;
|
||||||
mEditor->GetSelection(getter_AddRefs(selection));
|
mEditor->GetSelection(getter_AddRefs(selection));
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "nsIStandardURL.h"
|
#include "nsIStandardURL.h"
|
||||||
#include "nsMimeTypes.h"
|
#include "nsMimeTypes.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsNullPrincipal.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
#include <gio/gio.h>
|
#include <gio/gio.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -1062,11 +1063,18 @@ nsGIOProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **aResult)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||||
|
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// start out assuming an unknown content-type. we'll set the content-type
|
// start out assuming an unknown content-type. we'll set the content-type
|
||||||
// to something better once we open the URI.
|
// to something better once we open the URI.
|
||||||
rv = NS_NewInputStreamChannel(aResult,
|
rv = NS_NewInputStreamChannel(aResult,
|
||||||
aURI,
|
aURI,
|
||||||
stream,
|
stream,
|
||||||
|
nullPrincipal,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE));
|
NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE));
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
stream->SetChannel(*aResult);
|
stream->SetChannel(*aResult);
|
||||||
|
|
|
@ -548,11 +548,12 @@ Factory::SetDirect3D10Device(ID3D10Device1 *aDevice)
|
||||||
|
|
||||||
ID3D10Device1*
|
ID3D10Device1*
|
||||||
Factory::GetDirect3D10Device()
|
Factory::GetDirect3D10Device()
|
||||||
|
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
UINT mode = mD3D10Device->GetExceptionMode();
|
if (mD3D10Device) {
|
||||||
MOZ_ASSERT(0 == mode);
|
UINT mode = mD3D10Device->GetExceptionMode();
|
||||||
|
MOZ_ASSERT(0 == mode);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return mD3D10Device;
|
return mD3D10Device;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,3 @@ endif
|
||||||
|
|
||||||
include $(topsrcdir)/config/rules.mk
|
include $(topsrcdir)/config/rules.mk
|
||||||
|
|
||||||
# We have to filter out -pedantic, because of
|
|
||||||
# comma-at-end-of-enumerator list failures. We can try to get this fixed
|
|
||||||
# upstream at some point.
|
|
||||||
CXXFLAGS := $(filter-out -pedantic,$(CXXFLAGS))
|
|
||||||
CFLAGS := $(filter-out -pedantic,$(CFLAGS))
|
|
||||||
|
|
|
@ -1253,7 +1253,7 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
||||||
|
|
||||||
if (IsSupported(GLFeature::texture_3D)) {
|
if (IsSupported(GLFeature::texture_3D)) {
|
||||||
SymLoadStruct coreSymbols[] = {
|
SymLoadStruct coreSymbols[] = {
|
||||||
// TexImage3D is not required for WebGL2 so not queried here.
|
{ (PRFuncPtr*) &mSymbols.fTexImage3D, { "TexImage3D", nullptr } },
|
||||||
{ (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3D", nullptr } },
|
{ (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3D", nullptr } },
|
||||||
END_SYMBOLS
|
END_SYMBOLS
|
||||||
};
|
};
|
||||||
|
|
|
@ -3132,6 +3132,21 @@ public:
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// 3D Textures
|
// 3D Textures
|
||||||
|
void fTexImage3D(GLenum target, GLint level,
|
||||||
|
GLint internalFormat,
|
||||||
|
GLsizei width, GLsizei height, GLsizei depth,
|
||||||
|
GLint border, GLenum format, GLenum type,
|
||||||
|
const GLvoid * data)
|
||||||
|
{
|
||||||
|
BEFORE_GL_CALL;
|
||||||
|
ASSERT_SYMBOL_PRESENT(fTexImage3D);
|
||||||
|
mSymbols.fTexImage3D(target, level, internalFormat,
|
||||||
|
width, height, depth,
|
||||||
|
border, format, type,
|
||||||
|
data);
|
||||||
|
AFTER_GL_CALL;
|
||||||
|
}
|
||||||
|
|
||||||
void fTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
void fTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
|
||||||
GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
|
GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
|
||||||
GLenum format, GLenum type, const GLvoid* pixels)
|
GLenum format, GLenum type, const GLvoid* pixels)
|
||||||
|
|
|
@ -642,6 +642,12 @@ struct GLContextSymbols
|
||||||
PFNGLGETFRAGDATALOCATIONPROC fGetFragDataLocation;
|
PFNGLGETFRAGDATALOCATIONPROC fGetFragDataLocation;
|
||||||
|
|
||||||
// 3D Textures
|
// 3D Textures
|
||||||
|
typedef void (GLAPIENTRY * PFNGLTEXIMAGE3DPROC) (GLenum target, GLint level,
|
||||||
|
GLenum internalFormat,
|
||||||
|
GLenum width, GLsizei height, GLsizei depth,
|
||||||
|
GLint border, GLenum format, GLenum type,
|
||||||
|
const GLvoid* pixels);
|
||||||
|
PFNGLTEXIMAGE3DPROC fTexImage3D;
|
||||||
typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset,
|
typedef void (GLAPIENTRY * PFNGLTEXSUBIMAGE3DPROC) (GLenum target, GLint level, GLint xoffset,
|
||||||
GLint yoffset, GLint zoffset, GLsizei width,
|
GLint yoffset, GLint zoffset, GLsizei width,
|
||||||
GLsizei height, GLsizei depth, GLenum format,
|
GLsizei height, GLsizei depth, GLenum format,
|
||||||
|
|
|
@ -369,17 +369,16 @@ gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIChannel> channel;
|
nsCOMPtr<nsIChannel> channel;
|
||||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), uri, nullptr /* stream */,
|
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||||
SVG_CONTENT_TYPE, UTF8_CHARSET);
|
uri,
|
||||||
|
nullptr, //aStream
|
||||||
|
principal,
|
||||||
|
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
SVG_CONTENT_TYPE,
|
||||||
|
UTF8_CHARSET);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
|
||||||
new LoadInfo(principal,
|
|
||||||
nullptr,
|
|
||||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
|
||||||
nsIContentPolicy::TYPE_OTHER);
|
|
||||||
channel->SetLoadInfo(loadInfo);
|
|
||||||
|
|
||||||
// Set this early because various decisions during page-load depend on it.
|
// Set this early because various decisions during page-load depend on it.
|
||||||
document->SetIsBeingUsedAsImage();
|
document->SetIsBeingUsedAsImage();
|
||||||
document->SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
|
document->SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
|
||||||
|
|
|
@ -413,7 +413,7 @@ gfxUserFontEntry::LoadNextSrc()
|
||||||
mItalic);
|
mItalic);
|
||||||
mFontSet->SetLocalRulesUsed();
|
mFontSet->SetLocalRulesUsed();
|
||||||
if (fe) {
|
if (fe) {
|
||||||
LOG(("fontset (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
|
LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
|
||||||
mFontSet, mSrcIndex,
|
mFontSet, mSrcIndex,
|
||||||
NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
|
NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
|
||||||
NS_ConvertUTF16toUTF8(mFamilyName).get(),
|
NS_ConvertUTF16toUTF8(mFamilyName).get(),
|
||||||
|
@ -430,7 +430,7 @@ gfxUserFontEntry::LoadNextSrc()
|
||||||
SetLoadState(STATUS_LOADED);
|
SetLoadState(STATUS_LOADED);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
LOG(("fontset (%p) [src %d] failed local: (%s) for (%s)\n",
|
LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n",
|
||||||
mFontSet, mSrcIndex,
|
mFontSet, mSrcIndex,
|
||||||
NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
|
NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
|
||||||
NS_ConvertUTF16toUTF8(mFamilyName).get()));
|
NS_ConvertUTF16toUTF8(mFamilyName).get()));
|
||||||
|
@ -647,7 +647,7 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
|
||||||
nsAutoCString fontURI;
|
nsAutoCString fontURI;
|
||||||
mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
|
mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
|
||||||
LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) gen: %8.8x\n",
|
LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) gen: %8.8x\n",
|
||||||
this, mSrcIndex, fontURI.get(),
|
mFontSet, mSrcIndex, fontURI.get(),
|
||||||
NS_ConvertUTF16toUTF8(mFamilyName).get(),
|
NS_ConvertUTF16toUTF8(mFamilyName).get(),
|
||||||
uint32_t(mFontSet->mGeneration)));
|
uint32_t(mFontSet->mGeneration)));
|
||||||
}
|
}
|
||||||
|
@ -662,7 +662,7 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
|
||||||
mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
|
mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
|
||||||
LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
|
LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
|
||||||
" error making platform font\n",
|
" error making platform font\n",
|
||||||
this, mSrcIndex, fontURI.get(),
|
mFontSet, mSrcIndex, fontURI.get(),
|
||||||
NS_ConvertUTF16toUTF8(mFamilyName).get()));
|
NS_ConvertUTF16toUTF8(mFamilyName).get()));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -467,6 +467,10 @@ public:
|
||||||
mLocalRulesUsed = true;
|
mLocalRulesUsed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PR_LOGGING
|
||||||
|
static PRLogModuleInfo* GetUserFontsLog();
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Protected destructor, to discourage deletion outside of Release():
|
// Protected destructor, to discourage deletion outside of Release():
|
||||||
virtual ~gfxUserFontSet();
|
virtual ~gfxUserFontSet();
|
||||||
|
@ -512,8 +516,6 @@ protected:
|
||||||
|
|
||||||
// true when local names have been looked up, false otherwise
|
// true when local names have been looked up, false otherwise
|
||||||
bool mLocalRulesUsed;
|
bool mLocalRulesUsed;
|
||||||
|
|
||||||
static PRLogModuleInfo* GetUserFontsLog();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// acts a placeholder until the real font is downloaded
|
// acts a placeholder until the real font is downloaded
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "nsIconChannel.h"
|
#include "nsIconChannel.h"
|
||||||
#include "nsIStringStream.h"
|
#include "nsIStringStream.h"
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsNullPrincipal.h"
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(nsIconChannel,
|
NS_IMPL_ISUPPORTS(nsIconChannel,
|
||||||
nsIRequest,
|
nsIRequest,
|
||||||
|
@ -102,7 +103,16 @@ moz_icon_to_channel(nsIURI *aURI, const nsACString& aFileExt, uint32_t aIconSize
|
||||||
rv = stream->AdoptData((char*)buf, buf_size);
|
rv = stream->AdoptData((char*)buf, buf_size);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return NS_NewInputStreamChannel(aChannel, aURI, stream,
|
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||||
|
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_NewInputStreamChannel(aChannel,
|
||||||
|
aURI,
|
||||||
|
stream,
|
||||||
|
nullPrincipal,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
NS_LITERAL_CSTRING(IMAGE_ICON_MS));
|
NS_LITERAL_CSTRING(IMAGE_ICON_MS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
|
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsNullPrincipal.h"
|
||||||
#include "nsIURL.h"
|
#include "nsIURL.h"
|
||||||
#include "prlink.h"
|
#include "prlink.h"
|
||||||
|
|
||||||
|
@ -137,9 +138,17 @@ moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI *aURI,
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = NS_NewInputStreamChannel(aChannel, aURI, stream,
|
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||||
NS_LITERAL_CSTRING(IMAGE_ICON_MS));
|
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||||
return rv;
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_NewInputStreamChannel(aChannel,
|
||||||
|
aURI,
|
||||||
|
stream,
|
||||||
|
nullPrincipal,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
|
NS_LITERAL_CSTRING(IMAGE_ICON_MS));
|
||||||
}
|
}
|
||||||
|
|
||||||
static GtkWidget *gProtoWindow = nullptr;
|
static GtkWidget *gProtoWindow = nullptr;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "nsIStringBundle.h"
|
#include "nsIStringBundle.h"
|
||||||
|
|
||||||
#include "nsNetUtil.h"
|
#include "nsNetUtil.h"
|
||||||
|
#include "nsNullPrincipal.h"
|
||||||
#include "nsIURL.h"
|
#include "nsIURL.h"
|
||||||
|
|
||||||
#include "nsIconChannel.h"
|
#include "nsIconChannel.h"
|
||||||
|
@ -83,7 +84,16 @@ moz_qicon_to_channel(QImage *image, nsIURI *aURI,
|
||||||
rv = stream->AdoptData((char*)buf, buf_size);
|
rv = stream->AdoptData((char*)buf, buf_size);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return NS_NewInputStreamChannel(aChannel, aURI, stream,
|
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||||
|
do_CreateInstance("@mozilla.org/nullprincipal;1", &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
return NS_NewInputStreamChannel(aChannel,
|
||||||
|
aURI,
|
||||||
|
stream,
|
||||||
|
nullPrincipal,
|
||||||
|
nsILoadInfo::SEC_NORMAL,
|
||||||
|
nsIContentPolicy::TYPE_OTHER,
|
||||||
NS_LITERAL_CSTRING(IMAGE_ICON_MS));
|
NS_LITERAL_CSTRING(IMAGE_ICON_MS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,9 @@ MessageLoop::MessageLoop(Type type)
|
||||||
pump_ = new mozilla::ipc::MessagePumpForNonMainUIThreads();
|
pump_ = new mozilla::ipc::MessagePumpForNonMainUIThreads();
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
default:
|
||||||
|
// Create one of Chromium's standard MessageLoop types below.
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
|
|
|
@ -102,8 +102,8 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RecvGetPropertyKeys(const uint64_t &objId, const uint32_t &flags,
|
bool RecvGetPropertyKeys(const uint64_t &objId, const uint32_t &flags,
|
||||||
ReturnStatus *rs, nsTArray<nsString> *names) {
|
ReturnStatus *rs, nsTArray<JSIDVariant> *ids) {
|
||||||
return Answer::RecvGetPropertyKeys(ObjectId::deserialize(objId), flags, rs, names);
|
return Answer::RecvGetPropertyKeys(ObjectId::deserialize(objId), flags, rs, ids);
|
||||||
}
|
}
|
||||||
bool RecvInstanceOf(const uint64_t &objId, const JSIID &iid,
|
bool RecvInstanceOf(const uint64_t &objId, const JSIID &iid,
|
||||||
ReturnStatus *rs, bool *instanceof) {
|
ReturnStatus *rs, bool *instanceof) {
|
||||||
|
@ -200,8 +200,8 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SendGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
bool SendGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
||||||
ReturnStatus *rs, nsTArray<nsString> *names) {
|
ReturnStatus *rs, nsTArray<JSIDVariant> *ids) {
|
||||||
return Base::SendGetPropertyKeys(objId.serialize(), flags, rs, names);
|
return Base::SendGetPropertyKeys(objId.serialize(), flags, rs, ids);
|
||||||
}
|
}
|
||||||
bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
|
bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
|
||||||
ReturnStatus *rs, bool *instanceof) {
|
ReturnStatus *rs, bool *instanceof) {
|
||||||
|
|
|
@ -440,7 +440,8 @@ JavaScriptShared::toSymbolVariant(JSContext *cx, JS::Symbol *symArg, SymbolVaria
|
||||||
*symVarp = RegisteredSymbol(autoStr);
|
*symVarp = RegisteredSymbol(autoStr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
MOZ_CRASH("unique symbols not yet implemented");
|
|
||||||
|
JS_ReportError(cx, "unique symbol can't be used with CPOW");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ both:
|
||||||
prio(high) sync ClassName(uint64_t objId) returns (nsString name);
|
prio(high) sync ClassName(uint64_t objId) returns (nsString name);
|
||||||
prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
|
prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
|
||||||
|
|
||||||
prio(high) sync GetPropertyKeys(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, nsString[] names);
|
prio(high) sync GetPropertyKeys(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, JSIDVariant[] ids);
|
||||||
prio(high) sync InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
|
prio(high) sync InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
|
||||||
prio(high) sync DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
|
prio(high) sync DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
|
||||||
|
|
||||||
|
|
|
@ -580,7 +580,7 @@ WrapperAnswer::RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WrapperAnswer::RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
WrapperAnswer::RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
||||||
ReturnStatus *rs, nsTArray<nsString> *names)
|
ReturnStatus *rs, nsTArray<JSIDVariant> *ids)
|
||||||
{
|
{
|
||||||
AutoSafeJSContext cx;
|
AutoSafeJSContext cx;
|
||||||
JSAutoRequest request(cx);
|
JSAutoRequest request(cx);
|
||||||
|
@ -598,11 +598,11 @@ WrapperAnswer::RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
||||||
return fail(cx, rs);
|
return fail(cx, rs);
|
||||||
|
|
||||||
for (size_t i = 0; i < props.length(); i++) {
|
for (size_t i = 0; i < props.length(); i++) {
|
||||||
nsString name;
|
JSIDVariant id;
|
||||||
if (!convertIdToGeckoString(cx, props[i], &name))
|
if (!toJSIDVariant(cx, props[i], &id))
|
||||||
return fail(cx, rs);
|
return fail(cx, rs);
|
||||||
|
|
||||||
names->AppendElement(name);
|
ids->AppendElement(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok(rs);
|
return ok(rs);
|
||||||
|
|
|
@ -55,7 +55,7 @@ class WrapperAnswer : public virtual JavaScriptShared
|
||||||
bool RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
|
bool RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
|
||||||
|
|
||||||
bool RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
bool RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
||||||
ReturnStatus *rs, nsTArray<nsString> *names);
|
ReturnStatus *rs, nsTArray<JSIDVariant> *ids);
|
||||||
bool RecvInstanceOf(const ObjectId &objId, const JSIID &iid,
|
bool RecvInstanceOf(const ObjectId &objId, const JSIID &iid,
|
||||||
ReturnStatus *rs, bool *instanceof);
|
ReturnStatus *rs, bool *instanceof);
|
||||||
bool RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
bool RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
||||||
|
|
|
@ -63,9 +63,6 @@ class CPOWProxyHandler : public BaseProxyHandler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE;
|
|
||||||
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
|
||||||
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
|
||||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
virtual bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||||
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
@ -74,18 +71,21 @@ class CPOWProxyHandler : public BaseProxyHandler
|
||||||
AutoIdVector &props) const MOZ_OVERRIDE;
|
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||||
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
virtual bool delete_(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||||
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
|
virtual bool enumerate(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
|
||||||
|
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
|
||||||
|
virtual bool preventExtensions(JSContext *cx, HandleObject proxy) const MOZ_OVERRIDE;
|
||||||
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
virtual bool has(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||||
virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
|
||||||
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||||
HandleId id, MutableHandleValue vp) const MOZ_OVERRIDE;
|
HandleId id, MutableHandleValue vp) const MOZ_OVERRIDE;
|
||||||
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const MOZ_OVERRIDE;
|
JS::HandleId id, bool strict, JS::MutableHandleValue vp) const MOZ_OVERRIDE;
|
||||||
virtual bool keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) const MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual bool isExtensible(JSContext *cx, HandleObject proxy, bool *extensible) const MOZ_OVERRIDE;
|
|
||||||
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
|
virtual bool call(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
|
||||||
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
|
virtual bool construct(JSContext *cx, HandleObject proxy, const CallArgs &args) const MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||||
|
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||||
|
virtual bool hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||||
|
virtual bool getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||||
|
AutoIdVector &props) const MOZ_OVERRIDE;
|
||||||
virtual bool hasInstance(JSContext *cx, HandleObject proxy,
|
virtual bool hasInstance(JSContext *cx, HandleObject proxy,
|
||||||
MutableHandleValue v, bool *bp) const MOZ_OVERRIDE;
|
MutableHandleValue v, bool *bp) const MOZ_OVERRIDE;
|
||||||
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
|
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
|
||||||
|
@ -232,7 +232,7 @@ CPOWProxyHandler::ownPropertyKeys(JSContext *cx, HandleObject proxy,
|
||||||
bool
|
bool
|
||||||
WrapperOwner::ownPropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
WrapperOwner::ownPropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
{
|
{
|
||||||
return getPropertyKeys(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN, props);
|
return getPropertyKeys(cx, proxy, JSITER_OWNONLY | JSITER_HIDDEN | JSITER_SYMBOLS, props);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -463,13 +463,14 @@ WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiv
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CPOWProxyHandler::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props) const
|
CPOWProxyHandler::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy,
|
||||||
|
AutoIdVector &props) const
|
||||||
{
|
{
|
||||||
FORWARD(keys, (cx, proxy, props));
|
FORWARD(getOwnEnumerablePropertyKeys, (cx, proxy, props));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
WrapperOwner::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
WrapperOwner::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||||
{
|
{
|
||||||
return getPropertyKeys(cx, proxy, JSITER_OWNONLY, props);
|
return getPropertyKeys(cx, proxy, JSITER_OWNONLY, props);
|
||||||
}
|
}
|
||||||
|
@ -776,8 +777,8 @@ WrapperOwner::getPropertyKeys(JSContext *cx, HandleObject proxy, uint32_t flags,
|
||||||
ObjectId objId = idOf(proxy);
|
ObjectId objId = idOf(proxy);
|
||||||
|
|
||||||
ReturnStatus status;
|
ReturnStatus status;
|
||||||
InfallibleTArray<nsString> names;
|
InfallibleTArray<JSIDVariant> ids;
|
||||||
if (!SendGetPropertyKeys(objId, flags, &status, &names))
|
if (!SendGetPropertyKeys(objId, flags, &status, &ids))
|
||||||
return ipcfail(cx);
|
return ipcfail(cx);
|
||||||
|
|
||||||
LOG_STACK();
|
LOG_STACK();
|
||||||
|
@ -785,11 +786,11 @@ WrapperOwner::getPropertyKeys(JSContext *cx, HandleObject proxy, uint32_t flags,
|
||||||
if (!ok(cx, status))
|
if (!ok(cx, status))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (size_t i = 0; i < names.Length(); i++) {
|
for (size_t i = 0; i < ids.Length(); i++) {
|
||||||
RootedId name(cx);
|
RootedId id(cx);
|
||||||
if (!convertGeckoStringToId(cx, names[i], &name))
|
if (!fromJSIDVariant(cx, ids[i], &id))
|
||||||
return false;
|
return false;
|
||||||
if (!props.append(name))
|
if (!props.append(id))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,11 +31,8 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||||
explicit WrapperOwner(JSRuntime *rt);
|
explicit WrapperOwner(JSRuntime *rt);
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
// Fundamental proxy traps. These are required.
|
// Standard internal methods.
|
||||||
// (The traps should be in the same order like js/src/jsproxy.h)
|
// (The traps should be in the same order like js/src/jsproxy.h)
|
||||||
bool preventExtensions(JSContext *cx, JS::HandleObject proxy);
|
|
||||||
bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
|
||||||
bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
bool getOwnPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||||
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
bool defineProperty(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
|
@ -43,25 +40,27 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||||
bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
bool ownPropertyKeys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
bool delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||||
|
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
|
||||||
// Derived proxy traps. Implementing these is useful for perfomance.
|
bool preventExtensions(JSContext *cx, JS::HandleObject proxy);
|
||||||
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
bool has(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
bool hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
|
||||||
bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
bool get(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
JS::HandleId id, JS::MutableHandleValue vp);
|
JS::HandleId id, JS::MutableHandleValue vp);
|
||||||
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||||
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
|
JS::HandleId id, bool strict, JS::MutableHandleValue vp);
|
||||||
bool keys(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
|
||||||
// We use "iterate" provided by the base class here.
|
|
||||||
|
|
||||||
// SpiderMonkey Extensions.
|
|
||||||
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
|
|
||||||
bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g);
|
|
||||||
bool callOrConstruct(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args,
|
bool callOrConstruct(JSContext *cx, JS::HandleObject proxy, const JS::CallArgs &args,
|
||||||
bool construct);
|
bool construct);
|
||||||
|
|
||||||
|
// SpiderMonkey extensions.
|
||||||
|
bool getPropertyDescriptor(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||||
|
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||||
|
bool hasOwn(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||||
|
bool getOwnEnumerablePropertyKeys(JSContext *cx, JS::HandleObject proxy,
|
||||||
|
JS::AutoIdVector &props);
|
||||||
|
// We use "iterate" provided by the base class here.
|
||||||
bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
|
bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
|
||||||
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
|
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
|
||||||
const char* className(JSContext *cx, JS::HandleObject proxy);
|
const char* className(JSContext *cx, JS::HandleObject proxy);
|
||||||
|
bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g);
|
||||||
bool isCallable(JSObject *obj);
|
bool isCallable(JSObject *obj);
|
||||||
bool isConstructor(JSObject *obj);
|
bool isConstructor(JSObject *obj);
|
||||||
|
|
||||||
|
@ -146,7 +145,7 @@ class WrapperOwner : public virtual JavaScriptShared
|
||||||
uint32_t *flags) = 0;
|
uint32_t *flags) = 0;
|
||||||
|
|
||||||
virtual bool SendGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
virtual bool SendGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
||||||
ReturnStatus *rs, nsTArray<nsString> *names) = 0;
|
ReturnStatus *rs, nsTArray<JSIDVariant> *ids) = 0;
|
||||||
virtual bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
|
virtual bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
|
||||||
ReturnStatus *rs, bool *instanceof) = 0;
|
ReturnStatus *rs, bool *instanceof) = 0;
|
||||||
virtual bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
virtual bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
||||||
|
|
|
@ -315,6 +315,7 @@ selfhosting_srcs := \
|
||||||
$(srcdir)/builtin/Array.js \
|
$(srcdir)/builtin/Array.js \
|
||||||
$(srcdir)/builtin/Date.js \
|
$(srcdir)/builtin/Date.js \
|
||||||
$(srcdir)/builtin/Error.js \
|
$(srcdir)/builtin/Error.js \
|
||||||
|
$(srcdir)/builtin/Generator.js \
|
||||||
$(srcdir)/builtin/Intl.js \
|
$(srcdir)/builtin/Intl.js \
|
||||||
$(srcdir)/builtin/IntlData.js \
|
$(srcdir)/builtin/IntlData.js \
|
||||||
$(srcdir)/builtin/Iterator.js \
|
$(srcdir)/builtin/Iterator.js \
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
function StarGeneratorNext(val) {
|
||||||
|
if (!IsObject(this) || !IsStarGeneratorObject(this))
|
||||||
|
return callFunction(CallStarGeneratorMethodIfWrapped, this, val, "StarGeneratorNext");
|
||||||
|
|
||||||
|
if (StarGeneratorObjectIsClosed(this))
|
||||||
|
return { value: undefined, done: true };
|
||||||
|
|
||||||
|
if (GeneratorIsRunning(this))
|
||||||
|
ThrowError(JSMSG_NESTING_GENERATOR);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return resumeGenerator(this, val, 'next');
|
||||||
|
} catch (e) {
|
||||||
|
if (!StarGeneratorObjectIsClosed(this))
|
||||||
|
GeneratorSetClosed(this);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function StarGeneratorThrow(val) {
|
||||||
|
if (!IsObject(this) || !IsStarGeneratorObject(this))
|
||||||
|
return callFunction(CallStarGeneratorMethodIfWrapped, this, val, "StarGeneratorThrow");
|
||||||
|
|
||||||
|
if (StarGeneratorObjectIsClosed(this))
|
||||||
|
throw val;
|
||||||
|
|
||||||
|
if (GeneratorIsRunning(this))
|
||||||
|
ThrowError(JSMSG_NESTING_GENERATOR);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return resumeGenerator(this, val, 'throw');
|
||||||
|
} catch (e) {
|
||||||
|
if (!StarGeneratorObjectIsClosed(this))
|
||||||
|
GeneratorSetClosed(this);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function LegacyGeneratorNext(val) {
|
||||||
|
if (!IsObject(this) || !IsLegacyGeneratorObject(this))
|
||||||
|
return callFunction(CallLegacyGeneratorMethodIfWrapped, this, val, "LegacyGeneratorNext");
|
||||||
|
|
||||||
|
if (LegacyGeneratorObjectIsClosed(this))
|
||||||
|
ThrowStopIteration();
|
||||||
|
|
||||||
|
if (GeneratorIsRunning(this))
|
||||||
|
ThrowError(JSMSG_NESTING_GENERATOR);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return resumeGenerator(this, val, 'next');
|
||||||
|
} catch(e) {
|
||||||
|
if (!LegacyGeneratorObjectIsClosed(this))
|
||||||
|
GeneratorSetClosed(this);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function LegacyGeneratorThrow(val) {
|
||||||
|
if (!IsObject(this) || !IsLegacyGeneratorObject(this))
|
||||||
|
return callFunction(CallLegacyGeneratorMethodIfWrapped, this, val, "LegacyGeneratorThrow");
|
||||||
|
|
||||||
|
if (LegacyGeneratorObjectIsClosed(this))
|
||||||
|
throw val;
|
||||||
|
|
||||||
|
if (GeneratorIsRunning(this))
|
||||||
|
ThrowError(JSMSG_NESTING_GENERATOR);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return resumeGenerator(this, val, 'throw');
|
||||||
|
} catch(e) {
|
||||||
|
if (!LegacyGeneratorObjectIsClosed(this))
|
||||||
|
GeneratorSetClosed(this);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by js::CloseIterator.
|
||||||
|
function LegacyGeneratorCloseInternal() {
|
||||||
|
assert(IsObject(this), "Not an object: " + ToString(this));
|
||||||
|
assert(IsLegacyGeneratorObject(this), "Not a legacy generator object: " + ToString(this));
|
||||||
|
assert(!LegacyGeneratorObjectIsClosed(this), "Already closed: " + ToString(this));
|
||||||
|
assert(!CloseNewbornLegacyGeneratorObject(this), "Newborn: " + ToString(this));
|
||||||
|
|
||||||
|
if (GeneratorIsRunning(this))
|
||||||
|
ThrowError(JSMSG_NESTING_GENERATOR);
|
||||||
|
|
||||||
|
resumeGenerator(this, undefined, 'close');
|
||||||
|
if (!LegacyGeneratorObjectIsClosed(this))
|
||||||
|
CloseClosingLegacyGeneratorObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
function LegacyGeneratorClose() {
|
||||||
|
if (!IsObject(this) || !IsLegacyGeneratorObject(this))
|
||||||
|
return callFunction(CallLegacyGeneratorMethodIfWrapped, this, "LegacyGeneratorClose");
|
||||||
|
|
||||||
|
if (LegacyGeneratorObjectIsClosed(this) || CloseNewbornLegacyGeneratorObject(this))
|
||||||
|
return;
|
||||||
|
|
||||||
|
callFunction(LegacyGeneratorCloseInternal, this);
|
||||||
|
}
|
|
@ -1294,7 +1294,6 @@ if test "$GNU_CXX"; then
|
||||||
# -Wwrite-strings - catches non-const char* pointers to string literals
|
# -Wwrite-strings - catches non-const char* pointers to string literals
|
||||||
#
|
#
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall"
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wignored-qualifiers"
|
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wsign-compare"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wsign-compare"
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wtype-limits"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wtype-limits"
|
||||||
|
|
||||||
|
@ -1303,6 +1302,7 @@ if test "$GNU_CXX"; then
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=comment"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=comment"
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=empty-body"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=empty-body"
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=endif-labels"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=endif-labels"
|
||||||
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=ignored-qualifiers"
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=int-to-pointer-cast"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=int-to-pointer-cast"
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=missing-braces"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=missing-braces"
|
||||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=overloaded-virtual"
|
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=overloaded-virtual"
|
||||||
|
|
|
@ -2625,8 +2625,8 @@ ImplicitConvert(JSContext* cx,
|
||||||
if (val.isObject() && !sourceData) {
|
if (val.isObject() && !sourceData) {
|
||||||
// Enumerate the properties of the object; if they match the struct
|
// Enumerate the properties of the object; if they match the struct
|
||||||
// specification, convert the fields.
|
// specification, convert the fields.
|
||||||
RootedObject iter(cx, JS_NewPropertyIterator(cx, valObj));
|
AutoIdArray props(cx, JS_Enumerate(cx, valObj));
|
||||||
if (!iter)
|
if (!props)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Convert into an intermediate, in case of failure.
|
// Convert into an intermediate, in case of failure.
|
||||||
|
@ -2637,13 +2637,15 @@ ImplicitConvert(JSContext* cx,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const FieldInfoHash* fields = StructType::GetFieldInfo(targetType);
|
||||||
|
if (props.length() != fields->count()) {
|
||||||
|
JS_ReportError(cx, "missing fields");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
RootedId id(cx);
|
RootedId id(cx);
|
||||||
size_t i = 0;
|
for (size_t i = 0; i < props.length(); ++i) {
|
||||||
while (1) {
|
id = props[i];
|
||||||
if (!JS_NextProperty(cx, iter, &id))
|
|
||||||
return false;
|
|
||||||
if (JSID_IS_VOID(id))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!JSID_IS_STRING(id)) {
|
if (!JSID_IS_STRING(id)) {
|
||||||
JS_ReportError(cx, "property name is not a string");
|
JS_ReportError(cx, "property name is not a string");
|
||||||
|
@ -2663,14 +2665,6 @@ ImplicitConvert(JSContext* cx,
|
||||||
char* fieldData = intermediate.get() + field->mOffset;
|
char* fieldData = intermediate.get() + field->mOffset;
|
||||||
if (!ImplicitConvert(cx, prop, field->mType, fieldData, false, nullptr))
|
if (!ImplicitConvert(cx, prop, field->mType, fieldData, false, nullptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
const FieldInfoHash* fields = StructType::GetFieldInfo(targetType);
|
|
||||||
if (i != fields->count()) {
|
|
||||||
JS_ReportError(cx, "missing fields");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(buffer, intermediate.get(), structSize);
|
memcpy(buffer, intermediate.get(), structSize);
|
||||||
|
@ -4705,33 +4699,23 @@ ExtractStructField(JSContext* cx, jsval val, MutableHandleObject typeObj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedObject obj(cx, val.toObjectOrNull());
|
RootedObject obj(cx, &val.toObject());
|
||||||
RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
|
AutoIdArray props(cx, JS_Enumerate(cx, obj));
|
||||||
if (!iter)
|
if (!props)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
RootedId nameid(cx);
|
|
||||||
if (!JS_NextProperty(cx, iter, &nameid))
|
|
||||||
return nullptr;
|
|
||||||
if (JSID_IS_VOID(nameid)) {
|
|
||||||
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!JSID_IS_STRING(nameid)) {
|
|
||||||
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure we have one, and only one, property
|
// make sure we have one, and only one, property
|
||||||
RootedId id(cx);
|
if (props.length() != 1) {
|
||||||
if (!JS_NextProperty(cx, iter, &id))
|
|
||||||
return nullptr;
|
|
||||||
if (!JSID_IS_VOID(id)) {
|
|
||||||
JS_ReportError(cx, "struct field descriptors must contain one property");
|
JS_ReportError(cx, "struct field descriptors must contain one property");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RootedId nameid(cx, props[0]);
|
||||||
|
if (!JSID_IS_STRING(nameid)) {
|
||||||
|
JS_ReportError(cx, "struct field descriptors require a valid name and type");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
RootedValue propVal(cx);
|
RootedValue propVal(cx);
|
||||||
if (!JS_GetPropertyById(cx, obj, nameid, &propVal))
|
if (!JS_GetPropertyById(cx, obj, nameid, &propVal))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "frontend/Parser.h"
|
#include "frontend/Parser.h"
|
||||||
#include "frontend/TokenStream.h"
|
#include "frontend/TokenStream.h"
|
||||||
#include "vm/Debugger.h"
|
#include "vm/Debugger.h"
|
||||||
|
#include "vm/GeneratorObject.h"
|
||||||
#include "vm/Stack.h"
|
#include "vm/Stack.h"
|
||||||
|
|
||||||
#include "jsatominlines.h"
|
#include "jsatominlines.h"
|
||||||
|
@ -1989,10 +1990,10 @@ CheckSideEffects(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/*
|
/*
|
||||||
* All of PNK_INC, PNK_DEC, PNK_THROW, PNK_YIELD, and PNK_YIELD_STAR
|
* All of PNK_INC, PNK_DEC and PNK_THROW have direct effects. Of
|
||||||
* have direct effects. Of the remaining unary-arity node types, we
|
* the remaining unary-arity node types, we can't easily prove that
|
||||||
* can't easily prove that the operand never denotes an object with
|
* the operand never denotes an object with a toString or valueOf
|
||||||
* a toString or valueOf method.
|
* method.
|
||||||
*/
|
*/
|
||||||
*answer = true;
|
*answer = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -2973,13 +2974,6 @@ frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNo
|
||||||
bce->switchToMain();
|
bce->switchToMain();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (funbox->isGenerator()) {
|
|
||||||
bce->switchToProlog();
|
|
||||||
if (Emit1(cx, bce, JSOP_GENERATOR) < 0)
|
|
||||||
return false;
|
|
||||||
bce->switchToMain();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Emit a prologue for run-once scripts which will deoptimize JIT code if
|
* Emit a prologue for run-once scripts which will deoptimize JIT code if
|
||||||
* the script ends up running multiple times via foo.caller related
|
* the script ends up running multiple times via foo.caller related
|
||||||
|
@ -2996,18 +2990,27 @@ frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNo
|
||||||
if (!EmitTree(cx, bce, body))
|
if (!EmitTree(cx, bce, body))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// If we fall off the end of an ES6 generator, return a boxed iterator
|
// If we fall off the end of a generator, do a final yield.
|
||||||
// result object of the form { value: undefined, done: true }.
|
if (bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isGenerator()) {
|
||||||
if (bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isStarGenerator()) {
|
if (bce->sc->asFunctionBox()->isStarGenerator() && !EmitPrepareIteratorResult(cx, bce))
|
||||||
if (!EmitPrepareIteratorResult(cx, bce))
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||||
return false;
|
return false;
|
||||||
if (!EmitFinishIteratorResult(cx, bce, true))
|
|
||||||
|
if (bce->sc->asFunctionBox()->isStarGenerator() && !EmitFinishIteratorResult(cx, bce, true))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ScopeCoordinate sc;
|
||||||
|
// We know that .generator is on the top scope chain node, as we are
|
||||||
|
// at the function end.
|
||||||
|
sc.setHops(0);
|
||||||
|
MOZ_ALWAYS_TRUE(LookupAliasedNameSlot(bce, bce->script, cx->names().dotGenerator, &sc));
|
||||||
|
if (!EmitAliasedVarOp(cx, JSOP_GETALIASEDVAR, sc, DontCheckLexical, bce))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// No need to check for finally blocks, etc as in EmitReturn.
|
// No need to check for finally blocks, etc as in EmitReturn.
|
||||||
if (Emit1(cx, bce, JSOP_RETURN) < 0)
|
if (Emit1(cx, bce, JSOP_FINALYIELD) < 0)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5463,15 +5466,26 @@ EmitReturn(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
*/
|
*/
|
||||||
ptrdiff_t top = bce->offset();
|
ptrdiff_t top = bce->offset();
|
||||||
|
|
||||||
if (Emit1(cx, bce, JSOP_RETURN) < 0)
|
bool isGenerator = bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isGenerator();
|
||||||
return false;
|
if (Emit1(cx, bce, isGenerator ? JSOP_SETRVAL : JSOP_RETURN) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
NonLocalExitScope nle(cx, bce);
|
NonLocalExitScope nle(cx, bce);
|
||||||
|
|
||||||
if (!nle.prepareForNonLocalJump(nullptr))
|
if (!nle.prepareForNonLocalJump(nullptr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != bce->offset()) {
|
if (isGenerator) {
|
||||||
|
ScopeCoordinate sc;
|
||||||
|
// We know that .generator is on the top scope chain node, as we just
|
||||||
|
// exited nested scopes.
|
||||||
|
sc.setHops(0);
|
||||||
|
MOZ_ALWAYS_TRUE(LookupAliasedNameSlot(bce, bce->script, cx->names().dotGenerator, &sc));
|
||||||
|
if (!EmitAliasedVarOp(cx, JSOP_GETALIASEDVAR, sc, DontCheckLexical, bce))
|
||||||
|
return false;
|
||||||
|
if (Emit1(cx, bce, JSOP_FINALYIELDRVAL) < 0)
|
||||||
|
return false;
|
||||||
|
} else if (top + static_cast<ptrdiff_t>(JSOP_RETURN_LENGTH) != bce->offset()) {
|
||||||
bce->code()[top] = JSOP_SETRVAL;
|
bce->code()[top] = JSOP_SETRVAL;
|
||||||
if (Emit1(cx, bce, JSOP_RETRVAL) < 0)
|
if (Emit1(cx, bce, JSOP_RETRVAL) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
@ -5481,7 +5495,41 @@ EmitReturn(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
EmitYield(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(bce->sc->isFunctionBox());
|
||||||
|
|
||||||
|
if (pn->getOp() == JSOP_YIELD) {
|
||||||
|
if (bce->sc->asFunctionBox()->isStarGenerator()) {
|
||||||
|
if (!EmitPrepareIteratorResult(cx, bce))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pn->pn_left) {
|
||||||
|
if (!EmitTree(cx, bce, pn->pn_left))
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (bce->sc->asFunctionBox()->isStarGenerator()) {
|
||||||
|
if (!EmitFinishIteratorResult(cx, bce, false))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(pn->getOp() == JSOP_INITIALYIELD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!EmitTree(cx, bce, pn->pn_right))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (Emit1(cx, bce, pn->getOp()) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter, ParseNode *gen)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(bce->sc->isFunctionBox());
|
MOZ_ASSERT(bce->sc->isFunctionBox());
|
||||||
MOZ_ASSERT(bce->sc->asFunctionBox()->isStarGenerator());
|
MOZ_ASSERT(bce->sc->asFunctionBox()->isStarGenerator());
|
||||||
|
@ -5500,12 +5548,13 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
return false;
|
return false;
|
||||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||||
|
|
||||||
int depth = bce->stackDepth;
|
|
||||||
MOZ_ASSERT(depth >= 1);
|
|
||||||
|
|
||||||
// Initial send value is undefined.
|
// Initial send value is undefined.
|
||||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0) // ITER RECEIVED
|
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0) // ITER RECEIVED
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
int depth = bce->stackDepth;
|
||||||
|
MOZ_ASSERT(depth >= 2);
|
||||||
|
|
||||||
ptrdiff_t initialSend = -1;
|
ptrdiff_t initialSend = -1;
|
||||||
if (EmitBackPatchOp(cx, bce, &initialSend) < 0) // goto initialSend
|
if (EmitBackPatchOp(cx, bce, &initialSend) < 0) // goto initialSend
|
||||||
return false;
|
return false;
|
||||||
|
@ -5514,17 +5563,21 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
StmtInfoBCE stmtInfo(cx);
|
StmtInfoBCE stmtInfo(cx);
|
||||||
PushStatementBCE(bce, &stmtInfo, STMT_TRY, bce->offset());
|
PushStatementBCE(bce, &stmtInfo, STMT_TRY, bce->offset());
|
||||||
ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_TRY);
|
ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_TRY);
|
||||||
|
ptrdiff_t tryStart = bce->offset(); // tryStart:
|
||||||
if (noteIndex < 0 || Emit1(cx, bce, JSOP_TRY) < 0)
|
if (noteIndex < 0 || Emit1(cx, bce, JSOP_TRY) < 0)
|
||||||
return false;
|
return false;
|
||||||
ptrdiff_t tryStart = bce->offset(); // tryStart:
|
MOZ_ASSERT(bce->stackDepth == depth);
|
||||||
MOZ_ASSERT(bce->stackDepth == depth + 1);
|
|
||||||
|
// Load the generator object.
|
||||||
|
if (!EmitTree(cx, bce, gen)) // ITER RESULT GENOBJ
|
||||||
|
return false;
|
||||||
|
|
||||||
// Yield RESULT as-is, without re-boxing.
|
// Yield RESULT as-is, without re-boxing.
|
||||||
if (Emit1(cx, bce, JSOP_YIELD) < 0) // ITER RECEIVED
|
if (Emit1(cx, bce, JSOP_YIELD) < 0) // ITER RECEIVED
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Try epilogue.
|
// Try epilogue.
|
||||||
if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, bce->offset() - tryStart + JSOP_TRY_LENGTH))
|
if (!SetSrcNoteOffset(cx, bce, noteIndex, 0, bce->offset() - tryStart))
|
||||||
return false;
|
return false;
|
||||||
ptrdiff_t subsequentSend = -1;
|
ptrdiff_t subsequentSend = -1;
|
||||||
if (EmitBackPatchOp(cx, bce, &subsequentSend) < 0) // goto subsequentSend
|
if (EmitBackPatchOp(cx, bce, &subsequentSend) < 0) // goto subsequentSend
|
||||||
|
@ -5532,8 +5585,10 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
ptrdiff_t tryEnd = bce->offset(); // tryEnd:
|
ptrdiff_t tryEnd = bce->offset(); // tryEnd:
|
||||||
|
|
||||||
// Catch location.
|
// Catch location.
|
||||||
// THROW? = 'throw' in ITER // ITER
|
bce->stackDepth = uint32_t(depth); // ITER RESULT
|
||||||
bce->stackDepth = (uint32_t) depth;
|
if (Emit1(cx, bce, JSOP_POP) < 0) // ITER
|
||||||
|
return false;
|
||||||
|
// THROW? = 'throw' in ITER
|
||||||
if (Emit1(cx, bce, JSOP_EXCEPTION) < 0) // ITER EXCEPTION
|
if (Emit1(cx, bce, JSOP_EXCEPTION) < 0) // ITER EXCEPTION
|
||||||
return false;
|
return false;
|
||||||
if (Emit1(cx, bce, JSOP_SWAP) < 0) // EXCEPTION ITER
|
if (Emit1(cx, bce, JSOP_SWAP) < 0) // EXCEPTION ITER
|
||||||
|
@ -5557,7 +5612,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
|
|
||||||
SetJumpOffsetAt(bce, checkThrow); // delegate:
|
SetJumpOffsetAt(bce, checkThrow); // delegate:
|
||||||
// RESULT = ITER.throw(EXCEPTION) // EXCEPTION ITER
|
// RESULT = ITER.throw(EXCEPTION) // EXCEPTION ITER
|
||||||
bce->stackDepth = (uint32_t) depth + 1;
|
bce->stackDepth = uint32_t(depth);
|
||||||
if (Emit1(cx, bce, JSOP_DUP) < 0) // EXCEPTION ITER ITER
|
if (Emit1(cx, bce, JSOP_DUP) < 0) // EXCEPTION ITER ITER
|
||||||
return false;
|
return false;
|
||||||
if (Emit1(cx, bce, JSOP_DUP) < 0) // EXCEPTION ITER ITER ITER
|
if (Emit1(cx, bce, JSOP_DUP) < 0) // EXCEPTION ITER ITER ITER
|
||||||
|
@ -5571,7 +5626,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
if (EmitCall(cx, bce, JSOP_CALL, 1, iter) < 0) // ITER RESULT
|
if (EmitCall(cx, bce, JSOP_CALL, 1, iter) < 0) // ITER RESULT
|
||||||
return false;
|
return false;
|
||||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||||
MOZ_ASSERT(bce->stackDepth == depth + 1);
|
MOZ_ASSERT(bce->stackDepth == depth);
|
||||||
ptrdiff_t checkResult = -1;
|
ptrdiff_t checkResult = -1;
|
||||||
if (EmitBackPatchOp(cx, bce, &checkResult) < 0) // goto checkResult
|
if (EmitBackPatchOp(cx, bce, &checkResult) < 0) // goto checkResult
|
||||||
return false;
|
return false;
|
||||||
|
@ -5582,7 +5637,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
// This is a peace offering to ReconstructPCStack. See the note in EmitTry.
|
// This is a peace offering to ReconstructPCStack. See the note in EmitTry.
|
||||||
if (Emit1(cx, bce, JSOP_NOP) < 0)
|
if (Emit1(cx, bce, JSOP_NOP) < 0)
|
||||||
return false;
|
return false;
|
||||||
if (!bce->tryNoteList.append(JSTRY_CATCH, depth, tryStart, tryEnd))
|
if (!bce->tryNoteList.append(JSTRY_CATCH, depth, tryStart + JSOP_TRY_LENGTH, tryEnd))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// After the try/catch block: send the received value to the iterator.
|
// After the try/catch block: send the received value to the iterator.
|
||||||
|
@ -5608,7 +5663,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
if (EmitCall(cx, bce, JSOP_CALL, 1, iter) < 0) // ITER RESULT
|
if (EmitCall(cx, bce, JSOP_CALL, 1, iter) < 0) // ITER RESULT
|
||||||
return false;
|
return false;
|
||||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||||
MOZ_ASSERT(bce->stackDepth == depth + 1);
|
MOZ_ASSERT(bce->stackDepth == depth);
|
||||||
|
|
||||||
if (!BackPatch(cx, bce, checkResult, bce->code().end(), JSOP_GOTO)) // checkResult:
|
if (!BackPatch(cx, bce, checkResult, bce->code().end(), JSOP_GOTO)) // checkResult:
|
||||||
return false;
|
return false;
|
||||||
|
@ -5629,7 +5684,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
||||||
if (!EmitAtomOp(cx, cx->names().value, JSOP_GETPROP, bce)) // VALUE
|
if (!EmitAtomOp(cx, cx->names().value, JSOP_GETPROP, bce)) // VALUE
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
MOZ_ASSERT(bce->stackDepth == depth);
|
MOZ_ASSERT(bce->stackDepth == depth - 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -5807,6 +5862,80 @@ EmitDelete(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
static bool
|
static bool
|
||||||
EmitArray(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, uint32_t count);
|
EmitArray(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, uint32_t count);
|
||||||
|
|
||||||
|
static bool
|
||||||
|
EmitSelfHostedCallFunction(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
|
{
|
||||||
|
// Special-casing of callFunction to emit bytecode that directly
|
||||||
|
// invokes the callee with the correct |this| object and arguments.
|
||||||
|
// callFunction(fun, thisArg, arg0, arg1) thus becomes:
|
||||||
|
// - emit lookup for fun
|
||||||
|
// - emit lookup for thisArg
|
||||||
|
// - emit lookups for arg0, arg1
|
||||||
|
//
|
||||||
|
// argc is set to the amount of actually emitted args and the
|
||||||
|
// emitting of args below is disabled by setting emitArgs to false.
|
||||||
|
if (pn->pn_count < 3) {
|
||||||
|
bce->reportError(pn, JSMSG_MORE_ARGS_NEEDED, "callFunction", "1", "s");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseNode *pn2 = pn->pn_head;
|
||||||
|
ParseNode *funNode = pn2->pn_next;
|
||||||
|
if (!EmitTree(cx, bce, funNode))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParseNode *thisArg = funNode->pn_next;
|
||||||
|
if (!EmitTree(cx, bce, thisArg))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bool oldEmittingForInit = bce->emittingForInit;
|
||||||
|
bce->emittingForInit = false;
|
||||||
|
|
||||||
|
for (ParseNode *argpn = thisArg->pn_next; argpn; argpn = argpn->pn_next) {
|
||||||
|
if (!EmitTree(cx, bce, argpn))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bce->emittingForInit = oldEmittingForInit;
|
||||||
|
|
||||||
|
uint32_t argc = pn->pn_count - 3;
|
||||||
|
if (EmitCall(cx, bce, pn->getOp(), argc) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
CheckTypeSet(cx, bce, pn->getOp());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
EmitSelfHostedResumeGenerator(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
|
{
|
||||||
|
// Syntax: resumeGenerator(gen, value, 'next'|'throw'|'close')
|
||||||
|
if (pn->pn_count != 4) {
|
||||||
|
bce->reportError(pn, JSMSG_MORE_ARGS_NEEDED, "resumeGenerator", "1", "s");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseNode *funNode = pn->pn_head; // The resumeGenerator node.
|
||||||
|
|
||||||
|
ParseNode *genNode = funNode->pn_next;
|
||||||
|
if (!EmitTree(cx, bce, genNode))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParseNode *valNode = genNode->pn_next;
|
||||||
|
if (!EmitTree(cx, bce, valNode))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ParseNode *kindNode = valNode->pn_next;
|
||||||
|
MOZ_ASSERT(kindNode->isKind(PNK_STRING));
|
||||||
|
uint16_t operand = GeneratorObject::getResumeKind(cx, kindNode->pn_atom);
|
||||||
|
MOZ_ASSERT(!kindNode->pn_next);
|
||||||
|
|
||||||
|
if (EmitCall(cx, bce, JSOP_RESUME, operand) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
{
|
{
|
||||||
|
@ -5835,46 +5964,21 @@ EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool emitArgs = true;
|
|
||||||
ParseNode *pn2 = pn->pn_head;
|
ParseNode *pn2 = pn->pn_head;
|
||||||
bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
|
bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
|
||||||
switch (pn2->getKind()) {
|
switch (pn2->getKind()) {
|
||||||
case PNK_NAME:
|
case PNK_NAME:
|
||||||
if (bce->emitterMode == BytecodeEmitter::SelfHosting &&
|
if (bce->emitterMode == BytecodeEmitter::SelfHosting && !spread) {
|
||||||
pn2->name() == cx->names().callFunction &&
|
// We shouldn't see foo(bar) = x in self-hosted code.
|
||||||
!spread)
|
MOZ_ASSERT(!(pn->pn_xflags & PNX_SETCALL));
|
||||||
{
|
|
||||||
/*
|
// Calls to "callFunction" or "resumeGenerator" in self-hosted code
|
||||||
* Special-casing of callFunction to emit bytecode that directly
|
// generate inline bytecode.
|
||||||
* invokes the callee with the correct |this| object and arguments.
|
if (pn2->name() == cx->names().callFunction)
|
||||||
* callFunction(fun, thisArg, arg0, arg1) thus becomes:
|
return EmitSelfHostedCallFunction(cx, bce, pn);
|
||||||
* - emit lookup for fun
|
if (pn2->name() == cx->names().resumeGenerator)
|
||||||
* - emit lookup for thisArg
|
return EmitSelfHostedResumeGenerator(cx, bce, pn);
|
||||||
* - emit lookups for arg0, arg1
|
// Fall through.
|
||||||
*
|
|
||||||
* argc is set to the amount of actually emitted args and the
|
|
||||||
* emitting of args below is disabled by setting emitArgs to false.
|
|
||||||
*/
|
|
||||||
if (pn->pn_count < 3) {
|
|
||||||
bce->reportError(pn, JSMSG_MORE_ARGS_NEEDED, "callFunction", "1", "s");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ParseNode *funNode = pn2->pn_next;
|
|
||||||
if (!EmitTree(cx, bce, funNode))
|
|
||||||
return false;
|
|
||||||
ParseNode *thisArg = funNode->pn_next;
|
|
||||||
if (!EmitTree(cx, bce, thisArg))
|
|
||||||
return false;
|
|
||||||
bool oldEmittingForInit = bce->emittingForInit;
|
|
||||||
bce->emittingForInit = false;
|
|
||||||
for (ParseNode *argpn = thisArg->pn_next; argpn; argpn = argpn->pn_next) {
|
|
||||||
if (!EmitTree(cx, bce, argpn))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bce->emittingForInit = oldEmittingForInit;
|
|
||||||
argc -= 2;
|
|
||||||
emitArgs = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (!EmitNameOp(cx, bce, pn2, callop))
|
if (!EmitNameOp(cx, bce, pn2, callop))
|
||||||
return false;
|
return false;
|
||||||
|
@ -5922,25 +6026,23 @@ EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emitArgs) {
|
/*
|
||||||
/*
|
* Emit code for each argument in order, then emit the JSOP_*CALL or
|
||||||
* Emit code for each argument in order, then emit the JSOP_*CALL or
|
* JSOP_NEW bytecode with a two-byte immediate telling how many args
|
||||||
* JSOP_NEW bytecode with a two-byte immediate telling how many args
|
* were pushed on the operand stack.
|
||||||
* were pushed on the operand stack.
|
*/
|
||||||
*/
|
bool oldEmittingForInit = bce->emittingForInit;
|
||||||
bool oldEmittingForInit = bce->emittingForInit;
|
bce->emittingForInit = false;
|
||||||
bce->emittingForInit = false;
|
if (!spread) {
|
||||||
if (!spread) {
|
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
||||||
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
if (!EmitTree(cx, bce, pn3))
|
||||||
if (!EmitTree(cx, bce, pn3))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!EmitArray(cx, bce, pn2->pn_next, argc))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bce->emittingForInit = oldEmittingForInit;
|
} else {
|
||||||
|
if (!EmitArray(cx, bce, pn2->pn_next, argc))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
bce->emittingForInit = oldEmittingForInit;
|
||||||
|
|
||||||
if (!spread) {
|
if (!spread) {
|
||||||
if (EmitCall(cx, bce, pn->getOp(), argc, pn) < 0)
|
if (EmitCall(cx, bce, pn->getOp(), argc, pn) < 0)
|
||||||
|
@ -6687,28 +6789,16 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNK_YIELD_STAR:
|
case PNK_YIELD_STAR:
|
||||||
ok = EmitYieldStar(cx, bce, pn->pn_kid);
|
ok = EmitYieldStar(cx, bce, pn->pn_left, pn->pn_right);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PNK_GENERATOR:
|
||||||
|
if (Emit1(cx, bce, JSOP_GENERATOR) < 0)
|
||||||
|
return false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNK_YIELD:
|
case PNK_YIELD:
|
||||||
MOZ_ASSERT(bce->sc->isFunctionBox());
|
ok = EmitYield(cx, bce, pn);
|
||||||
if (bce->sc->asFunctionBox()->isStarGenerator()) {
|
|
||||||
if (!EmitPrepareIteratorResult(cx, bce))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (pn->pn_kid) {
|
|
||||||
if (!EmitTree(cx, bce, pn->pn_kid))
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (bce->sc->asFunctionBox()->isStarGenerator()) {
|
|
||||||
if (!EmitFinishIteratorResult(cx, bce, false))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (Emit1(cx, bce, JSOP_YIELD) < 0)
|
|
||||||
return false;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PNK_STATEMENTLIST:
|
case PNK_STATEMENTLIST:
|
||||||
|
|
|
@ -323,6 +323,17 @@ class FullParseHandler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParseNode *newYieldExpression(uint32_t begin, ParseNode *value, ParseNode *gen,
|
||||||
|
JSOp op = JSOP_YIELD) {
|
||||||
|
TokenPos pos(begin, value ? value->pn_pos.end : begin + 1);
|
||||||
|
return new_<BinaryNode>(PNK_YIELD, op, pos, value, gen);
|
||||||
|
}
|
||||||
|
|
||||||
|
ParseNode *newYieldStarExpression(uint32_t begin, ParseNode *value, ParseNode *gen) {
|
||||||
|
TokenPos pos(begin, value->pn_pos.end);
|
||||||
|
return new_<BinaryNode>(PNK_YIELD_STAR, JSOP_NOP, pos, value, gen);
|
||||||
|
}
|
||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
ParseNode *newStatementList(unsigned blockid, const TokenPos &pos) {
|
ParseNode *newStatementList(unsigned blockid, const TokenPos &pos) {
|
||||||
|
@ -352,6 +363,31 @@ class FullParseHandler
|
||||||
list->append(stmt);
|
list->append(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool prependInitialYield(ParseNode *stmtList, ParseNode *genName) {
|
||||||
|
MOZ_ASSERT(stmtList->isKind(PNK_STATEMENTLIST));
|
||||||
|
|
||||||
|
TokenPos yieldPos(stmtList->pn_pos.begin, stmtList->pn_pos.begin + 1);
|
||||||
|
ParseNode *makeGen = new_<NullaryNode>(PNK_GENERATOR, yieldPos);
|
||||||
|
if (!makeGen)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
MOZ_ASSERT(genName->getOp() == JSOP_NAME);
|
||||||
|
genName->setOp(JSOP_SETNAME);
|
||||||
|
genName->markAsAssigned();
|
||||||
|
ParseNode *genInit = newBinary(PNK_ASSIGN, genName, makeGen);
|
||||||
|
|
||||||
|
ParseNode *initialYield = newYieldExpression(yieldPos.begin, nullptr, genInit,
|
||||||
|
JSOP_INITIALYIELD);
|
||||||
|
if (!initialYield)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
initialYield->pn_next = stmtList->pn_head;
|
||||||
|
stmtList->pn_head = initialYield;
|
||||||
|
stmtList->pn_count++;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
ParseNode *newEmptyStatement(const TokenPos &pos) {
|
ParseNode *newEmptyStatement(const TokenPos &pos) {
|
||||||
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
|
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ class UpvarCookie
|
||||||
F(FINALLY) \
|
F(FINALLY) \
|
||||||
F(THROW) \
|
F(THROW) \
|
||||||
F(DEBUGGER) \
|
F(DEBUGGER) \
|
||||||
|
F(GENERATOR) \
|
||||||
F(YIELD) \
|
F(YIELD) \
|
||||||
F(YIELD_STAR) \
|
F(YIELD_STAR) \
|
||||||
F(GENEXP) \
|
F(GENEXP) \
|
||||||
|
@ -422,6 +423,9 @@ enum ParseNodeKind
|
||||||
*
|
*
|
||||||
* PNK_LEXICALSCOPE name pn_objbox: block object in ObjectBox holder
|
* PNK_LEXICALSCOPE name pn_objbox: block object in ObjectBox holder
|
||||||
* pn_expr: block body
|
* pn_expr: block body
|
||||||
|
* PNK_GENERATOR nullary
|
||||||
|
* PNK_YIELD, binary pn_left: expr or null; pn_right: generator object
|
||||||
|
* PNK_YIELD_STAR
|
||||||
* PNK_ARRAYCOMP list pn_count: 1
|
* PNK_ARRAYCOMP list pn_count: 1
|
||||||
* pn_head: list of 1 element, which is block
|
* pn_head: list of 1 element, which is block
|
||||||
* enclosing for loop(s) and optionally
|
* enclosing for loop(s) and optionally
|
||||||
|
@ -773,8 +777,9 @@ class ParseNode
|
||||||
MOZ_ASSERT(isKind(PNK_GENEXP));
|
MOZ_ASSERT(isKind(PNK_GENEXP));
|
||||||
ParseNode *callee = this->pn_head;
|
ParseNode *callee = this->pn_head;
|
||||||
ParseNode *body = callee->pn_body;
|
ParseNode *body = callee->pn_body;
|
||||||
MOZ_ASSERT(body->isKind(PNK_LEXICALSCOPE) || body->isKind(PNK_FOR));
|
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
|
||||||
return body;
|
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) || body->last()->isKind(PNK_FOR));
|
||||||
|
return body->last();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1035,6 +1035,23 @@ Parser<ParseHandler>::functionBody(FunctionSyntaxKind kind, FunctionBodyType typ
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pc->isGenerator()) {
|
||||||
|
MOZ_ASSERT(type == StatementListBody);
|
||||||
|
Node generator = newName(context->names().dotGenerator);
|
||||||
|
if (!generator)
|
||||||
|
return null();
|
||||||
|
if (!pc->define(tokenStream, context->names().dotGenerator, generator, Definition::VAR))
|
||||||
|
return null();
|
||||||
|
|
||||||
|
generator = newName(context->names().dotGenerator);
|
||||||
|
if (!generator)
|
||||||
|
return null();
|
||||||
|
if (!noteNameUse(context->names().dotGenerator, generator))
|
||||||
|
return null();
|
||||||
|
if (!handler.prependInitialYield(pn, generator))
|
||||||
|
return null();
|
||||||
|
}
|
||||||
|
|
||||||
/* Define the 'arguments' binding if necessary. */
|
/* Define the 'arguments' binding if necessary. */
|
||||||
if (!checkFunctionArguments())
|
if (!checkFunctionArguments())
|
||||||
return null();
|
return null();
|
||||||
|
@ -5007,6 +5024,21 @@ Parser<ParseHandler>::returnStatement()
|
||||||
return pn;
|
return pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ParseHandler>
|
||||||
|
typename ParseHandler::Node
|
||||||
|
Parser<ParseHandler>::newYieldExpression(uint32_t begin, typename ParseHandler::Node expr,
|
||||||
|
bool isYieldStar)
|
||||||
|
{
|
||||||
|
Node generator = newName(context->names().dotGenerator);
|
||||||
|
if (!generator)
|
||||||
|
return null();
|
||||||
|
if (!noteNameUse(context->names().dotGenerator, generator))
|
||||||
|
return null();
|
||||||
|
if (isYieldStar)
|
||||||
|
return handler.newYieldStarExpression(begin, expr, generator);
|
||||||
|
return handler.newYieldExpression(begin, expr, generator);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename ParseHandler>
|
template <typename ParseHandler>
|
||||||
typename ParseHandler::Node
|
typename ParseHandler::Node
|
||||||
Parser<ParseHandler>::yieldExpression()
|
Parser<ParseHandler>::yieldExpression()
|
||||||
|
@ -5052,7 +5084,7 @@ Parser<ParseHandler>::yieldExpression()
|
||||||
if (!exprNode)
|
if (!exprNode)
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
return handler.newUnary(kind, JSOP_NOP, begin, exprNode);
|
return newYieldExpression(begin, exprNode, kind == PNK_YIELD_STAR);
|
||||||
}
|
}
|
||||||
|
|
||||||
case NotGenerator:
|
case NotGenerator:
|
||||||
|
@ -5110,7 +5142,7 @@ Parser<ParseHandler>::yieldExpression()
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
|
|
||||||
return handler.newUnary(PNK_YIELD, JSOP_NOP, begin, exprNode);
|
return newYieldExpression(begin, exprNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6189,9 +6221,17 @@ LegacyCompExprTransplanter::transplant(ParseNode *pn)
|
||||||
MOZ_ASSERT(!stmt || stmt != pc->topStmt);
|
MOZ_ASSERT(!stmt || stmt != pc->topStmt);
|
||||||
#endif
|
#endif
|
||||||
if (isGenexp && !dn->isOp(JSOP_CALLEE)) {
|
if (isGenexp && !dn->isOp(JSOP_CALLEE)) {
|
||||||
MOZ_ASSERT(!pc->decls().lookupFirst(atom));
|
MOZ_ASSERT_IF(atom != parser->context->names().dotGenerator,
|
||||||
|
!pc->decls().lookupFirst(atom));
|
||||||
|
|
||||||
if (dn->pn_pos < root->pn_pos) {
|
if (atom == parser->context->names().dotGenerator) {
|
||||||
|
if (dn->dn_uses == pn) {
|
||||||
|
if (!BumpStaticLevel(parser->tokenStream, dn, pc))
|
||||||
|
return false;
|
||||||
|
if (!AdjustBlockId(parser->tokenStream, dn, adjust, pc))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (dn->pn_pos < root->pn_pos) {
|
||||||
/*
|
/*
|
||||||
* The variable originally appeared to be a use of a
|
* The variable originally appeared to be a use of a
|
||||||
* definition or placeholder outside the generator, but now
|
* definition or placeholder outside the generator, but now
|
||||||
|
@ -6304,7 +6344,7 @@ LegacyComprehensionHeadBlockScopeDepth(ParseContext<ParseHandler> *pc)
|
||||||
*/
|
*/
|
||||||
template <>
|
template <>
|
||||||
ParseNode *
|
ParseNode *
|
||||||
Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyStmt, unsigned blockid,
|
Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyExpr, unsigned blockid,
|
||||||
GeneratorKind comprehensionKind,
|
GeneratorKind comprehensionKind,
|
||||||
ParseContext<FullParseHandler> *outerpc,
|
ParseContext<FullParseHandler> *outerpc,
|
||||||
unsigned innerBlockScopeDepth)
|
unsigned innerBlockScopeDepth)
|
||||||
|
@ -6368,15 +6408,15 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyStmt, unsigned
|
||||||
adjust = blockid - adjust;
|
adjust = blockid - adjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.setBeginPosition(pn, bodyStmt);
|
handler.setBeginPosition(pn, bodyExpr);
|
||||||
|
|
||||||
pnp = &pn->pn_expr;
|
pnp = &pn->pn_expr;
|
||||||
|
|
||||||
LegacyCompExprTransplanter transplanter(bodyStmt, this, outerpc, comprehensionKind, adjust);
|
LegacyCompExprTransplanter transplanter(bodyExpr, this, outerpc, comprehensionKind, adjust);
|
||||||
if (!transplanter.init())
|
if (!transplanter.init())
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
if (!transplanter.transplant(bodyStmt))
|
if (!transplanter.transplant(bodyExpr))
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
MOZ_ASSERT(pc->staticScope && pc->staticScope == pn->pn_objbox->object);
|
MOZ_ASSERT(pc->staticScope && pc->staticScope == pn->pn_objbox->object);
|
||||||
|
@ -6532,6 +6572,23 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyStmt, unsigned
|
||||||
pnp = &pn2->pn_kid2;
|
pnp = &pn2->pn_kid2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParseNode *bodyStmt;
|
||||||
|
if (isGenexp) {
|
||||||
|
ParseNode *yieldExpr = newYieldExpression(bodyExpr->pn_pos.begin, bodyExpr);
|
||||||
|
if (!yieldExpr)
|
||||||
|
return null();
|
||||||
|
yieldExpr->setInParens(true);
|
||||||
|
|
||||||
|
bodyStmt = handler.newExprStatement(yieldExpr, bodyExpr->pn_pos.end);
|
||||||
|
if (!bodyStmt)
|
||||||
|
return null();
|
||||||
|
} else {
|
||||||
|
bodyStmt = handler.newUnary(PNK_ARRAYPUSH, JSOP_ARRAYPUSH,
|
||||||
|
bodyExpr->pn_pos.begin, bodyExpr);
|
||||||
|
if (!bodyStmt)
|
||||||
|
return null();
|
||||||
|
}
|
||||||
|
|
||||||
*pnp = bodyStmt;
|
*pnp = bodyStmt;
|
||||||
|
|
||||||
pc->topStmt->innerBlockScopeDepth += innerBlockScopeDepth;
|
pc->topStmt->innerBlockScopeDepth += innerBlockScopeDepth;
|
||||||
|
@ -6568,12 +6625,7 @@ Parser<FullParseHandler>::legacyArrayComprehension(ParseNode *array)
|
||||||
array->pn_tail = &array->pn_head;
|
array->pn_tail = &array->pn_head;
|
||||||
*array->pn_tail = nullptr;
|
*array->pn_tail = nullptr;
|
||||||
|
|
||||||
ParseNode *arrayPush = handler.newUnary(PNK_ARRAYPUSH, JSOP_ARRAYPUSH,
|
ParseNode *comp = legacyComprehensionTail(bodyExpr, array->pn_blockid, NotGenerator,
|
||||||
bodyExpr->pn_pos.begin, bodyExpr);
|
|
||||||
if (!arrayPush)
|
|
||||||
return null();
|
|
||||||
|
|
||||||
ParseNode *comp = legacyComprehensionTail(arrayPush, array->pn_blockid, NotGenerator,
|
|
||||||
nullptr, LegacyComprehensionHeadBlockScopeDepth(pc));
|
nullptr, LegacyComprehensionHeadBlockScopeDepth(pc));
|
||||||
if (!comp)
|
if (!comp)
|
||||||
return null();
|
return null();
|
||||||
|
@ -6596,10 +6648,10 @@ Parser<SyntaxParseHandler>::legacyArrayComprehension(Node array)
|
||||||
template <typename ParseHandler>
|
template <typename ParseHandler>
|
||||||
typename ParseHandler::Node
|
typename ParseHandler::Node
|
||||||
Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKind,
|
Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKind,
|
||||||
unsigned begin, Node innerStmt)
|
unsigned begin, Node innerExpr)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(comprehensionKind == LegacyGenerator || comprehensionKind == StarGenerator);
|
MOZ_ASSERT(comprehensionKind == LegacyGenerator || comprehensionKind == StarGenerator);
|
||||||
MOZ_ASSERT(!!innerStmt == (comprehensionKind == LegacyGenerator));
|
MOZ_ASSERT(!!innerExpr == (comprehensionKind == LegacyGenerator));
|
||||||
|
|
||||||
Node genfn = handler.newFunctionDefinition();
|
Node genfn = handler.newFunctionDefinition();
|
||||||
if (!genfn)
|
if (!genfn)
|
||||||
|
@ -6650,29 +6702,47 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
|
||||||
genFunbox->inGenexpLambda = true;
|
genFunbox->inGenexpLambda = true;
|
||||||
handler.setBlockId(genfn, genpc.bodyid);
|
handler.setBlockId(genfn, genpc.bodyid);
|
||||||
|
|
||||||
Node body;
|
Node generator = newName(context->names().dotGenerator);
|
||||||
|
if (!generator)
|
||||||
|
return null();
|
||||||
|
if (!pc->define(tokenStream, context->names().dotGenerator, generator, Definition::VAR))
|
||||||
|
return null();
|
||||||
|
|
||||||
|
Node body = handler.newStatementList(pc->blockid(), TokenPos(begin, pos().end));
|
||||||
|
if (!body)
|
||||||
|
return null();
|
||||||
|
|
||||||
|
Node comp;
|
||||||
if (comprehensionKind == StarGenerator) {
|
if (comprehensionKind == StarGenerator) {
|
||||||
body = comprehension(StarGenerator);
|
comp = comprehension(StarGenerator);
|
||||||
if (!body)
|
if (!comp)
|
||||||
return null();
|
return null();
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(comprehensionKind == LegacyGenerator);
|
MOZ_ASSERT(comprehensionKind == LegacyGenerator);
|
||||||
body = legacyComprehensionTail(innerStmt, outerpc->blockid(), LegacyGenerator,
|
comp = legacyComprehensionTail(innerExpr, outerpc->blockid(), LegacyGenerator,
|
||||||
outerpc, LegacyComprehensionHeadBlockScopeDepth(outerpc));
|
outerpc, LegacyComprehensionHeadBlockScopeDepth(outerpc));
|
||||||
if (!body)
|
if (!comp)
|
||||||
return null();
|
return null();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comprehensionKind == StarGenerator)
|
if (comprehensionKind == StarGenerator)
|
||||||
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
|
MUST_MATCH_TOKEN(TOK_RP, JSMSG_PAREN_IN_PAREN);
|
||||||
|
|
||||||
handler.setBeginPosition(body, begin);
|
handler.setBeginPosition(comp, begin);
|
||||||
|
handler.setEndPosition(comp, pos().end);
|
||||||
|
handler.addStatementToList(body, comp, pc);
|
||||||
handler.setEndPosition(body, pos().end);
|
handler.setEndPosition(body, pos().end);
|
||||||
|
|
||||||
handler.setBeginPosition(genfn, begin);
|
handler.setBeginPosition(genfn, begin);
|
||||||
handler.setEndPosition(genfn, pos().end);
|
handler.setEndPosition(genfn, pos().end);
|
||||||
|
|
||||||
|
generator = newName(context->names().dotGenerator);
|
||||||
|
if (!generator)
|
||||||
|
return null();
|
||||||
|
if (!noteNameUse(context->names().dotGenerator, generator))
|
||||||
|
return null();
|
||||||
|
if (!handler.prependInitialYield(body, generator))
|
||||||
|
return null();
|
||||||
|
|
||||||
// Note that if we ever start syntax-parsing generators, we will also
|
// Note that if we ever start syntax-parsing generators, we will also
|
||||||
// need to propagate the closed-over variable set to the inner
|
// need to propagate the closed-over variable set to the inner
|
||||||
// lazyscript, as in finishFunctionDefinition.
|
// lazyscript, as in finishFunctionDefinition.
|
||||||
|
@ -6709,19 +6779,8 @@ Parser<FullParseHandler>::legacyGeneratorExpr(ParseNode *expr)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
|
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_FOR));
|
||||||
|
|
||||||
/* Create a |yield| node for |kid|. */
|
|
||||||
ParseNode *yieldExpr = handler.newUnary(PNK_YIELD, JSOP_NOP, expr->pn_pos.begin, expr);
|
|
||||||
if (!yieldExpr)
|
|
||||||
return null();
|
|
||||||
yieldExpr->setInParens(true);
|
|
||||||
|
|
||||||
// A statement to wrap the yield expression.
|
|
||||||
ParseNode *yieldStmt = handler.newExprStatement(yieldExpr, expr->pn_pos.end);
|
|
||||||
if (!yieldStmt)
|
|
||||||
return null();
|
|
||||||
|
|
||||||
/* Make a new node for the desugared generator function. */
|
/* Make a new node for the desugared generator function. */
|
||||||
ParseNode *genfn = generatorComprehensionLambda(LegacyGenerator, expr->pn_pos.begin, yieldStmt);
|
ParseNode *genfn = generatorComprehensionLambda(LegacyGenerator, expr->pn_pos.begin, expr);
|
||||||
if (!genfn)
|
if (!genfn)
|
||||||
return null();
|
return null();
|
||||||
|
|
||||||
|
@ -6871,7 +6930,7 @@ Parser<ParseHandler>::comprehensionTail(GeneratorKind comprehensionKind)
|
||||||
return handler.newUnary(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, begin, bodyExpr);
|
return handler.newUnary(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, begin, bodyExpr);
|
||||||
|
|
||||||
MOZ_ASSERT(comprehensionKind == StarGenerator);
|
MOZ_ASSERT(comprehensionKind == StarGenerator);
|
||||||
Node yieldExpr = handler.newUnary(PNK_YIELD, JSOP_NOP, begin, bodyExpr);
|
Node yieldExpr = newYieldExpression(begin, bodyExpr);
|
||||||
if (!yieldExpr)
|
if (!yieldExpr)
|
||||||
return null();
|
return null();
|
||||||
handler.setInParens(yieldExpr);
|
handler.setInParens(yieldExpr);
|
||||||
|
|
|
@ -464,6 +464,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
||||||
bool addExprAndGetNextTemplStrToken(Node nodeList, TokenKind &tt);
|
bool addExprAndGetNextTemplStrToken(Node nodeList, TokenKind &tt);
|
||||||
|
|
||||||
inline Node newName(PropertyName *name);
|
inline Node newName(PropertyName *name);
|
||||||
|
inline Node newYieldExpression(uint32_t begin, Node expr, bool isYieldStar = false);
|
||||||
|
|
||||||
inline bool abortIfSyntaxParser();
|
inline bool abortIfSyntaxParser();
|
||||||
|
|
||||||
|
|
|
@ -135,11 +135,14 @@ class SyntaxParseHandler
|
||||||
bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
bool addPrototypeMutation(Node literal, uint32_t begin, Node expr) { return true; }
|
||||||
bool addPropertyDefinition(Node literal, Node name, Node expr, bool isShorthand = false) { return true; }
|
bool addPropertyDefinition(Node literal, Node name, Node expr, bool isShorthand = false) { return true; }
|
||||||
bool addMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
bool addMethodDefinition(Node literal, Node name, Node fn, JSOp op) { return true; }
|
||||||
|
Node newYieldExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
|
||||||
|
Node newYieldStarExpression(uint32_t begin, Node value, Node gen) { return NodeGeneric; }
|
||||||
|
|
||||||
// Statements
|
// Statements
|
||||||
|
|
||||||
Node newStatementList(unsigned blockid, const TokenPos &pos) { return NodeGeneric; }
|
Node newStatementList(unsigned blockid, const TokenPos &pos) { return NodeGeneric; }
|
||||||
void addStatementToList(Node list, Node stmt, ParseContext<SyntaxParseHandler> *pc) {}
|
void addStatementToList(Node list, Node stmt, ParseContext<SyntaxParseHandler> *pc) {}
|
||||||
|
bool prependInitialYield(Node stmtList, Node gen) { return true; }
|
||||||
Node newEmptyStatement(const TokenPos &pos) { return NodeGeneric; }
|
Node newEmptyStatement(const TokenPos &pos) { return NodeGeneric; }
|
||||||
|
|
||||||
Node newExprStatement(Node expr, uint32_t end) {
|
Node newExprStatement(Node expr, uint32_t end) {
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* - writes to object properties
|
* - writes to object properties
|
||||||
* - writes to array slots
|
* - writes to array slots
|
||||||
* - writes to fields like JSObject::shape_ that we trace through
|
* - writes to fields like JSObject::shape_ that we trace through
|
||||||
* - writes to fields in private data, like JSGenerator::obj
|
* - writes to fields in private data
|
||||||
* - writes to non-markable fields like JSObject::private that point to
|
* - writes to non-markable fields like JSObject::private that point to
|
||||||
* markable data
|
* markable data
|
||||||
* The last category is the trickiest. Even though the private pointers does not
|
* The last category is the trickiest. Even though the private pointers does not
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
// |jit-test| error: StopIteration
|
||||||
// Returning {throw:} from an onPop handler when yielding works and
|
// Returning {throw:} from an onPop handler when yielding works and
|
||||||
// does not close the generator-iterator.
|
// does closes the generator-iterator.
|
||||||
|
|
||||||
load(libdir + "asserts.js");
|
load(libdir + "asserts.js");
|
||||||
|
|
||||||
|
@ -17,4 +18,4 @@ var rv = gw.evalInGlobal("it.next();");
|
||||||
assertEq(rv.throw, "fit");
|
assertEq(rv.throw, "fit");
|
||||||
|
|
||||||
dbg.enabled = false;
|
dbg.enabled = false;
|
||||||
assertEq(g.it.next(), 1);
|
g.it.next();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Returning {throw:} from an onPop handler when yielding works and
|
// Returning {throw:} from an onPop handler when yielding works and
|
||||||
// does not close the generator-iterator.
|
// closes the generator-iterator.
|
||||||
|
|
||||||
load(libdir + "iteration.js");
|
load(libdir + "iteration.js");
|
||||||
|
|
||||||
|
@ -17,4 +17,4 @@ var rv = gw.evalInGlobal("it.next();");
|
||||||
assertEq(rv.throw, "fit");
|
assertEq(rv.throw, "fit");
|
||||||
|
|
||||||
dbg.enabled = false;
|
dbg.enabled = false;
|
||||||
assertIteratorNext(g.it, 1);
|
assertIteratorDone(g.it);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// |jit-test| error: already executing generator
|
||||||
// Forced return from a generator frame.
|
// Forced return from a generator frame.
|
||||||
|
|
||||||
var g = newGlobal();
|
var g = newGlobal();
|
||||||
|
@ -10,5 +11,9 @@ function gen() {
|
||||||
debugger; // Force return here. The value is ignored.
|
debugger; // Force return here. The value is ignored.
|
||||||
yield '2';
|
yield '2';
|
||||||
}
|
}
|
||||||
var x = [v for (v in gen())];
|
|
||||||
assertEq(x.join(","), "1");
|
var iter = gen();
|
||||||
|
assertEq(iter.next(), "1");
|
||||||
|
assertEq(iter.next(), "!");
|
||||||
|
iter.next();
|
||||||
|
assertEq(0, 1);
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// |jit-test| error: already executing generator
|
||||||
// Forced return from a star generator frame.
|
// Forced return from a star generator frame.
|
||||||
|
|
||||||
load(libdir + 'asserts.js')
|
load(libdir + 'asserts.js')
|
||||||
|
@ -16,4 +17,5 @@ function* gen() {
|
||||||
var iter = gen();
|
var iter = gen();
|
||||||
assertIteratorNext(iter, '1');
|
assertIteratorNext(iter, '1');
|
||||||
assertEq(iter.next(), '!');
|
assertEq(iter.next(), '!');
|
||||||
assertIteratorDone(iter);
|
iter.next();
|
||||||
|
assertEq(0, 1);
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
// When a generator function throws, the generator is closed.
|
||||||
|
|
||||||
|
load(libdir + "asserts.js");
|
||||||
|
load(libdir + "iteration.js");
|
||||||
|
|
||||||
|
// Star generator, next() throws.
|
||||||
|
function *g() {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
throw 3;
|
||||||
|
yield 4;
|
||||||
|
}
|
||||||
|
var i = g();
|
||||||
|
assertIteratorNext(i, 1);
|
||||||
|
assertIteratorNext(i, 2);
|
||||||
|
assertThrowsValue(() => i.next(), 3);
|
||||||
|
assertIteratorDone(i);
|
||||||
|
assertIteratorDone(i);
|
||||||
|
|
||||||
|
// Star generator, throw() throws.
|
||||||
|
function *h() {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
}
|
||||||
|
var i = h();
|
||||||
|
assertIteratorNext(i, 1);
|
||||||
|
assertThrowsValue(() => i.throw(4), 4);
|
||||||
|
assertIteratorDone(i);
|
||||||
|
|
||||||
|
// Legacy generator, throw() throws.
|
||||||
|
function l1() {
|
||||||
|
yield 1;
|
||||||
|
yield 2;
|
||||||
|
}
|
||||||
|
var i = l1();
|
||||||
|
assertEq(i.next(), 1);
|
||||||
|
assertThrowsValue(() => i.throw(5), 5);
|
||||||
|
assertThrowsInstanceOf(() => i.next(), StopIteration);
|
||||||
|
|
||||||
|
// Legacy generator, next() throws.
|
||||||
|
function l2() {
|
||||||
|
yield 1;
|
||||||
|
throw 6;
|
||||||
|
yield 2;
|
||||||
|
}
|
||||||
|
var i = l2();
|
||||||
|
assertEq(i.next(), 1);
|
||||||
|
assertThrowsValue(() => i.next(), 6);
|
||||||
|
assertThrowsInstanceOf(() => i.next(), StopIteration);
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Generator methods work transparently on CrossCompartmentWrappers.
|
||||||
|
|
||||||
|
load(libdir + "asserts.js");
|
||||||
|
load(libdir + "iteration.js");
|
||||||
|
|
||||||
|
function gen() { yield 1; yield 2; }
|
||||||
|
var it = gen();
|
||||||
|
|
||||||
|
var g = newGlobal();
|
||||||
|
g.eval("function gen2() { yield 3; yield 4; }; var it2 = gen2();");
|
||||||
|
|
||||||
|
// LegacyGenerator.next
|
||||||
|
assertEq(it.next.call(g.it2), 3);
|
||||||
|
|
||||||
|
// LegacyGenerator.throw
|
||||||
|
assertThrowsValue(() => it.throw.call(g.it2, 7), 7);
|
||||||
|
|
||||||
|
function *gen3() { yield 1; yield 2; }
|
||||||
|
it = gen3();
|
||||||
|
g.eval("function *gen4() { yield 5; yield 6; }; var it4 = gen4();");
|
||||||
|
|
||||||
|
// StarGenerator.next
|
||||||
|
assertIteratorResult(it.next.call(g.it4), 5, false)
|
||||||
|
|
||||||
|
// StarGenerator.throw
|
||||||
|
assertThrowsValue(() => it.throw.call(g.it4, 8), 8);
|
||||||
|
|
||||||
|
// Other objects should throw.
|
||||||
|
try {
|
||||||
|
it.next.call([]);
|
||||||
|
assertEq(0, 1);
|
||||||
|
} catch (e) {
|
||||||
|
assertEq(e.toString().contains("called on incompatible Array"), true);
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ const { value: frame } = (function iife1() {
|
||||||
|
|
||||||
assertEq(frame.functionDisplayName, "iife2");
|
assertEq(frame.functionDisplayName, "iife2");
|
||||||
assertEq(frame.parent.functionDisplayName, "generator");
|
assertEq(frame.parent.functionDisplayName, "generator");
|
||||||
assertEq(frame.parent.parent.functionDisplayName, "iife1");
|
assertEq(frame.parent.parent.functionDisplayName, "next");
|
||||||
assertEq(frame.parent.parent.parent.functionDisplayName, null);
|
assertEq(frame.parent.parent.parent.functionDisplayName, "iife1");
|
||||||
assertEq(frame.parent.parent.parent.parent, null);
|
assertEq(frame.parent.parent.parent.parent.functionDisplayName, null);
|
||||||
|
assertEq(frame.parent.parent.parent.parent.parent, null);
|
||||||
|
|
|
@ -49,7 +49,9 @@ jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
|
||||||
MOZ_ASSERT(IsBaselineEnabled(cx));
|
MOZ_ASSERT(IsBaselineEnabled(cx));
|
||||||
|
|
||||||
*bailoutInfo = nullptr;
|
*bailoutInfo = nullptr;
|
||||||
uint32_t retval = BailoutIonToBaseline(cx, bailoutData.activation(), iter, false, bailoutInfo);
|
bool poppedLastSPSFrame = false;
|
||||||
|
uint32_t retval = BailoutIonToBaseline(cx, bailoutData.activation(), iter, false, bailoutInfo,
|
||||||
|
/* excInfo = */ nullptr, &poppedLastSPSFrame);
|
||||||
MOZ_ASSERT(retval == BAILOUT_RETURN_OK ||
|
MOZ_ASSERT(retval == BAILOUT_RETURN_OK ||
|
||||||
retval == BAILOUT_RETURN_FATAL_ERROR ||
|
retval == BAILOUT_RETURN_FATAL_ERROR ||
|
||||||
retval == BAILOUT_RETURN_OVERRECURSED);
|
retval == BAILOUT_RETURN_OVERRECURSED);
|
||||||
|
@ -68,7 +70,8 @@ jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
|
||||||
// pseudostack frame would not have been pushed in the first
|
// pseudostack frame would not have been pushed in the first
|
||||||
// place, so don't pop anything in that case.
|
// place, so don't pop anything in that case.
|
||||||
bool popSPSFrame = iter.ionScript()->hasSPSInstrumentation() &&
|
bool popSPSFrame = iter.ionScript()->hasSPSInstrumentation() &&
|
||||||
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck);
|
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck) &&
|
||||||
|
!poppedLastSPSFrame;
|
||||||
JSScript *script = iter.script();
|
JSScript *script = iter.script();
|
||||||
probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
|
probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
|
||||||
|
|
||||||
|
@ -105,7 +108,9 @@ jit::InvalidationBailout(InvalidationBailoutStack *sp, size_t *frameSizeOut,
|
||||||
MOZ_ASSERT(IsBaselineEnabled(cx));
|
MOZ_ASSERT(IsBaselineEnabled(cx));
|
||||||
|
|
||||||
*bailoutInfo = nullptr;
|
*bailoutInfo = nullptr;
|
||||||
uint32_t retval = BailoutIonToBaseline(cx, bailoutData.activation(), iter, true, bailoutInfo);
|
bool poppedLastSPSFrame = false;
|
||||||
|
uint32_t retval = BailoutIonToBaseline(cx, bailoutData.activation(), iter, true, bailoutInfo,
|
||||||
|
/* excInfo = */ nullptr, &poppedLastSPSFrame);
|
||||||
MOZ_ASSERT(retval == BAILOUT_RETURN_OK ||
|
MOZ_ASSERT(retval == BAILOUT_RETURN_OK ||
|
||||||
retval == BAILOUT_RETURN_FATAL_ERROR ||
|
retval == BAILOUT_RETURN_FATAL_ERROR ||
|
||||||
retval == BAILOUT_RETURN_OVERRECURSED);
|
retval == BAILOUT_RETURN_OVERRECURSED);
|
||||||
|
@ -124,7 +129,8 @@ jit::InvalidationBailout(InvalidationBailoutStack *sp, size_t *frameSizeOut,
|
||||||
// pseudostack frame would not have been pushed in the first
|
// pseudostack frame would not have been pushed in the first
|
||||||
// place, so don't pop anything in that case.
|
// place, so don't pop anything in that case.
|
||||||
bool popSPSFrame = iter.ionScript()->hasSPSInstrumentation() &&
|
bool popSPSFrame = iter.ionScript()->hasSPSInstrumentation() &&
|
||||||
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck);
|
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck) &&
|
||||||
|
!poppedLastSPSFrame;
|
||||||
JSScript *script = iter.script();
|
JSScript *script = iter.script();
|
||||||
probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
|
probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
|
||||||
|
|
||||||
|
@ -180,7 +186,9 @@ jit::ExceptionHandlerBailout(JSContext *cx, const InlineFrameIterator &frame,
|
||||||
JitFrameIterator iter(jitActivations);
|
JitFrameIterator iter(jitActivations);
|
||||||
|
|
||||||
BaselineBailoutInfo *bailoutInfo = nullptr;
|
BaselineBailoutInfo *bailoutInfo = nullptr;
|
||||||
uint32_t retval = BailoutIonToBaseline(cx, bailoutData.activation(), iter, true, &bailoutInfo, &excInfo);
|
bool poppedLastSPSFrame = false;
|
||||||
|
uint32_t retval = BailoutIonToBaseline(cx, bailoutData.activation(), iter, true,
|
||||||
|
&bailoutInfo, &excInfo, &poppedLastSPSFrame);
|
||||||
|
|
||||||
if (retval == BAILOUT_RETURN_OK) {
|
if (retval == BAILOUT_RETURN_OK) {
|
||||||
MOZ_ASSERT(bailoutInfo);
|
MOZ_ASSERT(bailoutInfo);
|
||||||
|
|
|
@ -515,9 +515,12 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||||
HandleFunction fun, HandleScript script, IonScript *ionScript,
|
HandleFunction fun, HandleScript script, IonScript *ionScript,
|
||||||
SnapshotIterator &iter, bool invalidate, BaselineStackBuilder &builder,
|
SnapshotIterator &iter, bool invalidate, BaselineStackBuilder &builder,
|
||||||
AutoValueVector &startFrameFormals, MutableHandleFunction nextCallee,
|
AutoValueVector &startFrameFormals, MutableHandleFunction nextCallee,
|
||||||
jsbytecode **callPC, const ExceptionBailoutInfo *excInfo)
|
jsbytecode **callPC, const ExceptionBailoutInfo *excInfo,
|
||||||
|
bool *poppedLastSPSFrameOut)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(script->hasBaselineScript());
|
MOZ_ASSERT(script->hasBaselineScript());
|
||||||
|
MOZ_ASSERT(poppedLastSPSFrameOut);
|
||||||
|
MOZ_ASSERT(!*poppedLastSPSFrameOut);
|
||||||
|
|
||||||
// Are we catching an exception?
|
// Are we catching an exception?
|
||||||
bool catchingException = excInfo && excInfo->catchingException();
|
bool catchingException = excInfo && excInfo->catchingException();
|
||||||
|
@ -1035,6 +1038,11 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||||
JitSpew(JitSpew_BaselineBailouts,
|
JitSpew(JitSpew_BaselineBailouts,
|
||||||
" Popping SPS entry for outermost frame");
|
" Popping SPS entry for outermost frame");
|
||||||
cx->runtime()->spsProfiler.exit(script, fun);
|
cx->runtime()->spsProfiler.exit(script, fun);
|
||||||
|
|
||||||
|
// Notify caller that the last SPS frame was popped, so not
|
||||||
|
// to do it again.
|
||||||
|
if (poppedLastSPSFrameOut)
|
||||||
|
*poppedLastSPSFrameOut = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1291,7 +1299,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
||||||
uint32_t
|
uint32_t
|
||||||
jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
|
jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
|
||||||
bool invalidate, BaselineBailoutInfo **bailoutInfo,
|
bool invalidate, BaselineBailoutInfo **bailoutInfo,
|
||||||
const ExceptionBailoutInfo *excInfo)
|
const ExceptionBailoutInfo *excInfo, bool *poppedLastSPSFrameOut)
|
||||||
{
|
{
|
||||||
// The Baseline frames we will reconstruct on the heap are not rooted, so GC
|
// The Baseline frames we will reconstruct on the heap are not rooted, so GC
|
||||||
// must be suppressed here.
|
// must be suppressed here.
|
||||||
|
@ -1300,6 +1308,9 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIter
|
||||||
MOZ_ASSERT(bailoutInfo != nullptr);
|
MOZ_ASSERT(bailoutInfo != nullptr);
|
||||||
MOZ_ASSERT(*bailoutInfo == nullptr);
|
MOZ_ASSERT(*bailoutInfo == nullptr);
|
||||||
|
|
||||||
|
MOZ_ASSERT(poppedLastSPSFrameOut);
|
||||||
|
MOZ_ASSERT(!*poppedLastSPSFrameOut);
|
||||||
|
|
||||||
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
|
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
|
||||||
TraceLogStopEvent(logger, TraceLogger::IonMonkey);
|
TraceLogStopEvent(logger, TraceLogger::IonMonkey);
|
||||||
TraceLogStartEvent(logger, TraceLogger::Baseline);
|
TraceLogStartEvent(logger, TraceLogger::Baseline);
|
||||||
|
@ -1429,7 +1440,8 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIter
|
||||||
RootedFunction nextCallee(cx, nullptr);
|
RootedFunction nextCallee(cx, nullptr);
|
||||||
if (!InitFromBailout(cx, caller, callerPC, fun, scr, iter.ionScript(),
|
if (!InitFromBailout(cx, caller, callerPC, fun, scr, iter.ionScript(),
|
||||||
snapIter, invalidate, builder, startFrameFormals,
|
snapIter, invalidate, builder, startFrameFormals,
|
||||||
&nextCallee, &callPC, passExcInfo ? excInfo : nullptr))
|
&nextCallee, &callPC, passExcInfo ? excInfo : nullptr,
|
||||||
|
poppedLastSPSFrameOut))
|
||||||
{
|
{
|
||||||
return BAILOUT_RETURN_FATAL_ERROR;
|
return BAILOUT_RETURN_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
|
@ -323,16 +323,13 @@ jit::CanEnterBaselineMethod(JSContext *cx, RunState &state)
|
||||||
|
|
||||||
if (!state.maybeCreateThisForConstructor(cx))
|
if (!state.maybeCreateThisForConstructor(cx))
|
||||||
return Method_Skipped;
|
return Method_Skipped;
|
||||||
} else if (state.isExecute()) {
|
} else {
|
||||||
|
MOZ_ASSERT(state.isExecute());
|
||||||
ExecuteType type = state.asExecute()->type();
|
ExecuteType type = state.asExecute()->type();
|
||||||
if (type == EXECUTE_DEBUG || type == EXECUTE_DEBUG_GLOBAL) {
|
if (type == EXECUTE_DEBUG || type == EXECUTE_DEBUG_GLOBAL) {
|
||||||
JitSpew(JitSpew_BaselineAbort, "debugger frame");
|
JitSpew(JitSpew_BaselineAbort, "debugger frame");
|
||||||
return Method_CantCompile;
|
return Method_CantCompile;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
MOZ_ASSERT(state.isGenerator());
|
|
||||||
JitSpew(JitSpew_BaselineAbort, "generator frame");
|
|
||||||
return Method_CantCompile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedScript script(cx, state.script());
|
RootedScript script(cx, state.script());
|
||||||
|
|
|
@ -439,7 +439,8 @@ struct BaselineBailoutInfo
|
||||||
uint32_t
|
uint32_t
|
||||||
BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
|
BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
|
||||||
bool invalidate, BaselineBailoutInfo **bailoutInfo,
|
bool invalidate, BaselineBailoutInfo **bailoutInfo,
|
||||||
const ExceptionBailoutInfo *exceptionInfo = nullptr);
|
const ExceptionBailoutInfo *exceptionInfo,
|
||||||
|
bool *poppedLastSPSFrame);
|
||||||
|
|
||||||
// Mark baseline scripts on the stack as active, so that they are not discarded
|
// Mark baseline scripts on the stack as active, so that they are not discarded
|
||||||
// during GC.
|
// during GC.
|
||||||
|
|
|
@ -2401,10 +2401,6 @@ jit::CanEnter(JSContext *cx, RunState &state)
|
||||||
|
|
||||||
if (!state.maybeCreateThisForConstructor(cx))
|
if (!state.maybeCreateThisForConstructor(cx))
|
||||||
return Method_Skipped;
|
return Method_Skipped;
|
||||||
} else if (state.isGenerator()) {
|
|
||||||
JitSpew(JitSpew_IonAbort, "generator frame");
|
|
||||||
ForbidCompilation(cx, script);
|
|
||||||
return Method_CantCompile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If --ion-eager is used, compile with Baseline first, so that we
|
// If --ion-eager is used, compile with Baseline first, so that we
|
||||||
|
|
299
js/src/jsapi.cpp
299
js/src/jsapi.cpp
|
@ -2781,7 +2781,8 @@ JS_AlreadyHasOwnUCProperty(JSContext *cx, HandleObject obj, const char16_t *name
|
||||||
return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
|
return JS_AlreadyHasOwnPropertyById(cx, obj, id, foundp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
|
/*
|
||||||
|
* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
|
||||||
* function arguments.
|
* function arguments.
|
||||||
*/
|
*/
|
||||||
static JSPropertyOpWrapper
|
static JSPropertyOpWrapper
|
||||||
|
@ -2825,8 +2826,6 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val
|
||||||
MOZ_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
MOZ_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
||||||
JSFunction::Flags zeroFlags = JSAPIToJSFunctionFlags(0);
|
JSFunction::Flags zeroFlags = JSAPIToJSFunctionFlags(0);
|
||||||
|
|
||||||
// We can't just use JS_NewFunctionById here because it assumes a
|
|
||||||
// string id.
|
|
||||||
RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : nullptr);
|
RootedAtom atom(cx, JSID_IS_ATOM(id) ? JSID_TO_ATOM(id) : nullptr);
|
||||||
attrs &= ~JSPROP_NATIVE_ACCESSORS;
|
attrs &= ~JSPROP_NATIVE_ACCESSORS;
|
||||||
if (getter) {
|
if (getter) {
|
||||||
|
@ -2863,12 +2862,12 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val
|
||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, obj, id, value,
|
assertSameCompartment(cx, obj, id, value,
|
||||||
(attrs & JSPROP_GETTER)
|
(attrs & JSPROP_GETTER)
|
||||||
? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
|
? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
|
||||||
: nullptr,
|
: nullptr,
|
||||||
(attrs & JSPROP_SETTER)
|
(attrs & JSPROP_SETTER)
|
||||||
? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
|
? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
|
||||||
: nullptr);
|
: nullptr);
|
||||||
|
|
||||||
return JSObject::defineGeneric(cx, obj, id, value, getter, setter, attrs);
|
return JSObject::defineGeneric(cx, obj, id, value, getter, setter, attrs);
|
||||||
}
|
}
|
||||||
|
@ -3012,30 +3011,22 @@ DefineProperty(JSContext *cx, HandleObject obj, const char *name, HandleValue va
|
||||||
return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags);
|
return DefinePropertyById(cx, obj, id, value, getter, setter, attrs, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
DefineSelfHostedProperty(JSContext *cx,
|
DefineSelfHostedProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||||
HandleObject obj,
|
const char *getterName, const char *setterName,
|
||||||
const char *name,
|
unsigned attrs, unsigned flags)
|
||||||
const char *getterName,
|
|
||||||
const char *setterName,
|
|
||||||
unsigned attrs,
|
|
||||||
unsigned flags)
|
|
||||||
{
|
{
|
||||||
RootedAtom nameAtom(cx, Atomize(cx, name, strlen(name)));
|
|
||||||
if (!nameAtom)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
RootedAtom getterNameAtom(cx, Atomize(cx, getterName, strlen(getterName)));
|
RootedAtom getterNameAtom(cx, Atomize(cx, getterName, strlen(getterName)));
|
||||||
if (!getterNameAtom)
|
if (!getterNameAtom)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RootedValue getterValue(cx);
|
RootedAtom name(cx, IdToFunctionName(cx, id));
|
||||||
if (!cx->global()->getSelfHostedFunction(cx, getterNameAtom, nameAtom,
|
if (!name)
|
||||||
0, &getterValue))
|
return false;
|
||||||
{
|
|
||||||
|
RootedValue getterValue(cx);
|
||||||
|
if (!cx->global()->getSelfHostedFunction(cx, getterNameAtom, name, 0, &getterValue))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
MOZ_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
|
MOZ_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
|
||||||
RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
|
RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
|
||||||
JSPropertyOp getterOp = JS_DATA_TO_FUNC_PTR(PropertyOp, getterFunc.get());
|
JSPropertyOp getterOp = JS_DATA_TO_FUNC_PTR(PropertyOp, getterFunc.get());
|
||||||
|
@ -3047,19 +3038,16 @@ DefineSelfHostedProperty(JSContext *cx,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RootedValue setterValue(cx);
|
RootedValue setterValue(cx);
|
||||||
if (!cx->global()->getSelfHostedFunction(cx, setterNameAtom, nameAtom,
|
if (!cx->global()->getSelfHostedFunction(cx, setterNameAtom, name, 0, &setterValue))
|
||||||
0, &setterValue))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
MOZ_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
|
MOZ_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
|
||||||
setterFunc = &getterValue.toObject().as<JSFunction>();
|
setterFunc = &getterValue.toObject().as<JSFunction>();
|
||||||
}
|
}
|
||||||
JSStrictPropertyOp setterOp = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setterFunc.get());
|
JSStrictPropertyOp setterOp = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setterFunc.get());
|
||||||
|
|
||||||
return DefineProperty(cx, obj, name, JS::UndefinedHandleValue,
|
return DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue,
|
||||||
GetterWrapper(getterOp), SetterWrapper(setterOp),
|
GetterWrapper(getterOp), SetterWrapper(setterOp),
|
||||||
attrs, flags);
|
attrs, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
|
@ -3256,37 +3244,81 @@ JS_DefineConstIntegers(JSContext *cx, HandleObject obj, const JSConstIntegerSpec
|
||||||
return DefineConstScalar(cx, obj, cis);
|
return DefineConstScalar(cx, obj, cis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JS::SymbolCode
|
||||||
|
PropertySpecNameToSymbolCode(const char *name)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(JS::PropertySpecNameIsSymbol(name));
|
||||||
|
uintptr_t u = reinterpret_cast<uintptr_t>(name);
|
||||||
|
return JS::SymbolCode(u - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
PropertySpecNameToId(JSContext *cx, const char *name, MutableHandleId id,
|
||||||
|
js::InternBehavior ib = js::DoNotInternAtom)
|
||||||
|
{
|
||||||
|
if (JS::PropertySpecNameIsSymbol(name)) {
|
||||||
|
JS::SymbolCode which = PropertySpecNameToSymbolCode(name);
|
||||||
|
id.set(SYMBOL_TO_JSID(cx->wellKnownSymbols().get(which)));
|
||||||
|
} else {
|
||||||
|
JSAtom *atom = Atomize(cx, name, strlen(name), ib);
|
||||||
|
if (!atom)
|
||||||
|
return false;
|
||||||
|
id.set(AtomToId(atom));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(bool)
|
||||||
|
JS::PropertySpecNameToPermanentId(JSContext *cx, const char *name, jsid *idp)
|
||||||
|
{
|
||||||
|
// We are calling fromMarkedLocation(idp) even though idp points to a
|
||||||
|
// location that will never be marked. This is OK because the whole point
|
||||||
|
// of this API is to populate *idp with a jsid that does not need to be
|
||||||
|
// marked.
|
||||||
|
return PropertySpecNameToId(cx, name, MutableHandleId::fromMarkedLocation(idp),
|
||||||
|
js::InternAtom);
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
JS_DefineProperties(JSContext *cx, HandleObject obj, const JSPropertySpec *ps)
|
JS_DefineProperties(JSContext *cx, HandleObject obj, const JSPropertySpec *ps)
|
||||||
{
|
{
|
||||||
bool ok;
|
RootedId id(cx);
|
||||||
for (ok = true; ps->name; ps++) {
|
|
||||||
|
for (; ps->name; ps++) {
|
||||||
|
if (!PropertySpecNameToId(cx, ps->name, &id))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (ps->flags & JSPROP_NATIVE_ACCESSORS) {
|
if (ps->flags & JSPROP_NATIVE_ACCESSORS) {
|
||||||
// If you declare native accessors, then you should have a native
|
// If you declare native accessors, then you should have a native
|
||||||
// getter.
|
// getter.
|
||||||
MOZ_ASSERT(ps->getter.propertyOp.op);
|
MOZ_ASSERT(ps->getter.propertyOp.op);
|
||||||
|
|
||||||
// If you do not have a self-hosted getter, you should not have a
|
// If you do not have a self-hosted getter, you should not have a
|
||||||
// self-hosted setter. This is the closest approximation to that
|
// self-hosted setter. This is the closest approximation to that
|
||||||
// assertion we can have with our setup.
|
// assertion we can have with our setup.
|
||||||
MOZ_ASSERT_IF(ps->setter.propertyOp.info, ps->setter.propertyOp.op);
|
MOZ_ASSERT_IF(ps->setter.propertyOp.info, ps->setter.propertyOp.op);
|
||||||
|
|
||||||
ok = DefineProperty(cx, obj, ps->name, JS::UndefinedHandleValue,
|
if (!DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue,
|
||||||
ps->getter.propertyOp, ps->setter.propertyOp, ps->flags, 0);
|
ps->getter.propertyOp, ps->setter.propertyOp, ps->flags, 0))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If you have self-hosted getter/setter, you can't have a
|
// If you have self-hosted getter/setter, you can't have a
|
||||||
// native one.
|
// native one.
|
||||||
MOZ_ASSERT(!ps->getter.propertyOp.op && !ps->setter.propertyOp.op);
|
MOZ_ASSERT(!ps->getter.propertyOp.op && !ps->setter.propertyOp.op);
|
||||||
MOZ_ASSERT(ps->flags & JSPROP_GETTER);
|
MOZ_ASSERT(ps->flags & JSPROP_GETTER);
|
||||||
|
|
||||||
ok = DefineSelfHostedProperty(cx, obj, ps->name,
|
if (!DefineSelfHostedProperty(cx, obj, id,
|
||||||
ps->getter.selfHosted.funname,
|
ps->getter.selfHosted.funname,
|
||||||
ps->setter.selfHosted.funname,
|
ps->setter.selfHosted.funname,
|
||||||
ps->flags, 0);
|
ps->flags, 0))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!ok)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return ok;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
|
@ -3620,137 +3652,6 @@ JS_Enumerate(JSContext *cx, HandleObject obj)
|
||||||
return ida;
|
return ida;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX reverse iterator for properties, unreverse and meld with jsinterp.c's
|
|
||||||
* prop_iterator_class somehow...
|
|
||||||
* + preserve the obj->enumerate API while optimizing the native object case
|
|
||||||
* + native case here uses a JSShape *, but that iterates in reverse!
|
|
||||||
* + so we make non-native match, by reverse-iterating after JS_Enumerating
|
|
||||||
*/
|
|
||||||
static const uint32_t JSSLOT_ITER_INDEX = 0;
|
|
||||||
|
|
||||||
static void
|
|
||||||
prop_iter_finalize(FreeOp *fop, JSObject *obj)
|
|
||||||
{
|
|
||||||
void *pdata = obj->as<NativeObject>().getPrivate();
|
|
||||||
if (!pdata)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (obj->as<NativeObject>().getSlot(JSSLOT_ITER_INDEX).toInt32() >= 0) {
|
|
||||||
/* Non-native case: destroy the ida enumerated when obj was created. */
|
|
||||||
JSIdArray *ida = (JSIdArray *) pdata;
|
|
||||||
fop->free_(ida);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
prop_iter_trace(JSTracer *trc, JSObject *obj)
|
|
||||||
{
|
|
||||||
void *pdata = obj->as<NativeObject>().getPrivate();
|
|
||||||
if (!pdata)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (obj->as<NativeObject>().getSlot(JSSLOT_ITER_INDEX).toInt32() < 0) {
|
|
||||||
/*
|
|
||||||
* Native case: just mark the next property to visit. We don't need a
|
|
||||||
* barrier here because the pointer is updated via setPrivate, which
|
|
||||||
* always takes a barrier.
|
|
||||||
*/
|
|
||||||
Shape *tmp = static_cast<Shape *>(pdata);
|
|
||||||
MarkShapeUnbarriered(trc, &tmp, "prop iter shape");
|
|
||||||
obj->as<NativeObject>().setPrivateUnbarriered(tmp);
|
|
||||||
} else {
|
|
||||||
/* Non-native case: mark each id in the JSIdArray private. */
|
|
||||||
JSIdArray *ida = (JSIdArray *) pdata;
|
|
||||||
MarkIdRange(trc, ida->length, ida->vector, "prop iter");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Class prop_iter_class = {
|
|
||||||
"PropertyIterator",
|
|
||||||
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | JSCLASS_HAS_RESERVED_SLOTS(1),
|
|
||||||
JS_PropertyStub, /* addProperty */
|
|
||||||
JS_DeletePropertyStub, /* delProperty */
|
|
||||||
JS_PropertyStub, /* getProperty */
|
|
||||||
JS_StrictPropertyStub, /* setProperty */
|
|
||||||
JS_EnumerateStub,
|
|
||||||
JS_ResolveStub,
|
|
||||||
JS_ConvertStub,
|
|
||||||
prop_iter_finalize,
|
|
||||||
nullptr, /* call */
|
|
||||||
nullptr, /* hasInstance */
|
|
||||||
nullptr, /* construct */
|
|
||||||
prop_iter_trace
|
|
||||||
};
|
|
||||||
|
|
||||||
JS_PUBLIC_API(JSObject *)
|
|
||||||
JS_NewPropertyIterator(JSContext *cx, HandleObject obj)
|
|
||||||
{
|
|
||||||
AssertHeapIsIdle(cx);
|
|
||||||
CHECK_REQUEST(cx);
|
|
||||||
assertSameCompartment(cx, obj);
|
|
||||||
|
|
||||||
RootedNativeObject iterobj(cx, NewNativeObjectWithClassProto(cx, &prop_iter_class,
|
|
||||||
nullptr, obj));
|
|
||||||
if (!iterobj)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
int index;
|
|
||||||
if (obj->isNative()) {
|
|
||||||
/* Native case: start with the last property in obj. */
|
|
||||||
iterobj->setPrivateGCThing(obj->lastProperty());
|
|
||||||
index = -1;
|
|
||||||
} else {
|
|
||||||
/* Non-native case: enumerate a JSIdArray and keep it via private. */
|
|
||||||
JSIdArray *ida = JS_Enumerate(cx, obj);
|
|
||||||
if (!ida)
|
|
||||||
return nullptr;
|
|
||||||
iterobj->setPrivate((void *)ida);
|
|
||||||
index = ida->length;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* iterobj cannot escape to other threads here. */
|
|
||||||
iterobj->setSlot(JSSLOT_ITER_INDEX, Int32Value(index));
|
|
||||||
return iterobj;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
|
||||||
JS_NextProperty(JSContext *cx, HandleObject iterobj, MutableHandleId idp)
|
|
||||||
{
|
|
||||||
AssertHeapIsIdle(cx);
|
|
||||||
CHECK_REQUEST(cx);
|
|
||||||
assertSameCompartment(cx, iterobj);
|
|
||||||
int32_t i = iterobj->as<NativeObject>().getSlot(JSSLOT_ITER_INDEX).toInt32();
|
|
||||||
if (i < 0) {
|
|
||||||
/* Native case: private data is a property tree node pointer. */
|
|
||||||
MOZ_ASSERT(iterobj->getParent()->isNative());
|
|
||||||
Shape *shape = static_cast<Shape *>(iterobj->as<NativeObject>().getPrivate());
|
|
||||||
|
|
||||||
while (shape->previous() && !shape->enumerable())
|
|
||||||
shape = shape->previous();
|
|
||||||
|
|
||||||
if (!shape->previous()) {
|
|
||||||
MOZ_ASSERT(shape->isEmptyShape());
|
|
||||||
idp.set(JSID_VOID);
|
|
||||||
} else {
|
|
||||||
iterobj->as<NativeObject>().setPrivateGCThing(const_cast<Shape *>(shape->previous().get()));
|
|
||||||
idp.set(shape->propid());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* Non-native case: use the ida enumerated when iterobj was created. */
|
|
||||||
JSIdArray *ida = (JSIdArray *) iterobj->as<NativeObject>().getPrivate();
|
|
||||||
MOZ_ASSERT(i <= ida->length);
|
|
||||||
STATIC_ASSUME(i <= ida->length);
|
|
||||||
if (i == 0) {
|
|
||||||
idp.set(JSID_VOID);
|
|
||||||
} else {
|
|
||||||
idp.set(ida->vector[--i]);
|
|
||||||
iterobj->as<NativeObject>().setSlot(JSSLOT_ITER_INDEX, Int32Value(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS_PUBLIC_API(jsval)
|
JS_PUBLIC_API(jsval)
|
||||||
JS_GetReservedSlot(JSObject *obj, uint32_t index)
|
JS_GetReservedSlot(JSObject *obj, uint32_t index)
|
||||||
{
|
{
|
||||||
|
@ -3899,12 +3800,14 @@ JS_NewFunctionById(JSContext *cx, JSNative native, unsigned nargs, unsigned flag
|
||||||
JS_PUBLIC_API(JSFunction *)
|
JS_PUBLIC_API(JSFunction *)
|
||||||
JS::GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, HandleId id, unsigned nargs)
|
JS::GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, HandleId id, unsigned nargs)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(JSID_IS_STRING(id));
|
|
||||||
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
||||||
AssertHeapIsIdle(cx);
|
AssertHeapIsIdle(cx);
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
|
|
||||||
RootedAtom name(cx, JSID_TO_ATOM(id));
|
RootedAtom name(cx, IdToFunctionName(cx, id));
|
||||||
|
if (!name)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
RootedAtom shName(cx, Atomize(cx, selfHostedName, strlen(selfHostedName)));
|
RootedAtom shName(cx, Atomize(cx, selfHostedName, strlen(selfHostedName)));
|
||||||
if (!shName)
|
if (!shName)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -4068,21 +3971,11 @@ JS_DefineFunctions(JSContext *cx, HandleObject obj, const JSFunctionSpec *fs)
|
||||||
CHECK_REQUEST(cx);
|
CHECK_REQUEST(cx);
|
||||||
assertSameCompartment(cx, obj);
|
assertSameCompartment(cx, obj);
|
||||||
|
|
||||||
|
RootedId id(cx);
|
||||||
for (; fs->name; fs++) {
|
for (; fs->name; fs++) {
|
||||||
RootedAtom atom(cx);
|
if (!PropertySpecNameToId(cx, fs->name, &id))
|
||||||
// If the name starts with "@@", it must be a well-known symbol.
|
|
||||||
if (fs->name[0] != '@' || fs->name[1] != '@')
|
|
||||||
atom = Atomize(cx, fs->name, strlen(fs->name));
|
|
||||||
else if (strcmp(fs->name, "@@iterator") == 0)
|
|
||||||
// FIXME: This atom should be a symbol: bug 918828.
|
|
||||||
atom = cx->names().std_iterator;
|
|
||||||
else
|
|
||||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_SYMBOL, fs->name);
|
|
||||||
if (!atom)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Rooted<jsid> id(cx, AtomToId(atom));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Define a generic arity N+1 static method for the arity N prototype
|
* Define a generic arity N+1 static method for the arity N prototype
|
||||||
* method if flags contains JSFUN_GENERIC_NATIVE.
|
* method if flags contains JSFUN_GENERIC_NATIVE.
|
||||||
|
@ -4124,8 +4017,11 @@ JS_DefineFunctions(JSContext *cx, HandleObject obj, const JSFunctionSpec *fs)
|
||||||
RootedAtom shName(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
|
RootedAtom shName(cx, Atomize(cx, fs->selfHostedName, strlen(fs->selfHostedName)));
|
||||||
if (!shName)
|
if (!shName)
|
||||||
return false;
|
return false;
|
||||||
|
RootedAtom name(cx, IdToFunctionName(cx, id));
|
||||||
|
if (!name)
|
||||||
|
return false;
|
||||||
RootedValue funVal(cx);
|
RootedValue funVal(cx);
|
||||||
if (!cx->global()->getSelfHostedFunction(cx, shName, atom, fs->nargs, &funVal))
|
if (!cx->global()->getSelfHostedFunction(cx, shName, name, fs->nargs, &funVal))
|
||||||
return false;
|
return false;
|
||||||
if (!JSObject::defineGeneric(cx, obj, id, funVal, nullptr, nullptr, flags))
|
if (!JSObject::defineGeneric(cx, obj, id, funVal, nullptr, nullptr, flags))
|
||||||
return false;
|
return false;
|
||||||
|
@ -5628,6 +5524,33 @@ JS::GetWellKnownSymbol(JSContext *cx, JS::SymbolCode which)
|
||||||
return cx->runtime()->wellKnownSymbols->get(uint32_t(which));
|
return cx->runtime()->wellKnownSymbols->get(uint32_t(which));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
PropertySpecNameIsDigits(const char *s) {
|
||||||
|
if (JS::PropertySpecNameIsSymbol(s))
|
||||||
|
return false;
|
||||||
|
if (!*s)
|
||||||
|
return false;
|
||||||
|
for (; *s; s++) {
|
||||||
|
if (*s < '0' || *s > '9')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(bool)
|
||||||
|
JS::PropertySpecNameEqualsId(const char *name, HandleId id)
|
||||||
|
{
|
||||||
|
if (JS::PropertySpecNameIsSymbol(name)) {
|
||||||
|
if (!JSID_IS_SYMBOL(id))
|
||||||
|
return false;
|
||||||
|
Symbol *sym = JSID_TO_SYMBOL(id);
|
||||||
|
return sym->isWellKnownSymbol() && sym->code() == PropertySpecNameToSymbolCode(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!PropertySpecNameIsDigits(name));
|
||||||
|
return JSID_IS_ATOM(id) && JS_FlatStringEqualsAscii(JSID_TO_ATOM(id), name);
|
||||||
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(bool)
|
JS_PUBLIC_API(bool)
|
||||||
JS_Stringify(JSContext *cx, MutableHandleValue vp, HandleObject replacer,
|
JS_Stringify(JSContext *cx, MutableHandleValue vp, HandleObject replacer,
|
||||||
HandleValue space, JSONWriteCallback callback, void *data)
|
HandleValue space, JSONWriteCallback callback, void *data)
|
||||||
|
|
|
@ -2475,15 +2475,27 @@ struct JSFunctionSpec {
|
||||||
* JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of
|
* JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of
|
||||||
* JSJitInfos. JS_SELF_HOSTED_FN declares a self-hosted function. Finally
|
* JSJitInfos. JS_SELF_HOSTED_FN declares a self-hosted function. Finally
|
||||||
* JS_FNSPEC has slots for all the fields.
|
* JS_FNSPEC has slots for all the fields.
|
||||||
|
*
|
||||||
|
* The _SYM variants allow defining a function with a symbol key rather than a
|
||||||
|
* string key. For example, use JS_SYM_FN(iterator, ...) to define an
|
||||||
|
* @@iterator method.
|
||||||
*/
|
*/
|
||||||
#define JS_FS(name,call,nargs,flags) \
|
#define JS_FS(name,call,nargs,flags) \
|
||||||
JS_FNSPEC(name, call, nullptr, nargs, flags, nullptr)
|
JS_FNSPEC(name, call, nullptr, nargs, flags, nullptr)
|
||||||
#define JS_FN(name,call,nargs,flags) \
|
#define JS_FN(name,call,nargs,flags) \
|
||||||
JS_FNSPEC(name, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
|
JS_FNSPEC(name, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
|
||||||
|
#define JS_SYM_FN(name,call,nargs,flags) \
|
||||||
|
JS_SYM_FNSPEC(symbol, call, nullptr, nargs, (flags) | JSFUN_STUB_GSOPS, nullptr)
|
||||||
#define JS_FNINFO(name,call,info,nargs,flags) \
|
#define JS_FNINFO(name,call,info,nargs,flags) \
|
||||||
JS_FNSPEC(name, call, info, nargs, flags, nullptr)
|
JS_FNSPEC(name, call, info, nargs, flags, nullptr)
|
||||||
#define JS_SELF_HOSTED_FN(name,selfHostedName,nargs,flags) \
|
#define JS_SELF_HOSTED_FN(name,selfHostedName,nargs,flags) \
|
||||||
JS_FNSPEC(name, nullptr, nullptr, nargs, flags, selfHostedName)
|
JS_FNSPEC(name, nullptr, nullptr, nargs, flags, selfHostedName)
|
||||||
|
#define JS_SELF_HOSTED_SYM_FN(symbol, selfHostedName, nargs, flags) \
|
||||||
|
JS_SYM_FNSPEC(symbol, nullptr, nullptr, nargs, flags, selfHostedName)
|
||||||
|
#define JS_SYM_FNSPEC(symbol, call, info, nargs, flags, selfHostedName) \
|
||||||
|
JS_FNSPEC(reinterpret_cast<const char *>( \
|
||||||
|
uint32_t(::JS::SymbolCode::symbol) + 1), \
|
||||||
|
call, info, nargs, flags, selfHostedName)
|
||||||
#define JS_FNSPEC(name,call,info,nargs,flags,selfHostedName) \
|
#define JS_FNSPEC(name,call,info,nargs,flags,selfHostedName) \
|
||||||
{name, {call, info}, nargs, flags, selfHostedName}
|
{name, {call, info}, nargs, flags, selfHostedName}
|
||||||
|
|
||||||
|
@ -3305,22 +3317,6 @@ JS_ReleaseMappedArrayBufferContents(void *contents, size_t length);
|
||||||
extern JS_PUBLIC_API(JSIdArray *)
|
extern JS_PUBLIC_API(JSIdArray *)
|
||||||
JS_Enumerate(JSContext *cx, JS::HandleObject obj);
|
JS_Enumerate(JSContext *cx, JS::HandleObject obj);
|
||||||
|
|
||||||
/*
|
|
||||||
* Create an object to iterate over enumerable properties of obj, in arbitrary
|
|
||||||
* property definition order. NB: This differs from longstanding for..in loop
|
|
||||||
* order, which uses order of property definition in obj.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(JSObject *)
|
|
||||||
JS_NewPropertyIterator(JSContext *cx, JS::Handle<JSObject*> obj);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Return true on success with *idp containing the id of the next enumerable
|
|
||||||
* property to visit using iterobj, or JSID_IS_VOID if there is no such property
|
|
||||||
* left to visit. Return false on error.
|
|
||||||
*/
|
|
||||||
extern JS_PUBLIC_API(bool)
|
|
||||||
JS_NextProperty(JSContext *cx, JS::HandleObject iterobj, JS::MutableHandleId idp);
|
|
||||||
|
|
||||||
extern JS_PUBLIC_API(jsval)
|
extern JS_PUBLIC_API(jsval)
|
||||||
JS_GetReservedSlot(JSObject *obj, uint32_t index);
|
JS_GetReservedSlot(JSObject *obj, uint32_t index);
|
||||||
|
|
||||||
|
@ -4510,6 +4506,31 @@ GetSymbolCode(Handle<Symbol*> symbol);
|
||||||
JS_PUBLIC_API(Symbol *)
|
JS_PUBLIC_API(Symbol *)
|
||||||
GetWellKnownSymbol(JSContext *cx, SymbolCode which);
|
GetWellKnownSymbol(JSContext *cx, SymbolCode which);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return true if the given JSPropertySpec::name or JSFunctionSpec::name value
|
||||||
|
* is actually a symbol code and not a string. See JS_SYM_FN.
|
||||||
|
*/
|
||||||
|
inline bool
|
||||||
|
PropertySpecNameIsSymbol(const char *name)
|
||||||
|
{
|
||||||
|
uintptr_t u = reinterpret_cast<uintptr_t>(name);
|
||||||
|
return u != 0 && u - 1 < WellKnownSymbolLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS_PUBLIC_API(bool)
|
||||||
|
PropertySpecNameEqualsId(const char *name, HandleId id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a jsid that does not need to be marked for GC.
|
||||||
|
*
|
||||||
|
* 'name' is a JSPropertySpec::name or JSFunctionSpec::name value. The
|
||||||
|
* resulting jsid, on success, is either an interned string or a well-known
|
||||||
|
* symbol; either way it is immune to GC so there is no need to visit *idp
|
||||||
|
* during GC marking.
|
||||||
|
*/
|
||||||
|
JS_PUBLIC_API(bool)
|
||||||
|
PropertySpecNameToPermanentId(JSContext *cx, const char *name, jsid *idp);
|
||||||
|
|
||||||
} /* namespace JS */
|
} /* namespace JS */
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
|
@ -58,7 +58,6 @@ const char js_break_str[] = "break";
|
||||||
const char js_case_str[] = "case";
|
const char js_case_str[] = "case";
|
||||||
const char js_catch_str[] = "catch";
|
const char js_catch_str[] = "catch";
|
||||||
const char js_class_str[] = "class";
|
const char js_class_str[] = "class";
|
||||||
const char js_close_str[] = "close";
|
|
||||||
const char js_const_str[] = "const";
|
const char js_const_str[] = "const";
|
||||||
const char js_continue_str[] = "continue";
|
const char js_continue_str[] = "continue";
|
||||||
const char js_debugger_str[] = "debugger";
|
const char js_debugger_str[] = "debugger";
|
||||||
|
|
|
@ -1109,11 +1109,10 @@ JSContext::JSContext(JSRuntime *rt)
|
||||||
data(nullptr),
|
data(nullptr),
|
||||||
data2(nullptr),
|
data2(nullptr),
|
||||||
outstandingRequests(0),
|
outstandingRequests(0),
|
||||||
jitIsBroken(false),
|
jitIsBroken(false)
|
||||||
#ifdef MOZ_TRACE_JSCALLS
|
#ifdef MOZ_TRACE_JSCALLS
|
||||||
functionCallback(nullptr),
|
, functionCallback(nullptr)
|
||||||
#endif
|
#endif
|
||||||
innermostGenerator_(nullptr)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(static_cast<ContextFriendFields*>(this) ==
|
MOZ_ASSERT(static_cast<ContextFriendFields*>(this) ==
|
||||||
ContextFriendFields::get(this));
|
ContextFriendFields::get(this));
|
||||||
|
@ -1146,23 +1145,6 @@ JSContext::isThrowingOutOfMemory()
|
||||||
return throwing && unwrappedException_ == StringValue(names().outOfMemory);
|
return throwing && unwrappedException_ == StringValue(names().outOfMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
JSContext::enterGenerator(JSGenerator *gen)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(!gen->prevGenerator);
|
|
||||||
gen->prevGenerator = innermostGenerator_;
|
|
||||||
innermostGenerator_ = gen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
JSContext::leaveGenerator(JSGenerator *gen)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(innermostGenerator_ == gen);
|
|
||||||
innermostGenerator_ = innermostGenerator_->prevGenerator;
|
|
||||||
gen->prevGenerator = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSContext::saveFrameChain()
|
JSContext::saveFrameChain()
|
||||||
{
|
{
|
||||||
|
|
|
@ -284,6 +284,7 @@ struct ThreadSafeContext : ContextFriendFields,
|
||||||
JSAtomState &names() { return *runtime_->commonNames; }
|
JSAtomState &names() { return *runtime_->commonNames; }
|
||||||
StaticStrings &staticStrings() { return *runtime_->staticStrings; }
|
StaticStrings &staticStrings() { return *runtime_->staticStrings; }
|
||||||
AtomSet &permanentAtoms() { return *runtime_->permanentAtoms; }
|
AtomSet &permanentAtoms() { return *runtime_->permanentAtoms; }
|
||||||
|
WellKnownSymbols &wellKnownSymbols() { return *runtime_->wellKnownSymbols; }
|
||||||
const JS::AsmJSCacheOps &asmJSCacheOps() { return runtime_->asmJSCacheOps; }
|
const JS::AsmJSCacheOps &asmJSCacheOps() { return runtime_->asmJSCacheOps; }
|
||||||
PropertyName *emptyString() { return runtime_->emptyString; }
|
PropertyName *emptyString() { return runtime_->emptyString; }
|
||||||
FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
|
FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
|
||||||
|
@ -551,14 +552,7 @@ struct JSContext : public js::ExclusiveContext,
|
||||||
runtime_->gc.gcIfNeeded(this);
|
runtime_->gc.gcIfNeeded(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
/* Innermost-executing generator or null if no generator are executing. */
|
|
||||||
JSGenerator *innermostGenerator_;
|
|
||||||
public:
|
public:
|
||||||
JSGenerator *innermostGenerator() const { return innermostGenerator_; }
|
|
||||||
void enterGenerator(JSGenerator *gen);
|
|
||||||
void leaveGenerator(JSGenerator *gen);
|
|
||||||
|
|
||||||
bool isExceptionPending() {
|
bool isExceptionPending() {
|
||||||
return throwing;
|
return throwing;
|
||||||
}
|
}
|
||||||
|
|
|
@ -971,7 +971,7 @@ CopyFlatStringChars(char16_t *dest, JSFlatString *s, size_t len)
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
GetPropertyKeys(JSContext *cx, JSObject *obj, unsigned flags, JS::AutoIdVector *props);
|
GetPropertyKeys(JSContext *cx, JS::HandleObject obj, unsigned flags, JS::AutoIdVector *props);
|
||||||
|
|
||||||
JS_FRIEND_API(bool)
|
JS_FRIEND_API(bool)
|
||||||
AppendUnique(JSContext *cx, JS::AutoIdVector &base, JS::AutoIdVector &others);
|
AppendUnique(JSContext *cx, JS::AutoIdVector &base, JS::AutoIdVector &others);
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче