зеркало из 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
|
||||
# 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;
|
||||
border: 0px solid transparent !important;
|
||||
pointer-events: none;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
xul|scrollbar[orient="vertical"] {
|
||||
|
@ -56,7 +55,6 @@ xul|scrollbar[orient="horizontal"] xul|thumb {
|
|||
xul|scrollbar:not([active="true"]),
|
||||
xul|scrollbar[disabled] {
|
||||
opacity: 0;
|
||||
transition: opacity 1s ease;
|
||||
}
|
||||
|
||||
xul|scrollbarbutton {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<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="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<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">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</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="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
<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="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"remote": "",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "63436aa17e7fa3ad521fdeffdc22b81c36e5d69b",
|
||||
"revision": "934b8c3014a3e20dd5d90ecf95f4b6b704dddb1e",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<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="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f6b7471c881ee689183d681658cf2ba3dfc5610"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="abef62c0623e5504a97b4fd411e879a67b285b52"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="1daf2dadcd0d554c733661a4c0be1b82001e9da0"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="cc1f362ce43dce92ac786187ff4abf39060094bd"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
|
||||
|
|
|
@ -74,3 +74,13 @@ tabpanels {
|
|||
browser[pending] {
|
||||
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 name="_contentWaitingCount">
|
||||
0
|
||||
</field>
|
||||
|
||||
<property name="_numPinnedTabs" readonly="true">
|
||||
<getter><![CDATA[
|
||||
for (var i = 0; i < this.tabs.length; i++) {
|
||||
|
@ -3228,6 +3232,31 @@
|
|||
</body>
|
||||
</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">
|
||||
<parameter name="toTab"/>
|
||||
<parameter name="fromTab"/>
|
||||
|
@ -3266,16 +3295,19 @@
|
|||
|
||||
let timeoutPromise = new Promise((aResolve, aReject) => {
|
||||
timeoutId = setTimeout(() => {
|
||||
this._showBusySpinnerRemoteBrowser(toBrowser);
|
||||
attemptTabSwitch(aResolve, aReject);
|
||||
}, kTabSwitchTimeout);
|
||||
});
|
||||
|
||||
let paintPromise = new Promise((aResolve, aReject) => {
|
||||
toBrowser.addEventListener("MozAfterRemotePaint", function onRemotePaint() {
|
||||
let onRemotePaint = () => {
|
||||
toBrowser.removeEventListener("MozAfterRemotePaint", onRemotePaint);
|
||||
this._hideBusySpinnerRemoteBrowser(toBrowser);
|
||||
clearTimeout(timeoutId);
|
||||
attemptTabSwitch(aResolve, aReject);
|
||||
});
|
||||
};
|
||||
toBrowser.addEventListener("MozAfterRemotePaint", onRemotePaint);
|
||||
toBrowser.QueryInterface(Ci.nsIFrameLoaderOwner)
|
||||
.frameLoader
|
||||
.requestNotifyAfterRemotePaint();
|
||||
|
|
|
@ -1376,7 +1376,7 @@ PlacesToolbar.prototype = {
|
|||
elt.localName != "menupopup") {
|
||||
let eltRect = elt.getBoundingClientRect();
|
||||
let eltIndex = Array.indexOf(this._rootElt.childNodes, elt);
|
||||
if (PlacesUIUtils.nodeIsFolder(elt._placesNode) &&
|
||||
if (PlacesUtils.nodeIsFolder(elt._placesNode) &&
|
||||
!PlacesUIUtils.isContentsReadOnly(elt._placesNode)) {
|
||||
// This is a folder.
|
||||
// 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
|
||||
DEFINES += -DCLANG_CXX
|
||||
endif
|
||||
ifdef CLANG_CL
|
||||
DEFINES += -DCLANG_CL
|
||||
endif
|
||||
|
||||
libs::
|
||||
$(MAKE) -C $(DEPTH)/browser/locales langpack
|
||||
|
|
|
@ -921,4 +921,7 @@ bin/libfreebl_32int64_3.so
|
|||
#ifdef CLANG_CXX
|
||||
@BINPATH@/llvm-symbolizer
|
||||
#endif
|
||||
#ifdef CLANG_CL
|
||||
@BINPATH@/clang_rt.asan_dynamic-i386.dll
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -94,6 +94,9 @@ PluginContent.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
if (Services.telemetry.canSend) {
|
||||
this._finishRecordingFlashPluginTelemetry();
|
||||
}
|
||||
this.clearPluginDataCache();
|
||||
},
|
||||
|
||||
|
@ -378,6 +381,11 @@ PluginContent.prototype = {
|
|||
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.
|
||||
if (eventType != "PluginCrashed") {
|
||||
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) {
|
||||
return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
|
||||
Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
|
||||
|
|
|
@ -66,6 +66,13 @@ LLDBINIT_FINAL_TARGET_FILES := $(DEPTH)/.lldbinit
|
|||
LLDBINIT_FINAL_TARGET_DEST = $(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
|
||||
|
||||
TARGET_DEPTH = ..
|
||||
|
|
23
configure.in
23
configure.in
|
@ -506,6 +506,11 @@ case "$target" in
|
|||
if test -z "$CLANG_CL"; then
|
||||
AC_DEFINE(HAVE_SEH_EXCEPTIONS)
|
||||
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)
|
||||
fi
|
||||
|
||||
|
@ -1260,6 +1265,16 @@ MOZ_ARG_ENABLE_BOOL(address-sanitizer,
|
|||
MOZ_ASAN= )
|
||||
if test -n "$MOZ_ASAN"; then
|
||||
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)
|
||||
MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
|
||||
fi
|
||||
|
@ -3796,11 +3811,6 @@ dnl system libffi Support
|
|||
dnl ========================================================
|
||||
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,
|
||||
[ --enable-shared-js
|
||||
Create a shared JavaScript library.],
|
||||
|
@ -7953,8 +7963,7 @@ dnl =
|
|||
dnl ========================================================
|
||||
MOZ_ARG_HEADER(Static build options)
|
||||
|
||||
if test "$OS_ARCH" = "WINNT"; then
|
||||
GKMEDIAS_SHARED_LIBRARY=1
|
||||
if test -n "$GKMEDIAS_SHARED_LIBRARY"; then
|
||||
AC_DEFINE(GKMEDIAS_SHARED_LIBRARY)
|
||||
fi
|
||||
AC_SUBST(GKMEDIAS_SHARED_LIBRARY)
|
||||
|
|
|
@ -412,7 +412,7 @@ public:
|
|||
/**
|
||||
* Web components custom element data.
|
||||
*/
|
||||
nsAutoPtr<CustomElementData> mCustomElementData;
|
||||
nsRefPtr<CustomElementData> mCustomElementData;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -238,18 +238,15 @@ DOMParser::ParseFromStream(nsIInputStream *stream,
|
|||
|
||||
// Create a fake channel
|
||||
nsCOMPtr<nsIChannel> parserChannel;
|
||||
NS_NewInputStreamChannel(getter_AddRefs(parserChannel), mDocumentURI, nullptr,
|
||||
nsDependentCString(contentType), nullptr);
|
||||
NS_NewInputStreamChannel(getter_AddRefs(parserChannel),
|
||||
mDocumentURI,
|
||||
nullptr, // aStream
|
||||
mOriginalPrincipal,
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
nsDependentCString(contentType));
|
||||
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) {
|
||||
parserChannel->SetContentCharset(nsDependentCString(charset));
|
||||
}
|
||||
|
|
|
@ -193,6 +193,8 @@ public:
|
|||
WorkerPrivate* mWorkerPrivate;
|
||||
nsAutoPtr<WorkerFeature> mWorkerFeature;
|
||||
|
||||
nsWeakPtr mWeakLoadGroup;
|
||||
|
||||
private:
|
||||
~WebSocketImpl()
|
||||
{
|
||||
|
@ -528,8 +530,7 @@ WebSocketImpl::DisconnectInternal()
|
|||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakLoadGroup);
|
||||
if (loadGroup) {
|
||||
loadGroup->RemoveRequest(this, nullptr, NS_OK);
|
||||
}
|
||||
|
@ -1390,6 +1391,8 @@ WebSocketImpl::InitializeConnection()
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = loadGroup->AddRequest(this, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mWeakLoadGroup = do_GetWeakReference(loadGroup);
|
||||
}
|
||||
|
||||
// manually adding loadinfo to the channel since it
|
||||
|
|
|
@ -5844,12 +5844,7 @@ nsDocument::ProcessTopElementQueue(bool aIsBaseQueue)
|
|||
{
|
||||
MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
|
||||
|
||||
if (sProcessingStack.isNothing()) {
|
||||
// If XPCOM shutdown has reset the processing stack, don't do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
nsTArray<CustomElementData*>& stack = *sProcessingStack;
|
||||
nsTArray<nsRefPtr<CustomElementData>>& stack = *sProcessingStack;
|
||||
uint32_t firstQueue = stack.LastIndexOf((CustomElementData*) nullptr);
|
||||
|
||||
if (aIsBaseQueue && firstQueue != 0) {
|
||||
|
@ -5886,7 +5881,7 @@ nsDocument::RegisterEnabled()
|
|||
}
|
||||
|
||||
// static
|
||||
Maybe<nsTArray<mozilla::dom::CustomElementData*>>
|
||||
Maybe<nsTArray<nsRefPtr<mozilla::dom::CustomElementData>>>
|
||||
nsDocument::sProcessingStack;
|
||||
|
||||
// static
|
||||
|
|
|
@ -325,6 +325,8 @@ private:
|
|||
// being created flag.
|
||||
struct CustomElementData
|
||||
{
|
||||
NS_INLINE_DECL_REFCOUNTING(CustomElementData)
|
||||
|
||||
explicit CustomElementData(nsIAtom* aType);
|
||||
// Objects in this array are transient and empty after each microtask
|
||||
// checkpoint.
|
||||
|
@ -346,6 +348,9 @@ struct CustomElementData
|
|||
|
||||
// Empties the callback queue.
|
||||
void RunCallbackQueue();
|
||||
|
||||
private:
|
||||
virtual ~CustomElementData() {}
|
||||
};
|
||||
|
||||
// The required information for a custom element as defined in:
|
||||
|
@ -1520,7 +1525,7 @@ private:
|
|||
// CustomElementData in this array, separated by nullptr that
|
||||
// represent the boundaries of the items in the stack. The first
|
||||
// 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
|
||||
// custom elements speicification.
|
||||
|
|
|
@ -519,7 +519,11 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
|||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
stream);
|
||||
stream,
|
||||
info->mPrincipal,
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||
nsIContentPolicy::TYPE_OTHER);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString type;
|
||||
|
@ -537,12 +541,6 @@ nsHostObjectProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
|
|||
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->SetContentType(NS_ConvertUTF16toUTF8(type));
|
||||
channel->SetContentLength(size);
|
||||
|
|
|
@ -12,6 +12,9 @@ var is_remote;
|
|||
error_reporting_test();
|
||||
dom_test();
|
||||
xray_test();
|
||||
if (typeof Symbol === "function") {
|
||||
symbol_test();
|
||||
}
|
||||
compartment_test();
|
||||
regexp_test();
|
||||
sync_test();
|
||||
|
@ -119,15 +122,13 @@ function symbol_test()
|
|||
{
|
||||
let iterator = Symbol.iterator;
|
||||
let named = Symbol.for("cpow-test");
|
||||
// let unique = Symbol();
|
||||
|
||||
let object = {
|
||||
[iterator]: iterator,
|
||||
[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
|
||||
|
|
|
@ -206,10 +206,16 @@
|
|||
}
|
||||
|
||||
function recvSymbolTest(message) {
|
||||
let object = message.objects;
|
||||
let object = message.objects.object;
|
||||
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(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;
|
||||
|
@ -307,7 +313,9 @@
|
|||
mm.addMessageListener("cpows:dom_test", recvDomTest);
|
||||
mm.addMessageListener("cpows:dom_test_after_gc", recvDomTestAfterGC);
|
||||
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:regexp_test", recvRegExpTest);
|
||||
mm.addMessageListener("cpows:lifetime_test_1", recvLifetimeTest1);
|
||||
|
|
|
@ -1655,12 +1655,25 @@ nsDocShell::LoadStream(nsIInputStream *aStream, nsIURI * aURI,
|
|||
|
||||
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.
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
NS_ENSURE_SUCCESS(NS_NewInputStreamChannel
|
||||
(getter_AddRefs(channel), uri, aStream,
|
||||
aContentType, aContentCharset),
|
||||
NS_ERROR_FAILURE);
|
||||
nsresult rv =
|
||||
NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
aStream,
|
||||
requestingPrincipal,
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
aContentType,
|
||||
aContentCharset);
|
||||
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIURILoader>
|
||||
uriLoader(do_GetService(NS_URI_LOADER_CONTRACTID));
|
||||
|
@ -10266,25 +10279,28 @@ nsDocShell::DoURILoad(nsIURI * aURI,
|
|||
rv = vsh->NewSrcdocChannel(aURI, aSrcdoc, aBaseURI,
|
||||
getter_AddRefs(channel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||
new LoadInfo(requestingPrincipal,
|
||||
requestingNode,
|
||||
securityFlags,
|
||||
aContentPolicyType);
|
||||
channel->SetLoadInfo(loadInfo);
|
||||
}
|
||||
else {
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),aURI,
|
||||
aSrcdoc,
|
||||
NS_LITERAL_CSTRING("text/html"),
|
||||
true);
|
||||
rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
|
||||
aURI,
|
||||
aSrcdoc,
|
||||
NS_LITERAL_CSTRING("text/html"),
|
||||
requestingNode,
|
||||
requestingPrincipal,
|
||||
securityFlags,
|
||||
aContentPolicyType,
|
||||
true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIInputStreamChannel> isc = do_QueryInterface(channel);
|
||||
MOZ_ASSERT(isc);
|
||||
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 =
|
||||
|
|
|
@ -599,20 +599,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual const char *className(JSContext *cx,
|
||||
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;
|
||||
// Standard internal methods
|
||||
virtual bool getOwnPropertyDescriptor(JSContext* cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id,
|
||||
|
@ -631,23 +618,12 @@ public:
|
|||
bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const MOZ_OVERRIDE;
|
||||
|
||||
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;
|
||||
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE {
|
||||
return false;
|
||||
}
|
||||
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Derived 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 has(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
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,
|
||||
JS::Handle<JSObject*> receiver,
|
||||
JS::Handle<jsid> id,
|
||||
|
@ -657,11 +633,36 @@ public:
|
|||
JS::Handle<jsid> id,
|
||||
bool strict,
|
||||
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,
|
||||
unsigned flags,
|
||||
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);
|
||||
|
||||
|
@ -930,12 +931,12 @@ nsOuterWindowProxy::set(JSContext *cx, JS::Handle<JSObject*> proxy,
|
|||
}
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::keys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const
|
||||
nsOuterWindowProxy::getOwnEnumerablePropertyKeys(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) const
|
||||
{
|
||||
// BaseProxyHandler::keys seems to do what we want here: call
|
||||
// ownPropertyKeys and then filter out the non-enumerable properties.
|
||||
return js::BaseProxyHandler::keys(cx, proxy, props);
|
||||
return js::BaseProxyHandler::getOwnEnumerablePropertyKeys(cx, proxy, props);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -82,6 +82,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
|||
[test_urlutils_stringify.html]
|
||||
[test_window_constructor.html]
|
||||
[test_window_cross_origin_props.html]
|
||||
[test_window_define_symbol.html]
|
||||
[test_window_enumeration.html]
|
||||
[test_window_extensible.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.
|
||||
size_t i = list->specs - specList;
|
||||
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) ||
|
||||
(specList[i].flags & JSPROP_ENUMERATE)) &&
|
||||
((flags & JSITER_SYMBOLS) || !JSID_IS_SYMBOL(ids[i])) &&
|
||||
!props.append(ids[i])) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1685,7 +1685,7 @@ InitIds(JSContext* cx, const Prefable<Spec>* prefableSpecs, jsid* ids)
|
|||
// because this is only done once per application runtime.
|
||||
Spec* spec = prefableSpecs->specs;
|
||||
do {
|
||||
if (!InternJSString(cx, *ids, spec->name)) {
|
||||
if (!JS::PropertySpecNameToPermanentId(cx, spec->name, ids)) {
|
||||
return false;
|
||||
}
|
||||
} while (++ids, (++spec)->name);
|
||||
|
|
|
@ -277,7 +277,7 @@ BaseDOMProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
|||
if (!JS_GetPrototype(cx, proxy, &proto)) {
|
||||
return false;
|
||||
}
|
||||
return keys(cx, proxy, props) &&
|
||||
return getOwnEnumerablePropertyKeys(cx, proxy, props) &&
|
||||
(!proto || js::GetPropertyKeys(cx, proto, 0, &props));
|
||||
}
|
||||
|
||||
|
@ -299,13 +299,13 @@ BaseDOMProxyHandler::ownPropertyKeys(JSContext* cx,
|
|||
JS::Handle<JSObject*> proxy,
|
||||
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
|
||||
BaseDOMProxyHandler::keys(JSContext* cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector& props) const
|
||||
BaseDOMProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
|
||||
JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector& props) const
|
||||
{
|
||||
return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
|
||||
}
|
||||
|
@ -345,7 +345,8 @@ IdToInt32(JSContext* cx, JS::Handle<jsid> id)
|
|||
JS::Rooted<JS::Value> idval(cx);
|
||||
double array_index;
|
||||
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_DoubleIsInt32(array_index, &i)) {
|
||||
return -1;
|
||||
|
|
|
@ -50,34 +50,38 @@ public:
|
|||
: js::BaseProxyHandler(aProxyFamily, aHasPrototype)
|
||||
{}
|
||||
|
||||
// Implementations of traps that can be implemented in terms of
|
||||
// fundamental traps.
|
||||
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;
|
||||
// Implementations of methods that can be implemented in terms of
|
||||
// other lower-level methods.
|
||||
bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id,
|
||||
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,
|
||||
JS::Handle<JSObject*> callable) const MOZ_OVERRIDE;
|
||||
bool unwatch(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
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:
|
||||
// Hook for subclasses to implement shared ownPropertyKeys()/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,
|
||||
unsigned flags,
|
||||
JS::AutoIdVector& props) const = 0;
|
||||
|
@ -100,7 +104,6 @@ public:
|
|||
: 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,
|
||||
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,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc, bool* defined)
|
||||
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,
|
||||
JS::Handle<jsid> id, bool strict, JS::MutableHandle<JS::Value> vp)
|
||||
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
|
||||
|
|
|
@ -39,4 +39,9 @@
|
|||
/* CHLD values */
|
||||
#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 */
|
||||
|
|
|
@ -66,7 +66,11 @@ public:
|
|||
void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
|
||||
void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
||||
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,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
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
|
||||
WebGL2Context::TexSubImage3D(GLenum rawTarget, GLint level,
|
||||
GLint xoffset, GLint yoffset, GLint zoffset,
|
||||
|
|
|
@ -922,7 +922,11 @@ WebGLContext::GenerateMipmap(GLenum rawTarget)
|
|||
const TexImageTarget imageTarget = (target == LOCAL_GL_TEXTURE_2D)
|
||||
? LOCAL_GL_TEXTURE_2D
|
||||
: 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.");
|
||||
}
|
||||
|
|
|
@ -867,6 +867,7 @@ InfoFrom(WebGLTexImageFunc func, WebGLTexDimensions dims)
|
|||
}
|
||||
case WebGLTexDimensions::Tex3D:
|
||||
switch (func) {
|
||||
case WebGLTexImageFunc::TexImage: return "texImage3D";
|
||||
case WebGLTexImageFunc::TexSubImage: return "texSubImage3D";
|
||||
case WebGLTexImageFunc::CopyTexSubImage: return "copyTexSubImage3D";
|
||||
case WebGLTexImageFunc::CompTexSubImage: return "compressedTexSubImage3D";
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "WebGLTexelConversions.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -64,36 +65,50 @@ WebGLTexture::MemoryUsage() const {
|
|||
return 0;
|
||||
size_t result = 0;
|
||||
for(size_t face = 0; face < mFacesCount; face++) {
|
||||
for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++)
|
||||
result += ImageInfoAtFace(face, level).MemoryUsage();
|
||||
}
|
||||
for(size_t level = 0; level <= mMaxLevelWithCustomImages; level++)
|
||||
result += ImageInfoAtFace(face, level).MemoryUsage();
|
||||
}
|
||||
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
|
||||
WebGLTexture::DoesMipmapHaveAllLevelsConsistentlyDefined(TexImageTarget texImageTarget) const
|
||||
{
|
||||
// We could not have generated a mipmap if the base image wasn't defined.
|
||||
if (mHaveGeneratedMipmap)
|
||||
return true;
|
||||
|
||||
if (GetMaxMipmapLevel() < GetBaseMipmapLevel())
|
||||
if (!IsMipmapRangeValid())
|
||||
return false;
|
||||
|
||||
// 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
|
||||
// and have the expected dimensions
|
||||
for (size_t level = GetBaseMipmapLevel(); level <= GetMaxMipmapLevel(); ++level) {
|
||||
// If Level{max} is > mMaxLevelWithCustomImages, then check if we are
|
||||
// missing any image levels.
|
||||
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);
|
||||
if (actual != expected)
|
||||
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.mHeight = std::max(1, expected.mHeight / 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 false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -177,25 +191,19 @@ WebGLTexture::SetGeneratedMipmap() {
|
|||
void
|
||||
WebGLTexture::SetCustomMipmap() {
|
||||
if (mHaveGeneratedMipmap) {
|
||||
// if we were in GeneratedMipmap mode and are now switching to CustomMipmap mode,
|
||||
// we need to compute now all the mipmap image info.
|
||||
if (!IsMipmapRangeValid())
|
||||
return;
|
||||
|
||||
// since we were in GeneratedMipmap mode, we know that the level 0 images all have the same info,
|
||||
// and are power-of-two.
|
||||
ImageInfo imageInfo = ImageInfoAtFace(0, GetBaseMipmapLevel());
|
||||
// If we were in GeneratedMipmap mode and are now switching to CustomMipmap mode,
|
||||
// we now need to compute all the mipmap image info.
|
||||
ImageInfo imageInfo = ImageInfoAtFace(0, EffectiveBaseMipmapLevel());
|
||||
NS_ASSERTION(mContext->IsWebGL2() || imageInfo.IsPowerOfTwo(),
|
||||
"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).
|
||||
size_t maxLevel = 0;
|
||||
for (GLsizei n = size; n > 1; n >>= 1)
|
||||
++maxLevel;
|
||||
|
||||
EnsureMaxLevelWithCustomImagesAtLeast(maxLevel);
|
||||
|
||||
for (size_t level = GetBaseMipmapLevel() + 1; level <= GetMaxMipmapLevel(); ++level) {
|
||||
for (size_t level = EffectiveBaseMipmapLevel() + 1; level <= EffectiveMaxMipmapLevel(); ++level) {
|
||||
imageInfo.mWidth = std::max(imageInfo.mWidth / 2, 1);
|
||||
imageInfo.mHeight = std::max(imageInfo.mHeight / 2, 1);
|
||||
imageInfo.mDepth = std::max(imageInfo.mDepth / 2, 1);
|
||||
|
@ -219,11 +227,6 @@ bool
|
|||
WebGLTexture::IsMipmapComplete() const {
|
||||
MOZ_ASSERT(mTarget == LOCAL_GL_TEXTURE_2D ||
|
||||
mTarget == LOCAL_GL_TEXTURE_3D);
|
||||
|
||||
if (!ImageInfoAtFace(0, GetBaseMipmapLevel()).IsPositive())
|
||||
return false;
|
||||
if (mHaveGeneratedMipmap)
|
||||
return true;
|
||||
return DoesMipmapHaveAllLevelsConsistentlyDefined(LOCAL_GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
|
@ -249,6 +252,17 @@ WebGLTexture::IsMipmapCubeComplete() const {
|
|||
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
|
||||
WebGLTexture::ResolvedFakeBlackStatus() {
|
||||
if (MOZ_LIKELY(mFakeBlackStatus != WebGLTextureFakeBlackStatus::Unknown)) {
|
||||
|
@ -256,10 +270,14 @@ WebGLTexture::ResolvedFakeBlackStatus() {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
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
|
||||
// and often legitimate case (asynchronous texture loading).
|
||||
mFakeBlackStatus = WebGLTextureFakeBlackStatus::IncompleteTexture;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "mozilla/LinkedList.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include <algorithm>
|
||||
#include "nsAlgorithm.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -286,16 +287,22 @@ public:
|
|||
bool IsImmutable() const { return mImmutable; }
|
||||
void SetImmutable() { mImmutable = true; }
|
||||
|
||||
void SetBaseMipmapLevel(unsigned level) { mBaseMipmapLevel = level; }
|
||||
void SetMaxMipmapLevel(unsigned level) { mMaxMipmapLevel = level; }
|
||||
size_t GetBaseMipmapLevel() const {
|
||||
// Clamp to [0, levels - 1]
|
||||
return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
|
||||
void SetBaseMipmapLevel(size_t level) { mBaseMipmapLevel = level; }
|
||||
void SetMaxMipmapLevel(size_t level) { mMaxMipmapLevel = level; }
|
||||
|
||||
// Clamping (from ES 3.0.4, section 3.8 - Texturing). When not immutable,
|
||||
// the ranges must be guarded.
|
||||
size_t EffectiveBaseMipmapLevel() const {
|
||||
if (IsImmutable())
|
||||
return std::min(mBaseMipmapLevel, mMaxLevelWithCustomImages);
|
||||
return mBaseMipmapLevel;
|
||||
}
|
||||
size_t GetMaxMipmapLevel() const {
|
||||
// Clamp to [base, levels - 1]
|
||||
size_t EffectiveMaxMipmapLevel() const {
|
||||
if (IsImmutable())
|
||||
return mozilla::clamped(mMaxMipmapLevel, EffectiveBaseMipmapLevel(), mMaxLevelWithCustomImages);
|
||||
return std::min(mMaxMipmapLevel, mMaxLevelWithCustomImages);
|
||||
}
|
||||
bool IsMipmapRangeValid() const;
|
||||
|
||||
size_t MaxLevelWithCustomImages() const { return mMaxLevelWithCustomImages; }
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "nsCRTGlue.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include <algorithm>
|
||||
|
||||
|
@ -409,9 +410,19 @@ nsJSON::DecodeInternal(JSContext* cx,
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
NS_NewInputStreamChannel(getter_AddRefs(jsonChannel), mURI, aStream,
|
||||
NS_LITERAL_CSTRING("application/json"));
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrincipal> nullPrincipal =
|
||||
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))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include "nsIContentViewer.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIScriptChannel.h"
|
||||
|
@ -427,9 +428,18 @@ nsresult nsJSChannel::Init(nsIURI *aURI)
|
|||
// and the underlying Input Stream will not be created...
|
||||
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
|
||||
// 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"));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ interface MediaKeySession : EventTarget {
|
|||
|
||||
readonly attribute unrestricted double expiration;
|
||||
|
||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
||||
readonly attribute Promise<void> closed;
|
||||
|
||||
[NewObject, Throws]
|
||||
|
@ -31,15 +30,12 @@ interface MediaKeySession : EventTarget {
|
|||
Promise<boolean> load(DOMString sessionId);
|
||||
|
||||
// session operations
|
||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
||||
[NewObject, Throws]
|
||||
Promise<void> update((ArrayBufferView or ArrayBuffer) response);
|
||||
|
||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
||||
[NewObject, Throws]
|
||||
Promise<void> close();
|
||||
|
||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
||||
[NewObject, Throws]
|
||||
Promise<void> remove();
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@ interface MediaKeys {
|
|||
[NewObject, Throws]
|
||||
MediaKeySession createSession(optional SessionType sessionType = "temporary");
|
||||
|
||||
// void, not any: https://www.w3.org/Bugs/Public/show_bug.cgi?id=26457
|
||||
[NewObject, Throws]
|
||||
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 texStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height,
|
||||
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,
|
||||
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
|
||||
ArrayBufferView? pixels);
|
||||
|
|
|
@ -72,6 +72,11 @@ nsresult
|
|||
nsHTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
|
||||
{
|
||||
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
|
||||
// XXX This should be easier to do!
|
||||
|
@ -93,11 +98,6 @@ nsHTMLEditorEventListener::MouseDown(nsIDOMMouseEvent* aMouseEvent)
|
|||
NS_ENSURE_TRUE(target, NS_ERROR_NULL_POINTER);
|
||||
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)) {
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsIStandardURL.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include <gio/gio.h>
|
||||
#include <algorithm>
|
||||
|
@ -1062,11 +1063,18 @@ nsGIOProtocolHandler::NewChannel(nsIURI *aURI, nsIChannel **aResult)
|
|||
}
|
||||
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
|
||||
// to something better once we open the URI.
|
||||
rv = NS_NewInputStreamChannel(aResult,
|
||||
aURI,
|
||||
stream,
|
||||
nullPrincipal,
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
NS_LITERAL_CSTRING(UNKNOWN_CONTENT_TYPE));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
stream->SetChannel(*aResult);
|
||||
|
|
|
@ -548,11 +548,12 @@ Factory::SetDirect3D10Device(ID3D10Device1 *aDevice)
|
|||
|
||||
ID3D10Device1*
|
||||
Factory::GetDirect3D10Device()
|
||||
|
||||
{
|
||||
#ifdef DEBUG
|
||||
UINT mode = mD3D10Device->GetExceptionMode();
|
||||
MOZ_ASSERT(0 == mode);
|
||||
if (mD3D10Device) {
|
||||
UINT mode = mD3D10Device->GetExceptionMode();
|
||||
MOZ_ASSERT(0 == mode);
|
||||
}
|
||||
#endif
|
||||
return mD3D10Device;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,3 @@ endif
|
|||
|
||||
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)) {
|
||||
SymLoadStruct coreSymbols[] = {
|
||||
// TexImage3D is not required for WebGL2 so not queried here.
|
||||
{ (PRFuncPtr*) &mSymbols.fTexImage3D, { "TexImage3D", nullptr } },
|
||||
{ (PRFuncPtr*) &mSymbols.fTexSubImage3D, { "TexSubImage3D", nullptr } },
|
||||
END_SYMBOLS
|
||||
};
|
||||
|
|
|
@ -3132,6 +3132,21 @@ public:
|
|||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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,
|
||||
GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
|
||||
GLenum format, GLenum type, const GLvoid* pixels)
|
||||
|
|
|
@ -642,6 +642,12 @@ struct GLContextSymbols
|
|||
PFNGLGETFRAGDATALOCATIONPROC fGetFragDataLocation;
|
||||
|
||||
// 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,
|
||||
GLint yoffset, GLint zoffset, GLsizei width,
|
||||
GLsizei height, GLsizei depth, GLenum format,
|
||||
|
|
|
@ -369,17 +369,16 @@ gfxSVGGlyphsDocument::ParseDocument(const uint8_t *aBuffer, uint32_t aBufLen)
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel), uri, nullptr /* stream */,
|
||||
SVG_CONTENT_TYPE, UTF8_CHARSET);
|
||||
rv = NS_NewInputStreamChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
nullptr, //aStream
|
||||
principal,
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
SVG_CONTENT_TYPE,
|
||||
UTF8_CHARSET);
|
||||
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.
|
||||
document->SetIsBeingUsedAsImage();
|
||||
document->SetReadyStateInternal(nsIDocument::READYSTATE_UNINITIALIZED);
|
||||
|
|
|
@ -413,7 +413,7 @@ gfxUserFontEntry::LoadNextSrc()
|
|||
mItalic);
|
||||
mFontSet->SetLocalRulesUsed();
|
||||
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,
|
||||
NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
|
||||
NS_ConvertUTF16toUTF8(mFamilyName).get(),
|
||||
|
@ -430,7 +430,7 @@ gfxUserFontEntry::LoadNextSrc()
|
|||
SetLoadState(STATUS_LOADED);
|
||||
return;
|
||||
} 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,
|
||||
NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
|
||||
NS_ConvertUTF16toUTF8(mFamilyName).get()));
|
||||
|
@ -647,7 +647,7 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
|
|||
nsAutoCString fontURI;
|
||||
mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
|
||||
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(),
|
||||
uint32_t(mFontSet->mGeneration)));
|
||||
}
|
||||
|
@ -662,7 +662,7 @@ gfxUserFontEntry::LoadPlatformFont(const uint8_t* aFontData, uint32_t& aLength)
|
|||
mSrcList[mSrcIndex].mURI->GetSpec(fontURI);
|
||||
LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
|
||||
" error making platform font\n",
|
||||
this, mSrcIndex, fontURI.get(),
|
||||
mFontSet, mSrcIndex, fontURI.get(),
|
||||
NS_ConvertUTF16toUTF8(mFamilyName).get()));
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -467,6 +467,10 @@ public:
|
|||
mLocalRulesUsed = true;
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* GetUserFontsLog();
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// Protected destructor, to discourage deletion outside of Release():
|
||||
virtual ~gfxUserFontSet();
|
||||
|
@ -512,8 +516,6 @@ protected:
|
|||
|
||||
// true when local names have been looked up, false otherwise
|
||||
bool mLocalRulesUsed;
|
||||
|
||||
static PRLogModuleInfo* GetUserFontsLog();
|
||||
};
|
||||
|
||||
// acts a placeholder until the real font is downloaded
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "nsIconChannel.h"
|
||||
#include "nsIStringStream.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsIconChannel,
|
||||
nsIRequest,
|
||||
|
@ -102,7 +103,16 @@ moz_icon_to_channel(nsIURI *aURI, const nsACString& aFileExt, uint32_t aIconSize
|
|||
rv = stream->AdoptData((char*)buf, buf_size);
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ extern "C" {
|
|||
#include "nsIStringBundle.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "nsIURL.h"
|
||||
#include "prlink.h"
|
||||
|
||||
|
@ -137,9 +138,17 @@ moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI *aURI,
|
|||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = NS_NewInputStreamChannel(aChannel, aURI, stream,
|
||||
NS_LITERAL_CSTRING(IMAGE_ICON_MS));
|
||||
return rv;
|
||||
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));
|
||||
}
|
||||
|
||||
static GtkWidget *gProtoWindow = nullptr;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsIStringBundle.h"
|
||||
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "nsIURL.h"
|
||||
|
||||
#include "nsIconChannel.h"
|
||||
|
@ -83,7 +84,16 @@ moz_qicon_to_channel(QImage *image, nsIURI *aURI,
|
|||
rv = stream->AdoptData((char*)buf, buf_size);
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -125,6 +125,9 @@ MessageLoop::MessageLoop(Type type)
|
|||
pump_ = new mozilla::ipc::MessagePumpForNonMainUIThreads();
|
||||
return;
|
||||
#endif
|
||||
default:
|
||||
// Create one of Chromium's standard MessageLoop types below.
|
||||
break;
|
||||
}
|
||||
|
||||
#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,
|
||||
ReturnStatus *rs, nsTArray<nsString> *names) {
|
||||
return Answer::RecvGetPropertyKeys(ObjectId::deserialize(objId), flags, rs, names);
|
||||
ReturnStatus *rs, nsTArray<JSIDVariant> *ids) {
|
||||
return Answer::RecvGetPropertyKeys(ObjectId::deserialize(objId), flags, rs, ids);
|
||||
}
|
||||
bool RecvInstanceOf(const uint64_t &objId, const JSIID &iid,
|
||||
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,
|
||||
ReturnStatus *rs, nsTArray<nsString> *names) {
|
||||
return Base::SendGetPropertyKeys(objId.serialize(), flags, rs, names);
|
||||
ReturnStatus *rs, nsTArray<JSIDVariant> *ids) {
|
||||
return Base::SendGetPropertyKeys(objId.serialize(), flags, rs, ids);
|
||||
}
|
||||
bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
|
||||
ReturnStatus *rs, bool *instanceof) {
|
||||
|
|
|
@ -440,7 +440,8 @@ JavaScriptShared::toSymbolVariant(JSContext *cx, JS::Symbol *symArg, SymbolVaria
|
|||
*symVarp = RegisteredSymbol(autoStr);
|
||||
return true;
|
||||
}
|
||||
MOZ_CRASH("unique symbols not yet implemented");
|
||||
|
||||
JS_ReportError(cx, "unique symbol can't be used with CPOW");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ both:
|
|||
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 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 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
|
||||
WrapperAnswer::RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
||||
ReturnStatus *rs, nsTArray<nsString> *names)
|
||||
ReturnStatus *rs, nsTArray<JSIDVariant> *ids)
|
||||
{
|
||||
AutoSafeJSContext cx;
|
||||
JSAutoRequest request(cx);
|
||||
|
@ -598,11 +598,11 @@ WrapperAnswer::RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,
|
|||
return fail(cx, rs);
|
||||
|
||||
for (size_t i = 0; i < props.length(); i++) {
|
||||
nsString name;
|
||||
if (!convertIdToGeckoString(cx, props[i], &name))
|
||||
JSIDVariant id;
|
||||
if (!toJSIDVariant(cx, props[i], &id))
|
||||
return fail(cx, rs);
|
||||
|
||||
names->AppendElement(name);
|
||||
ids->AppendElement(id);
|
||||
}
|
||||
|
||||
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 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,
|
||||
ReturnStatus *rs, bool *instanceof);
|
||||
bool RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
||||
|
|
|
@ -63,9 +63,6 @@ class CPOWProxyHandler : public BaseProxyHandler
|
|||
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,
|
||||
MutableHandle<JSPropertyDescriptor> desc) const MOZ_OVERRIDE;
|
||||
virtual bool defineProperty(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
|
@ -74,18 +71,21 @@ class CPOWProxyHandler : public BaseProxyHandler
|
|||
AutoIdVector &props) 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 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 hasOwn(JSContext *cx, HandleObject proxy, HandleId id, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool get(JSContext *cx, HandleObject proxy, HandleObject receiver,
|
||||
HandleId id, MutableHandleValue vp) const MOZ_OVERRIDE;
|
||||
virtual bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
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 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,
|
||||
MutableHandleValue v, bool *bp) const MOZ_OVERRIDE;
|
||||
virtual bool objectClassIs(HandleObject obj, js::ESClassValue classValue,
|
||||
|
@ -232,7 +232,7 @@ CPOWProxyHandler::ownPropertyKeys(JSContext *cx, HandleObject proxy,
|
|||
bool
|
||||
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
|
||||
|
@ -463,13 +463,14 @@ WrapperOwner::set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiv
|
|||
}
|
||||
|
||||
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
|
||||
WrapperOwner::keys(JSContext *cx, HandleObject proxy, AutoIdVector &props)
|
||||
WrapperOwner::getOwnEnumerablePropertyKeys(JSContext *cx, HandleObject proxy, AutoIdVector &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);
|
||||
|
||||
ReturnStatus status;
|
||||
InfallibleTArray<nsString> names;
|
||||
if (!SendGetPropertyKeys(objId, flags, &status, &names))
|
||||
InfallibleTArray<JSIDVariant> ids;
|
||||
if (!SendGetPropertyKeys(objId, flags, &status, &ids))
|
||||
return ipcfail(cx);
|
||||
|
||||
LOG_STACK();
|
||||
|
@ -785,11 +786,11 @@ WrapperOwner::getPropertyKeys(JSContext *cx, HandleObject proxy, uint32_t flags,
|
|||
if (!ok(cx, status))
|
||||
return false;
|
||||
|
||||
for (size_t i = 0; i < names.Length(); i++) {
|
||||
RootedId name(cx);
|
||||
if (!convertGeckoStringToId(cx, names[i], &name))
|
||||
for (size_t i = 0; i < ids.Length(); i++) {
|
||||
RootedId id(cx);
|
||||
if (!fromJSIDVariant(cx, ids[i], &id))
|
||||
return false;
|
||||
if (!props.append(name))
|
||||
if (!props.append(id))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,11 +31,8 @@ class WrapperOwner : public virtual JavaScriptShared
|
|||
explicit WrapperOwner(JSRuntime *rt);
|
||||
bool init();
|
||||
|
||||
// Fundamental proxy traps. These are required.
|
||||
// Standard internal methods.
|
||||
// (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,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc);
|
||||
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 delete_(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, bool *bp);
|
||||
bool enumerate(JSContext *cx, JS::HandleObject proxy, JS::AutoIdVector &props);
|
||||
|
||||
// Derived proxy traps. Implementing these is useful for perfomance.
|
||||
bool isExtensible(JSContext *cx, JS::HandleObject proxy, bool *extensible);
|
||||
bool preventExtensions(JSContext *cx, JS::HandleObject proxy);
|
||||
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,
|
||||
JS::HandleId id, JS::MutableHandleValue vp);
|
||||
bool set(JSContext *cx, JS::HandleObject proxy, JS::HandleObject receiver,
|
||||
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 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 objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
|
||||
const char* className(JSContext *cx, JS::HandleObject proxy);
|
||||
bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g);
|
||||
bool isCallable(JSObject *obj);
|
||||
bool isConstructor(JSObject *obj);
|
||||
|
||||
|
@ -146,7 +145,7 @@ class WrapperOwner : public virtual JavaScriptShared
|
|||
uint32_t *flags) = 0;
|
||||
|
||||
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,
|
||||
ReturnStatus *rs, bool *instanceof) = 0;
|
||||
virtual bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
|
||||
|
|
|
@ -315,6 +315,7 @@ selfhosting_srcs := \
|
|||
$(srcdir)/builtin/Array.js \
|
||||
$(srcdir)/builtin/Date.js \
|
||||
$(srcdir)/builtin/Error.js \
|
||||
$(srcdir)/builtin/Generator.js \
|
||||
$(srcdir)/builtin/Intl.js \
|
||||
$(srcdir)/builtin/IntlData.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
|
||||
#
|
||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wall"
|
||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wignored-qualifiers"
|
||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wsign-compare"
|
||||
_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=empty-body"
|
||||
_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=missing-braces"
|
||||
_WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Werror=overloaded-virtual"
|
||||
|
|
|
@ -2625,8 +2625,8 @@ ImplicitConvert(JSContext* cx,
|
|||
if (val.isObject() && !sourceData) {
|
||||
// Enumerate the properties of the object; if they match the struct
|
||||
// specification, convert the fields.
|
||||
RootedObject iter(cx, JS_NewPropertyIterator(cx, valObj));
|
||||
if (!iter)
|
||||
AutoIdArray props(cx, JS_Enumerate(cx, valObj));
|
||||
if (!props)
|
||||
return false;
|
||||
|
||||
// Convert into an intermediate, in case of failure.
|
||||
|
@ -2637,13 +2637,15 @@ ImplicitConvert(JSContext* cx,
|
|||
return false;
|
||||
}
|
||||
|
||||
const FieldInfoHash* fields = StructType::GetFieldInfo(targetType);
|
||||
if (props.length() != fields->count()) {
|
||||
JS_ReportError(cx, "missing fields");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedId id(cx);
|
||||
size_t i = 0;
|
||||
while (1) {
|
||||
if (!JS_NextProperty(cx, iter, &id))
|
||||
return false;
|
||||
if (JSID_IS_VOID(id))
|
||||
break;
|
||||
for (size_t i = 0; i < props.length(); ++i) {
|
||||
id = props[i];
|
||||
|
||||
if (!JSID_IS_STRING(id)) {
|
||||
JS_ReportError(cx, "property name is not a string");
|
||||
|
@ -2663,14 +2665,6 @@ ImplicitConvert(JSContext* cx,
|
|||
char* fieldData = intermediate.get() + field->mOffset;
|
||||
if (!ImplicitConvert(cx, prop, field->mType, fieldData, false, nullptr))
|
||||
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);
|
||||
|
@ -4705,33 +4699,23 @@ ExtractStructField(JSContext* cx, jsval val, MutableHandleObject typeObj)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RootedObject obj(cx, val.toObjectOrNull());
|
||||
RootedObject iter(cx, JS_NewPropertyIterator(cx, obj));
|
||||
if (!iter)
|
||||
RootedObject obj(cx, &val.toObject());
|
||||
AutoIdArray props(cx, JS_Enumerate(cx, obj));
|
||||
if (!props)
|
||||
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
|
||||
RootedId id(cx);
|
||||
if (!JS_NextProperty(cx, iter, &id))
|
||||
return nullptr;
|
||||
if (!JSID_IS_VOID(id)) {
|
||||
if (props.length() != 1) {
|
||||
JS_ReportError(cx, "struct field descriptors must contain one property");
|
||||
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);
|
||||
if (!JS_GetPropertyById(cx, obj, nameid, &propVal))
|
||||
return nullptr;
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "frontend/Parser.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
#include "vm/Stack.h"
|
||||
|
||||
#include "jsatominlines.h"
|
||||
|
@ -1989,10 +1990,10 @@ CheckSideEffects(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool
|
|||
|
||||
default:
|
||||
/*
|
||||
* All of PNK_INC, PNK_DEC, PNK_THROW, PNK_YIELD, and PNK_YIELD_STAR
|
||||
* have direct effects. Of the remaining unary-arity node types, we
|
||||
* can't easily prove that the operand never denotes an object with
|
||||
* a toString or valueOf method.
|
||||
* All of PNK_INC, PNK_DEC and PNK_THROW have direct effects. Of
|
||||
* the remaining unary-arity node types, we can't easily prove that
|
||||
* the operand never denotes an object with a toString or valueOf
|
||||
* method.
|
||||
*/
|
||||
*answer = true;
|
||||
return true;
|
||||
|
@ -2973,13 +2974,6 @@ frontend::EmitFunctionScript(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNo
|
|||
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
|
||||
* 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))
|
||||
return false;
|
||||
|
||||
// If we fall off the end of an ES6 generator, return a boxed iterator
|
||||
// result object of the form { value: undefined, done: true }.
|
||||
if (bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isStarGenerator()) {
|
||||
if (!EmitPrepareIteratorResult(cx, bce))
|
||||
// If we fall off the end of a generator, do a final yield.
|
||||
if (bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isGenerator()) {
|
||||
if (bce->sc->asFunctionBox()->isStarGenerator() && !EmitPrepareIteratorResult(cx, bce))
|
||||
return false;
|
||||
|
||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0)
|
||||
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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -5463,15 +5466,26 @@ EmitReturn(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
*/
|
||||
ptrdiff_t top = bce->offset();
|
||||
|
||||
if (Emit1(cx, bce, JSOP_RETURN) < 0)
|
||||
return false;
|
||||
bool isGenerator = bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->isGenerator();
|
||||
if (Emit1(cx, bce, isGenerator ? JSOP_SETRVAL : JSOP_RETURN) < 0)
|
||||
return false;
|
||||
|
||||
NonLocalExitScope nle(cx, bce);
|
||||
|
||||
if (!nle.prepareForNonLocalJump(nullptr))
|
||||
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;
|
||||
if (Emit1(cx, bce, JSOP_RETRVAL) < 0)
|
||||
return false;
|
||||
|
@ -5481,7 +5495,41 @@ EmitReturn(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
}
|
||||
|
||||
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->asFunctionBox()->isStarGenerator());
|
||||
|
@ -5500,12 +5548,13 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
|||
return false;
|
||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||
|
||||
int depth = bce->stackDepth;
|
||||
MOZ_ASSERT(depth >= 1);
|
||||
|
||||
// Initial send value is undefined.
|
||||
if (Emit1(cx, bce, JSOP_UNDEFINED) < 0) // ITER RECEIVED
|
||||
return false;
|
||||
|
||||
int depth = bce->stackDepth;
|
||||
MOZ_ASSERT(depth >= 2);
|
||||
|
||||
ptrdiff_t initialSend = -1;
|
||||
if (EmitBackPatchOp(cx, bce, &initialSend) < 0) // goto initialSend
|
||||
return false;
|
||||
|
@ -5514,17 +5563,21 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
|||
StmtInfoBCE stmtInfo(cx);
|
||||
PushStatementBCE(bce, &stmtInfo, STMT_TRY, bce->offset());
|
||||
ptrdiff_t noteIndex = NewSrcNote(cx, bce, SRC_TRY);
|
||||
ptrdiff_t tryStart = bce->offset(); // tryStart:
|
||||
if (noteIndex < 0 || Emit1(cx, bce, JSOP_TRY) < 0)
|
||||
return false;
|
||||
ptrdiff_t tryStart = bce->offset(); // tryStart:
|
||||
MOZ_ASSERT(bce->stackDepth == depth + 1);
|
||||
MOZ_ASSERT(bce->stackDepth == depth);
|
||||
|
||||
// Load the generator object.
|
||||
if (!EmitTree(cx, bce, gen)) // ITER RESULT GENOBJ
|
||||
return false;
|
||||
|
||||
// Yield RESULT as-is, without re-boxing.
|
||||
if (Emit1(cx, bce, JSOP_YIELD) < 0) // ITER RECEIVED
|
||||
return false;
|
||||
|
||||
// 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;
|
||||
ptrdiff_t subsequentSend = -1;
|
||||
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:
|
||||
|
||||
// Catch location.
|
||||
// THROW? = 'throw' in ITER // ITER
|
||||
bce->stackDepth = (uint32_t) depth;
|
||||
bce->stackDepth = uint32_t(depth); // ITER RESULT
|
||||
if (Emit1(cx, bce, JSOP_POP) < 0) // ITER
|
||||
return false;
|
||||
// THROW? = 'throw' in ITER
|
||||
if (Emit1(cx, bce, JSOP_EXCEPTION) < 0) // ITER EXCEPTION
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_SWAP) < 0) // EXCEPTION ITER
|
||||
|
@ -5557,7 +5612,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
|||
|
||||
SetJumpOffsetAt(bce, checkThrow); // delegate:
|
||||
// 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
|
||||
return false;
|
||||
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
|
||||
return false;
|
||||
CheckTypeSet(cx, bce, JSOP_CALL);
|
||||
MOZ_ASSERT(bce->stackDepth == depth + 1);
|
||||
MOZ_ASSERT(bce->stackDepth == depth);
|
||||
ptrdiff_t checkResult = -1;
|
||||
if (EmitBackPatchOp(cx, bce, &checkResult) < 0) // goto checkResult
|
||||
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.
|
||||
if (Emit1(cx, bce, JSOP_NOP) < 0)
|
||||
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;
|
||||
|
||||
// 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
|
||||
return false;
|
||||
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:
|
||||
return false;
|
||||
|
@ -5629,7 +5684,7 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter)
|
|||
if (!EmitAtomOp(cx, cx->names().value, JSOP_GETPROP, bce)) // VALUE
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(bce->stackDepth == depth);
|
||||
MOZ_ASSERT(bce->stackDepth == depth - 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -5807,6 +5862,80 @@ EmitDelete(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
static bool
|
||||
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
|
||||
EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
{
|
||||
|
@ -5835,46 +5964,21 @@ EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool emitArgs = true;
|
||||
ParseNode *pn2 = pn->pn_head;
|
||||
bool spread = JOF_OPTYPE(pn->getOp()) == JOF_BYTE;
|
||||
switch (pn2->getKind()) {
|
||||
case PNK_NAME:
|
||||
if (bce->emitterMode == BytecodeEmitter::SelfHosting &&
|
||||
pn2->name() == cx->names().callFunction &&
|
||||
!spread)
|
||||
{
|
||||
/*
|
||||
* 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 *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 (bce->emitterMode == BytecodeEmitter::SelfHosting && !spread) {
|
||||
// We shouldn't see foo(bar) = x in self-hosted code.
|
||||
MOZ_ASSERT(!(pn->pn_xflags & PNX_SETCALL));
|
||||
|
||||
// Calls to "callFunction" or "resumeGenerator" in self-hosted code
|
||||
// generate inline bytecode.
|
||||
if (pn2->name() == cx->names().callFunction)
|
||||
return EmitSelfHostedCallFunction(cx, bce, pn);
|
||||
if (pn2->name() == cx->names().resumeGenerator)
|
||||
return EmitSelfHostedResumeGenerator(cx, bce, pn);
|
||||
// Fall through.
|
||||
}
|
||||
if (!EmitNameOp(cx, bce, pn2, callop))
|
||||
return false;
|
||||
|
@ -5922,25 +6026,23 @@ EmitCallOrNew(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (emitArgs) {
|
||||
/*
|
||||
* 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
|
||||
* were pushed on the operand stack.
|
||||
*/
|
||||
bool oldEmittingForInit = bce->emittingForInit;
|
||||
bce->emittingForInit = false;
|
||||
if (!spread) {
|
||||
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!EmitArray(cx, bce, pn2->pn_next, argc))
|
||||
/*
|
||||
* 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
|
||||
* were pushed on the operand stack.
|
||||
*/
|
||||
bool oldEmittingForInit = bce->emittingForInit;
|
||||
bce->emittingForInit = false;
|
||||
if (!spread) {
|
||||
for (ParseNode *pn3 = pn2->pn_next; pn3; pn3 = pn3->pn_next) {
|
||||
if (!EmitTree(cx, bce, pn3))
|
||||
return false;
|
||||
}
|
||||
bce->emittingForInit = oldEmittingForInit;
|
||||
} else {
|
||||
if (!EmitArray(cx, bce, pn2->pn_next, argc))
|
||||
return false;
|
||||
}
|
||||
bce->emittingForInit = oldEmittingForInit;
|
||||
|
||||
if (!spread) {
|
||||
if (EmitCall(cx, bce, pn->getOp(), argc, pn) < 0)
|
||||
|
@ -6687,28 +6789,16 @@ frontend::EmitTree(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
break;
|
||||
|
||||
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;
|
||||
|
||||
case PNK_YIELD:
|
||||
MOZ_ASSERT(bce->sc->isFunctionBox());
|
||||
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;
|
||||
ok = EmitYield(cx, bce, pn);
|
||||
break;
|
||||
|
||||
case PNK_STATEMENTLIST:
|
||||
|
|
|
@ -323,6 +323,17 @@ class FullParseHandler
|
|||
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
|
||||
|
||||
ParseNode *newStatementList(unsigned blockid, const TokenPos &pos) {
|
||||
|
@ -352,6 +363,31 @@ class FullParseHandler
|
|||
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) {
|
||||
return new_<UnaryNode>(PNK_SEMI, JSOP_NOP, pos, (ParseNode *) nullptr);
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ class UpvarCookie
|
|||
F(FINALLY) \
|
||||
F(THROW) \
|
||||
F(DEBUGGER) \
|
||||
F(GENERATOR) \
|
||||
F(YIELD) \
|
||||
F(YIELD_STAR) \
|
||||
F(GENEXP) \
|
||||
|
@ -422,6 +423,9 @@ enum ParseNodeKind
|
|||
*
|
||||
* PNK_LEXICALSCOPE name pn_objbox: block object in ObjectBox holder
|
||||
* 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
|
||||
* pn_head: list of 1 element, which is block
|
||||
* enclosing for loop(s) and optionally
|
||||
|
@ -773,8 +777,9 @@ class ParseNode
|
|||
MOZ_ASSERT(isKind(PNK_GENEXP));
|
||||
ParseNode *callee = this->pn_head;
|
||||
ParseNode *body = callee->pn_body;
|
||||
MOZ_ASSERT(body->isKind(PNK_LEXICALSCOPE) || body->isKind(PNK_FOR));
|
||||
return body;
|
||||
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
|
||||
MOZ_ASSERT(body->last()->isKind(PNK_LEXICALSCOPE) || body->last()->isKind(PNK_FOR));
|
||||
return body->last();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1035,6 +1035,23 @@ Parser<ParseHandler>::functionBody(FunctionSyntaxKind kind, FunctionBodyType typ
|
|||
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. */
|
||||
if (!checkFunctionArguments())
|
||||
return null();
|
||||
|
@ -5007,6 +5024,21 @@ Parser<ParseHandler>::returnStatement()
|
|||
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>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::yieldExpression()
|
||||
|
@ -5052,7 +5084,7 @@ Parser<ParseHandler>::yieldExpression()
|
|||
if (!exprNode)
|
||||
return null();
|
||||
}
|
||||
return handler.newUnary(kind, JSOP_NOP, begin, exprNode);
|
||||
return newYieldExpression(begin, exprNode, kind == PNK_YIELD_STAR);
|
||||
}
|
||||
|
||||
case NotGenerator:
|
||||
|
@ -5110,7 +5142,7 @@ Parser<ParseHandler>::yieldExpression()
|
|||
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);
|
||||
#endif
|
||||
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
|
||||
* definition or placeholder outside the generator, but now
|
||||
|
@ -6304,7 +6344,7 @@ LegacyComprehensionHeadBlockScopeDepth(ParseContext<ParseHandler> *pc)
|
|||
*/
|
||||
template <>
|
||||
ParseNode *
|
||||
Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyStmt, unsigned blockid,
|
||||
Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyExpr, unsigned blockid,
|
||||
GeneratorKind comprehensionKind,
|
||||
ParseContext<FullParseHandler> *outerpc,
|
||||
unsigned innerBlockScopeDepth)
|
||||
|
@ -6368,15 +6408,15 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyStmt, unsigned
|
|||
adjust = blockid - adjust;
|
||||
}
|
||||
|
||||
handler.setBeginPosition(pn, bodyStmt);
|
||||
handler.setBeginPosition(pn, bodyExpr);
|
||||
|
||||
pnp = &pn->pn_expr;
|
||||
|
||||
LegacyCompExprTransplanter transplanter(bodyStmt, this, outerpc, comprehensionKind, adjust);
|
||||
LegacyCompExprTransplanter transplanter(bodyExpr, this, outerpc, comprehensionKind, adjust);
|
||||
if (!transplanter.init())
|
||||
return null();
|
||||
|
||||
if (!transplanter.transplant(bodyStmt))
|
||||
if (!transplanter.transplant(bodyExpr))
|
||||
return null();
|
||||
|
||||
MOZ_ASSERT(pc->staticScope && pc->staticScope == pn->pn_objbox->object);
|
||||
|
@ -6532,6 +6572,23 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyStmt, unsigned
|
|||
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;
|
||||
|
||||
pc->topStmt->innerBlockScopeDepth += innerBlockScopeDepth;
|
||||
|
@ -6568,12 +6625,7 @@ Parser<FullParseHandler>::legacyArrayComprehension(ParseNode *array)
|
|||
array->pn_tail = &array->pn_head;
|
||||
*array->pn_tail = nullptr;
|
||||
|
||||
ParseNode *arrayPush = handler.newUnary(PNK_ARRAYPUSH, JSOP_ARRAYPUSH,
|
||||
bodyExpr->pn_pos.begin, bodyExpr);
|
||||
if (!arrayPush)
|
||||
return null();
|
||||
|
||||
ParseNode *comp = legacyComprehensionTail(arrayPush, array->pn_blockid, NotGenerator,
|
||||
ParseNode *comp = legacyComprehensionTail(bodyExpr, array->pn_blockid, NotGenerator,
|
||||
nullptr, LegacyComprehensionHeadBlockScopeDepth(pc));
|
||||
if (!comp)
|
||||
return null();
|
||||
|
@ -6596,10 +6648,10 @@ Parser<SyntaxParseHandler>::legacyArrayComprehension(Node array)
|
|||
template <typename ParseHandler>
|
||||
typename ParseHandler::Node
|
||||
Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKind,
|
||||
unsigned begin, Node innerStmt)
|
||||
unsigned begin, Node innerExpr)
|
||||
{
|
||||
MOZ_ASSERT(comprehensionKind == LegacyGenerator || comprehensionKind == StarGenerator);
|
||||
MOZ_ASSERT(!!innerStmt == (comprehensionKind == LegacyGenerator));
|
||||
MOZ_ASSERT(!!innerExpr == (comprehensionKind == LegacyGenerator));
|
||||
|
||||
Node genfn = handler.newFunctionDefinition();
|
||||
if (!genfn)
|
||||
|
@ -6650,29 +6702,47 @@ Parser<ParseHandler>::generatorComprehensionLambda(GeneratorKind comprehensionKi
|
|||
genFunbox->inGenexpLambda = true;
|
||||
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) {
|
||||
body = comprehension(StarGenerator);
|
||||
if (!body)
|
||||
comp = comprehension(StarGenerator);
|
||||
if (!comp)
|
||||
return null();
|
||||
} else {
|
||||
MOZ_ASSERT(comprehensionKind == LegacyGenerator);
|
||||
body = legacyComprehensionTail(innerStmt, outerpc->blockid(), LegacyGenerator,
|
||||
comp = legacyComprehensionTail(innerExpr, outerpc->blockid(), LegacyGenerator,
|
||||
outerpc, LegacyComprehensionHeadBlockScopeDepth(outerpc));
|
||||
if (!body)
|
||||
if (!comp)
|
||||
return null();
|
||||
}
|
||||
|
||||
if (comprehensionKind == StarGenerator)
|
||||
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.setBeginPosition(genfn, begin);
|
||||
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
|
||||
// need to propagate the closed-over variable set to the inner
|
||||
// lazyscript, as in finishFunctionDefinition.
|
||||
|
@ -6709,19 +6779,8 @@ Parser<FullParseHandler>::legacyGeneratorExpr(ParseNode *expr)
|
|||
{
|
||||
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. */
|
||||
ParseNode *genfn = generatorComprehensionLambda(LegacyGenerator, expr->pn_pos.begin, yieldStmt);
|
||||
ParseNode *genfn = generatorComprehensionLambda(LegacyGenerator, expr->pn_pos.begin, expr);
|
||||
if (!genfn)
|
||||
return null();
|
||||
|
||||
|
@ -6871,7 +6930,7 @@ Parser<ParseHandler>::comprehensionTail(GeneratorKind comprehensionKind)
|
|||
return handler.newUnary(PNK_ARRAYPUSH, JSOP_ARRAYPUSH, begin, bodyExpr);
|
||||
|
||||
MOZ_ASSERT(comprehensionKind == StarGenerator);
|
||||
Node yieldExpr = handler.newUnary(PNK_YIELD, JSOP_NOP, begin, bodyExpr);
|
||||
Node yieldExpr = newYieldExpression(begin, bodyExpr);
|
||||
if (!yieldExpr)
|
||||
return null();
|
||||
handler.setInParens(yieldExpr);
|
||||
|
|
|
@ -464,6 +464,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
|
|||
bool addExprAndGetNextTemplStrToken(Node nodeList, TokenKind &tt);
|
||||
|
||||
inline Node newName(PropertyName *name);
|
||||
inline Node newYieldExpression(uint32_t begin, Node expr, bool isYieldStar = false);
|
||||
|
||||
inline bool abortIfSyntaxParser();
|
||||
|
||||
|
|
|
@ -135,11 +135,14 @@ class SyntaxParseHandler
|
|||
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 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
|
||||
|
||||
Node newStatementList(unsigned blockid, const TokenPos &pos) { return NodeGeneric; }
|
||||
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 newExprStatement(Node expr, uint32_t end) {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* - writes to object properties
|
||||
* - writes to array slots
|
||||
* - 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
|
||||
* markable data
|
||||
* 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
|
||||
// does not close the generator-iterator.
|
||||
// does closes the generator-iterator.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
|
||||
|
@ -17,4 +18,4 @@ var rv = gw.evalInGlobal("it.next();");
|
|||
assertEq(rv.throw, "fit");
|
||||
|
||||
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
|
||||
// does not close the generator-iterator.
|
||||
// closes the generator-iterator.
|
||||
|
||||
load(libdir + "iteration.js");
|
||||
|
||||
|
@ -17,4 +17,4 @@ var rv = gw.evalInGlobal("it.next();");
|
|||
assertEq(rv.throw, "fit");
|
||||
|
||||
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.
|
||||
|
||||
var g = newGlobal();
|
||||
|
@ -10,5 +11,9 @@ function gen() {
|
|||
debugger; // Force return here. The value is ignored.
|
||||
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.
|
||||
|
||||
load(libdir + 'asserts.js')
|
||||
|
@ -16,4 +17,5 @@ function* gen() {
|
|||
var iter = gen();
|
||||
assertIteratorNext(iter, '1');
|
||||
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.parent.functionDisplayName, "generator");
|
||||
assertEq(frame.parent.parent.functionDisplayName, "iife1");
|
||||
assertEq(frame.parent.parent.parent.functionDisplayName, null);
|
||||
assertEq(frame.parent.parent.parent.parent, null);
|
||||
assertEq(frame.parent.parent.functionDisplayName, "next");
|
||||
assertEq(frame.parent.parent.parent.functionDisplayName, "iife1");
|
||||
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));
|
||||
|
||||
*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 ||
|
||||
retval == BAILOUT_RETURN_FATAL_ERROR ||
|
||||
retval == BAILOUT_RETURN_OVERRECURSED);
|
||||
|
@ -68,7 +70,8 @@ jit::Bailout(BailoutStack *sp, BaselineBailoutInfo **bailoutInfo)
|
|||
// pseudostack frame would not have been pushed in the first
|
||||
// place, so don't pop anything in that case.
|
||||
bool popSPSFrame = iter.ionScript()->hasSPSInstrumentation() &&
|
||||
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck);
|
||||
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck) &&
|
||||
!poppedLastSPSFrame;
|
||||
JSScript *script = iter.script();
|
||||
probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
|
||||
|
||||
|
@ -105,7 +108,9 @@ jit::InvalidationBailout(InvalidationBailoutStack *sp, size_t *frameSizeOut,
|
|||
MOZ_ASSERT(IsBaselineEnabled(cx));
|
||||
|
||||
*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 ||
|
||||
retval == BAILOUT_RETURN_FATAL_ERROR ||
|
||||
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
|
||||
// place, so don't pop anything in that case.
|
||||
bool popSPSFrame = iter.ionScript()->hasSPSInstrumentation() &&
|
||||
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck);
|
||||
(SnapshotIterator(iter).bailoutKind() != Bailout_ArgumentCheck) &&
|
||||
!poppedLastSPSFrame;
|
||||
JSScript *script = iter.script();
|
||||
probes::ExitScript(cx, script, script->functionNonDelazifying(), popSPSFrame);
|
||||
|
||||
|
@ -180,7 +186,9 @@ jit::ExceptionHandlerBailout(JSContext *cx, const InlineFrameIterator &frame,
|
|||
JitFrameIterator iter(jitActivations);
|
||||
|
||||
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) {
|
||||
MOZ_ASSERT(bailoutInfo);
|
||||
|
|
|
@ -515,9 +515,12 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
|||
HandleFunction fun, HandleScript script, IonScript *ionScript,
|
||||
SnapshotIterator &iter, bool invalidate, BaselineStackBuilder &builder,
|
||||
AutoValueVector &startFrameFormals, MutableHandleFunction nextCallee,
|
||||
jsbytecode **callPC, const ExceptionBailoutInfo *excInfo)
|
||||
jsbytecode **callPC, const ExceptionBailoutInfo *excInfo,
|
||||
bool *poppedLastSPSFrameOut)
|
||||
{
|
||||
MOZ_ASSERT(script->hasBaselineScript());
|
||||
MOZ_ASSERT(poppedLastSPSFrameOut);
|
||||
MOZ_ASSERT(!*poppedLastSPSFrameOut);
|
||||
|
||||
// Are we catching an exception?
|
||||
bool catchingException = excInfo && excInfo->catchingException();
|
||||
|
@ -1035,6 +1038,11 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
|||
JitSpew(JitSpew_BaselineBailouts,
|
||||
" Popping SPS entry for outermost frame");
|
||||
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 {
|
||||
|
@ -1291,7 +1299,7 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
|
|||
uint32_t
|
||||
jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
|
||||
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
|
||||
// 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(poppedLastSPSFrameOut);
|
||||
MOZ_ASSERT(!*poppedLastSPSFrameOut);
|
||||
|
||||
TraceLogger *logger = TraceLoggerForMainThread(cx->runtime());
|
||||
TraceLogStopEvent(logger, TraceLogger::IonMonkey);
|
||||
TraceLogStartEvent(logger, TraceLogger::Baseline);
|
||||
|
@ -1429,7 +1440,8 @@ jit::BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIter
|
|||
RootedFunction nextCallee(cx, nullptr);
|
||||
if (!InitFromBailout(cx, caller, callerPC, fun, scr, iter.ionScript(),
|
||||
snapIter, invalidate, builder, startFrameFormals,
|
||||
&nextCallee, &callPC, passExcInfo ? excInfo : nullptr))
|
||||
&nextCallee, &callPC, passExcInfo ? excInfo : nullptr,
|
||||
poppedLastSPSFrameOut))
|
||||
{
|
||||
return BAILOUT_RETURN_FATAL_ERROR;
|
||||
}
|
||||
|
|
|
@ -323,16 +323,13 @@ jit::CanEnterBaselineMethod(JSContext *cx, RunState &state)
|
|||
|
||||
if (!state.maybeCreateThisForConstructor(cx))
|
||||
return Method_Skipped;
|
||||
} else if (state.isExecute()) {
|
||||
} else {
|
||||
MOZ_ASSERT(state.isExecute());
|
||||
ExecuteType type = state.asExecute()->type();
|
||||
if (type == EXECUTE_DEBUG || type == EXECUTE_DEBUG_GLOBAL) {
|
||||
JitSpew(JitSpew_BaselineAbort, "debugger frame");
|
||||
return Method_CantCompile;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(state.isGenerator());
|
||||
JitSpew(JitSpew_BaselineAbort, "generator frame");
|
||||
return Method_CantCompile;
|
||||
}
|
||||
|
||||
RootedScript script(cx, state.script());
|
||||
|
|
|
@ -439,7 +439,8 @@ struct BaselineBailoutInfo
|
|||
uint32_t
|
||||
BailoutIonToBaseline(JSContext *cx, JitActivation *activation, JitFrameIterator &iter,
|
||||
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
|
||||
// during GC.
|
||||
|
|
|
@ -2401,10 +2401,6 @@ jit::CanEnter(JSContext *cx, RunState &state)
|
|||
|
||||
if (!state.maybeCreateThisForConstructor(cx))
|
||||
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
|
||||
|
|
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);
|
||||
}
|
||||
|
||||
/* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
|
||||
/*
|
||||
* Wrapper functions to create wrappers with no corresponding JSJitInfo from API
|
||||
* function arguments.
|
||||
*/
|
||||
static JSPropertyOpWrapper
|
||||
|
@ -2825,8 +2826,6 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val
|
|||
MOZ_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
||||
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);
|
||||
attrs &= ~JSPROP_NATIVE_ACCESSORS;
|
||||
if (getter) {
|
||||
|
@ -2863,12 +2862,12 @@ DefinePropertyById(JSContext *cx, HandleObject obj, HandleId id, HandleValue val
|
|||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj, id, value,
|
||||
(attrs & JSPROP_GETTER)
|
||||
? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
|
||||
: nullptr,
|
||||
(attrs & JSPROP_SETTER)
|
||||
? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
|
||||
: nullptr);
|
||||
(attrs & JSPROP_GETTER)
|
||||
? JS_FUNC_TO_DATA_PTR(JSObject *, getter)
|
||||
: nullptr,
|
||||
(attrs & JSPROP_SETTER)
|
||||
? JS_FUNC_TO_DATA_PTR(JSObject *, setter)
|
||||
: nullptr);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
DefineSelfHostedProperty(JSContext *cx,
|
||||
HandleObject obj,
|
||||
const char *name,
|
||||
const char *getterName,
|
||||
const char *setterName,
|
||||
unsigned attrs,
|
||||
unsigned flags)
|
||||
DefineSelfHostedProperty(JSContext *cx, HandleObject obj, HandleId id,
|
||||
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)));
|
||||
if (!getterNameAtom)
|
||||
return false;
|
||||
|
||||
RootedValue getterValue(cx);
|
||||
if (!cx->global()->getSelfHostedFunction(cx, getterNameAtom, nameAtom,
|
||||
0, &getterValue))
|
||||
{
|
||||
RootedAtom name(cx, IdToFunctionName(cx, id));
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
RootedValue getterValue(cx);
|
||||
if (!cx->global()->getSelfHostedFunction(cx, getterNameAtom, name, 0, &getterValue))
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(getterValue.isObject() && getterValue.toObject().is<JSFunction>());
|
||||
RootedFunction getterFunc(cx, &getterValue.toObject().as<JSFunction>());
|
||||
JSPropertyOp getterOp = JS_DATA_TO_FUNC_PTR(PropertyOp, getterFunc.get());
|
||||
|
@ -3047,19 +3038,16 @@ DefineSelfHostedProperty(JSContext *cx,
|
|||
return false;
|
||||
|
||||
RootedValue setterValue(cx);
|
||||
if (!cx->global()->getSelfHostedFunction(cx, setterNameAtom, nameAtom,
|
||||
0, &setterValue))
|
||||
{
|
||||
if (!cx->global()->getSelfHostedFunction(cx, setterNameAtom, name, 0, &setterValue))
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(setterValue.isObject() && setterValue.toObject().is<JSFunction>());
|
||||
setterFunc = &getterValue.toObject().as<JSFunction>();
|
||||
}
|
||||
JSStrictPropertyOp setterOp = JS_DATA_TO_FUNC_PTR(StrictPropertyOp, setterFunc.get());
|
||||
|
||||
return DefineProperty(cx, obj, name, JS::UndefinedHandleValue,
|
||||
GetterWrapper(getterOp), SetterWrapper(setterOp),
|
||||
attrs, flags);
|
||||
return DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue,
|
||||
GetterWrapper(getterOp), SetterWrapper(setterOp),
|
||||
attrs, flags);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
@ -3256,37 +3244,81 @@ JS_DefineConstIntegers(JSContext *cx, HandleObject obj, const JSConstIntegerSpec
|
|||
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_DefineProperties(JSContext *cx, HandleObject obj, const JSPropertySpec *ps)
|
||||
{
|
||||
bool ok;
|
||||
for (ok = true; ps->name; ps++) {
|
||||
RootedId id(cx);
|
||||
|
||||
for (; ps->name; ps++) {
|
||||
if (!PropertySpecNameToId(cx, ps->name, &id))
|
||||
return false;
|
||||
|
||||
if (ps->flags & JSPROP_NATIVE_ACCESSORS) {
|
||||
// If you declare native accessors, then you should have a native
|
||||
// getter.
|
||||
MOZ_ASSERT(ps->getter.propertyOp.op);
|
||||
|
||||
// If you do not have a self-hosted getter, you should not have a
|
||||
// self-hosted setter. This is the closest approximation to that
|
||||
// assertion we can have with our setup.
|
||||
MOZ_ASSERT_IF(ps->setter.propertyOp.info, ps->setter.propertyOp.op);
|
||||
|
||||
ok = DefineProperty(cx, obj, ps->name, JS::UndefinedHandleValue,
|
||||
ps->getter.propertyOp, ps->setter.propertyOp, ps->flags, 0);
|
||||
if (!DefinePropertyById(cx, obj, id, JS::UndefinedHandleValue,
|
||||
ps->getter.propertyOp, ps->setter.propertyOp, ps->flags, 0))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// If you have self-hosted getter/setter, you can't have a
|
||||
// native one.
|
||||
MOZ_ASSERT(!ps->getter.propertyOp.op && !ps->setter.propertyOp.op);
|
||||
MOZ_ASSERT(ps->flags & JSPROP_GETTER);
|
||||
|
||||
ok = DefineSelfHostedProperty(cx, obj, ps->name,
|
||||
if (!DefineSelfHostedProperty(cx, obj, id,
|
||||
ps->getter.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)
|
||||
|
@ -3620,137 +3652,6 @@ JS_Enumerate(JSContext *cx, HandleObject obj)
|
|||
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_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::GetSelfHostedFunction(JSContext *cx, const char *selfHostedName, HandleId id, unsigned nargs)
|
||||
{
|
||||
MOZ_ASSERT(JSID_IS_STRING(id));
|
||||
MOZ_ASSERT(!cx->runtime()->isAtomsCompartment(cx->compartment()));
|
||||
AssertHeapIsIdle(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)));
|
||||
if (!shName)
|
||||
return nullptr;
|
||||
|
@ -4068,21 +3971,11 @@ JS_DefineFunctions(JSContext *cx, HandleObject obj, const JSFunctionSpec *fs)
|
|||
CHECK_REQUEST(cx);
|
||||
assertSameCompartment(cx, obj);
|
||||
|
||||
RootedId id(cx);
|
||||
for (; fs->name; fs++) {
|
||||
RootedAtom atom(cx);
|
||||
// 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)
|
||||
if (!PropertySpecNameToId(cx, fs->name, &id))
|
||||
return false;
|
||||
|
||||
Rooted<jsid> id(cx, AtomToId(atom));
|
||||
|
||||
/*
|
||||
* Define a generic arity N+1 static method for the arity N prototype
|
||||
* 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)));
|
||||
if (!shName)
|
||||
return false;
|
||||
RootedAtom name(cx, IdToFunctionName(cx, id));
|
||||
if (!name)
|
||||
return false;
|
||||
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;
|
||||
if (!JSObject::defineGeneric(cx, obj, id, funVal, nullptr, nullptr, flags))
|
||||
return false;
|
||||
|
@ -5628,6 +5524,33 @@ JS::GetWellKnownSymbol(JSContext *cx, JS::SymbolCode 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_Stringify(JSContext *cx, MutableHandleValue vp, HandleObject replacer,
|
||||
HandleValue space, JSONWriteCallback callback, void *data)
|
||||
|
|
|
@ -2475,15 +2475,27 @@ struct JSFunctionSpec {
|
|||
* JSFUN_STUB_GSOPS. JS_FNINFO allows the simple adding of
|
||||
* JSJitInfos. JS_SELF_HOSTED_FN declares a self-hosted function. Finally
|
||||
* 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) \
|
||||
JS_FNSPEC(name, call, nullptr, nargs, flags, nullptr)
|
||||
#define JS_FN(name,call,nargs,flags) \
|
||||
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) \
|
||||
JS_FNSPEC(name, call, info, nargs, flags, nullptr)
|
||||
#define JS_SELF_HOSTED_FN(name,selfHostedName,nargs,flags) \
|
||||
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) \
|
||||
{name, {call, info}, nargs, flags, selfHostedName}
|
||||
|
||||
|
@ -3305,22 +3317,6 @@ JS_ReleaseMappedArrayBufferContents(void *contents, size_t length);
|
|||
extern JS_PUBLIC_API(JSIdArray *)
|
||||
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)
|
||||
JS_GetReservedSlot(JSObject *obj, uint32_t index);
|
||||
|
||||
|
@ -4510,6 +4506,31 @@ GetSymbolCode(Handle<Symbol*> symbol);
|
|||
JS_PUBLIC_API(Symbol *)
|
||||
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 */
|
||||
|
||||
/************************************************************************/
|
||||
|
|
|
@ -58,7 +58,6 @@ const char js_break_str[] = "break";
|
|||
const char js_case_str[] = "case";
|
||||
const char js_catch_str[] = "catch";
|
||||
const char js_class_str[] = "class";
|
||||
const char js_close_str[] = "close";
|
||||
const char js_const_str[] = "const";
|
||||
const char js_continue_str[] = "continue";
|
||||
const char js_debugger_str[] = "debugger";
|
||||
|
|
|
@ -1109,11 +1109,10 @@ JSContext::JSContext(JSRuntime *rt)
|
|||
data(nullptr),
|
||||
data2(nullptr),
|
||||
outstandingRequests(0),
|
||||
jitIsBroken(false),
|
||||
jitIsBroken(false)
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
functionCallback(nullptr),
|
||||
, functionCallback(nullptr)
|
||||
#endif
|
||||
innermostGenerator_(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(static_cast<ContextFriendFields*>(this) ==
|
||||
ContextFriendFields::get(this));
|
||||
|
@ -1146,23 +1145,6 @@ JSContext::isThrowingOutOfMemory()
|
|||
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
|
||||
JSContext::saveFrameChain()
|
||||
{
|
||||
|
|
|
@ -284,6 +284,7 @@ struct ThreadSafeContext : ContextFriendFields,
|
|||
JSAtomState &names() { return *runtime_->commonNames; }
|
||||
StaticStrings &staticStrings() { return *runtime_->staticStrings; }
|
||||
AtomSet &permanentAtoms() { return *runtime_->permanentAtoms; }
|
||||
WellKnownSymbols &wellKnownSymbols() { return *runtime_->wellKnownSymbols; }
|
||||
const JS::AsmJSCacheOps &asmJSCacheOps() { return runtime_->asmJSCacheOps; }
|
||||
PropertyName *emptyString() { return runtime_->emptyString; }
|
||||
FreeOp *defaultFreeOp() { return runtime_->defaultFreeOp(); }
|
||||
|
@ -551,14 +552,7 @@ struct JSContext : public js::ExclusiveContext,
|
|||
runtime_->gc.gcIfNeeded(this);
|
||||
}
|
||||
|
||||
private:
|
||||
/* Innermost-executing generator or null if no generator are executing. */
|
||||
JSGenerator *innermostGenerator_;
|
||||
public:
|
||||
JSGenerator *innermostGenerator() const { return innermostGenerator_; }
|
||||
void enterGenerator(JSGenerator *gen);
|
||||
void leaveGenerator(JSGenerator *gen);
|
||||
|
||||
bool isExceptionPending() {
|
||||
return throwing;
|
||||
}
|
||||
|
|
|
@ -971,7 +971,7 @@ CopyFlatStringChars(char16_t *dest, JSFlatString *s, size_t len)
|
|||
}
|
||||
|
||||
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)
|
||||
AppendUnique(JSContext *cx, JS::AutoIdVector &base, JS::AutoIdVector &others);
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче