mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
commit
f3a2dc46bd
@ -11,6 +11,7 @@
|
||||
#include "mozilla/a11y/DocManager.h"
|
||||
#include "mozilla/a11y/FocusManager.h"
|
||||
#include "mozilla/a11y/SelectionManager.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
#include "nsIObserver.h"
|
||||
|
||||
@ -254,7 +255,8 @@ IPCAccessibilityActive()
|
||||
#ifdef MOZ_B2G
|
||||
return false;
|
||||
#else
|
||||
return XRE_GetProcessType() == GeckoProcessType_Content;
|
||||
return XRE_GetProcessType() == GeckoProcessType_Content &&
|
||||
mozilla::Preferences::GetBool("accessibility.ipc_architecture.enabled", true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1095,9 +1095,6 @@ var gBrowserInit = {
|
||||
socialBrowser.addEventListener("MozApplicationManifest",
|
||||
OfflineApps, false);
|
||||
|
||||
let uriToLoad = this._getUriToLoad();
|
||||
var isLoadingBlank = isBlankPageURL(uriToLoad);
|
||||
|
||||
// This pageshow listener needs to be registered before we may call
|
||||
// swapBrowsersAndCloseOther() to receive pageshow events fired by that.
|
||||
let mm = window.messageManager;
|
||||
@ -1135,6 +1132,7 @@ var gBrowserInit = {
|
||||
SessionStore.reviveCrashedTab(tab);
|
||||
}, false, true);
|
||||
|
||||
let uriToLoad = this._getUriToLoad();
|
||||
if (uriToLoad && uriToLoad != "about:blank") {
|
||||
if (uriToLoad instanceof Ci.nsISupportsArray) {
|
||||
let count = uriToLoad.Count();
|
||||
@ -1219,8 +1217,10 @@ var gBrowserInit = {
|
||||
|
||||
UpdateUrlbarSearchSplitterState();
|
||||
|
||||
if (!isLoadingBlank || !focusAndSelectUrlBar())
|
||||
if (!(isBlankPageURL(uriToLoad) || uriToLoad == "about:privatebrowsing") ||
|
||||
!focusAndSelectUrlBar()) {
|
||||
gBrowser.selectedBrowser.focus();
|
||||
}
|
||||
|
||||
// Set up Sanitize Item
|
||||
this._initializeSanitizer();
|
||||
|
@ -29,13 +29,8 @@ function test() {
|
||||
|
||||
// Open a newtab after setting the custom newtab url
|
||||
openNewTab(aWindow, function () {
|
||||
if (aIsPrivateMode) {
|
||||
is(aWindow.gBrowser.selectedBrowser.currentURI.spec, newTabURL,
|
||||
"URL of NewTab should always be " + newTabURL + " in " + mode + " mode");
|
||||
} else {
|
||||
is(aWindow.gBrowser.selectedBrowser.currentURI.spec, testURL,
|
||||
"URL of NewTab should be the custom url");
|
||||
}
|
||||
is(aWindow.gBrowser.selectedBrowser.currentURI.spec, testURL,
|
||||
"URL of NewTab should be the custom url");
|
||||
|
||||
// clear the custom url preference
|
||||
Services.prefs.clearUserPref(newTabPrefName);
|
||||
|
@ -14,7 +14,8 @@ XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
|
||||
|
||||
function getNewTabPageURL() {
|
||||
if (PrivateBrowsingUtils.isWindowPrivate(window) &&
|
||||
!PrivateBrowsingUtils.permanentPrivateBrowsing) {
|
||||
!PrivateBrowsingUtils.permanentPrivateBrowsing &&
|
||||
!Services.prefs.prefHasUserValue(PREF)) {
|
||||
return "about:privatebrowsing";
|
||||
}
|
||||
|
||||
|
@ -473,8 +473,13 @@ class ShutdownLeaks(object):
|
||||
for url, count in self._zipLeakedWindows(test["leakedWindows"]):
|
||||
self.logger.warning("TEST-UNEXPECTED-FAIL | %s | leaked %d window(s) until shutdown [url = %s]" % (test["fileName"], count, url))
|
||||
|
||||
if test["leakedWindowsString"]:
|
||||
self.logger.info("TEST-INFO | %s | windows(s) leaked: %s" % (test["fileName"], test["leakedWindowsString"]))
|
||||
|
||||
if test["leakedDocShells"]:
|
||||
self.logger.warning("TEST-UNEXPECTED-FAIL | %s | leaked %d docShell(s) until shutdown" % (test["fileName"], len(test["leakedDocShells"])))
|
||||
self.logger.info("TEST-INFO | %s | docShell(s) leaked: %s" % (test["fileName"],
|
||||
', '.join(["[pid = %s] [id = %s]" % x for x in test["leakedDocShells"]])))
|
||||
|
||||
def _logWindow(self, line):
|
||||
created = line[:2] == "++"
|
||||
@ -486,7 +491,7 @@ class ShutdownLeaks(object):
|
||||
self.logger.warning("TEST-UNEXPECTED-FAIL | ShutdownLeaks | failed to parse line <%s>" % line)
|
||||
return
|
||||
|
||||
key = pid + "." + serial
|
||||
key = (pid, serial)
|
||||
|
||||
if self.currentTest:
|
||||
windows = self.currentTest["windows"]
|
||||
@ -507,7 +512,7 @@ class ShutdownLeaks(object):
|
||||
self.logger.warning("TEST-UNEXPECTED-FAIL | ShutdownLeaks | failed to parse line <%s>" % line)
|
||||
return
|
||||
|
||||
key = pid + "." + id
|
||||
key = (pid, id)
|
||||
|
||||
if self.currentTest:
|
||||
docShells = self.currentTest["docShells"]
|
||||
@ -528,7 +533,9 @@ class ShutdownLeaks(object):
|
||||
leakingTests = []
|
||||
|
||||
for test in self.tests:
|
||||
test["leakedWindows"] = [self.leakedWindows[id] for id in test["windows"] if id in self.leakedWindows]
|
||||
leakedWindows = [id for id in test["windows"] if id in self.leakedWindows]
|
||||
test["leakedWindows"] = [self.leakedWindows[id] for id in leakedWindows]
|
||||
test["leakedWindowsString"] = ', '.join(["[pid = %s] [serial = %s]" % x for x in leakedWindows])
|
||||
test["leakedDocShells"] = [id for id in test["docShells"] if id in self.leakedDocShells]
|
||||
test["leakCount"] = len(test["leakedWindows"]) + len(test["leakedDocShells"])
|
||||
|
||||
|
@ -31,8 +31,8 @@ public:
|
||||
NS_DECL_NSIURI
|
||||
|
||||
// nsISizeOf
|
||||
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
|
||||
virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
|
||||
|
||||
explicit nsNullPrincipalURI(const nsCString &aSpec);
|
||||
|
||||
|
@ -49,25 +49,25 @@ class nsPrincipal MOZ_FINAL : public nsBasePrincipal
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSISERIALIZABLE
|
||||
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD GetHashValue(uint32_t* aHashValue);
|
||||
NS_IMETHOD GetURI(nsIURI** aURI);
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain);
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain);
|
||||
NS_IMETHOD GetOrigin(char** aOrigin);
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix);
|
||||
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);
|
||||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
|
||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain);
|
||||
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetHashValue(uint32_t* aHashValue) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetURI(nsIURI** aURI) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain) MOZ_OVERRIDE;
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetOrigin(char** aOrigin) MOZ_OVERRIDE;
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetAppId(uint32_t* aAppStatus) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) MOZ_OVERRIDE;
|
||||
#ifdef DEBUG
|
||||
virtual void dumpImpl();
|
||||
virtual void dumpImpl() MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
nsPrincipal();
|
||||
@ -132,25 +132,25 @@ public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIEXPANDEDPRINCIPAL
|
||||
NS_DECL_NSISERIALIZABLE
|
||||
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD GetHashValue(uint32_t* aHashValue);
|
||||
NS_IMETHOD GetURI(nsIURI** aURI);
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain);
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain);
|
||||
NS_IMETHOD GetOrigin(char** aOrigin);
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval);
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal);
|
||||
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix);
|
||||
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus);
|
||||
NS_IMETHOD GetAppId(uint32_t* aAppStatus);
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement);
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId);
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal);
|
||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain);
|
||||
NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetHashValue(uint32_t* aHashValue) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetURI(nsIURI** aURI) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetDomain(nsIURI** aDomain) MOZ_OVERRIDE;
|
||||
NS_IMETHOD SetDomain(nsIURI* aDomain) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetOrigin(char** aOrigin) MOZ_OVERRIDE;
|
||||
NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetJarPrefix(nsACString& aJarPrefix) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetAppId(uint32_t* aAppStatus) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetIsInBrowserElement(bool* aIsInBrowserElement) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetIsNullPrincipal(bool* aIsNullPrincipal) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) MOZ_OVERRIDE;
|
||||
#ifdef DEBUG
|
||||
virtual void dumpImpl();
|
||||
virtual void dumpImpl() MOZ_OVERRIDE;
|
||||
#endif
|
||||
|
||||
virtual void GetScriptLocation(nsACString &aStr) MOZ_OVERRIDE;
|
||||
|
@ -47,16 +47,16 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIXULChromeRegistry methods:
|
||||
NS_IMETHOD ReloadChrome();
|
||||
NS_IMETHOD RefreshSkins();
|
||||
NS_IMETHOD ReloadChrome() MOZ_OVERRIDE;
|
||||
NS_IMETHOD RefreshSkins() MOZ_OVERRIDE;
|
||||
NS_IMETHOD AllowScriptsForPackage(nsIURI* url,
|
||||
bool* _retval);
|
||||
bool* _retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD AllowContentToAccess(nsIURI* url,
|
||||
bool* _retval);
|
||||
bool* _retval) MOZ_OVERRIDE;
|
||||
|
||||
// nsIChromeRegistry methods:
|
||||
NS_IMETHOD_(bool) WrappersEnabled(nsIURI *aURI);
|
||||
NS_IMETHOD ConvertChromeURL(nsIURI* aChromeURI, nsIURI* *aResult);
|
||||
NS_IMETHOD_(bool) WrappersEnabled(nsIURI *aURI) MOZ_OVERRIDE;
|
||||
NS_IMETHOD ConvertChromeURL(nsIURI* aChromeURI, nsIURI* *aResult) MOZ_OVERRIDE;
|
||||
|
||||
// nsChromeRegistry methods:
|
||||
nsChromeRegistry() : mInitialized(false) { }
|
||||
|
@ -167,25 +167,25 @@ class nsChromeRegistryChrome : public nsChromeRegistry
|
||||
|
||||
virtual void ManifestContent(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestResource(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // nsChromeRegistryChrome_h
|
||||
|
@ -66,25 +66,25 @@ class nsChromeRegistryContent : public nsChromeRegistry
|
||||
|
||||
virtual void ManifestContent(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestLocale(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestSkin(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestOverlay(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestStyle(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestOverride(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
virtual void ManifestResource(ManifestProcessingContext& cx, int lineno,
|
||||
char *const * argv, bool platform,
|
||||
bool contentaccessible);
|
||||
bool contentaccessible) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // nsChromeRegistryContent_h
|
||||
|
@ -132,14 +132,14 @@ NS_DEFINE_STATIC_IID_ACCESSOR(IHistory, IHISTORY_IID)
|
||||
|
||||
#define NS_DECL_IHISTORY \
|
||||
NS_IMETHOD RegisterVisitedCallback(nsIURI *aURI, \
|
||||
mozilla::dom::Link *aContent); \
|
||||
mozilla::dom::Link *aContent) MOZ_OVERRIDE; \
|
||||
NS_IMETHOD UnregisterVisitedCallback(nsIURI *aURI, \
|
||||
mozilla::dom::Link *aContent); \
|
||||
mozilla::dom::Link *aContent) MOZ_OVERRIDE; \
|
||||
NS_IMETHOD VisitURI(nsIURI *aURI, \
|
||||
nsIURI *aLastVisitedURI, \
|
||||
uint32_t aFlags); \
|
||||
NS_IMETHOD SetURITitle(nsIURI* aURI, const nsAString& aTitle); \
|
||||
NS_IMETHOD NotifyVisited(nsIURI* aURI);
|
||||
uint32_t aFlags) MOZ_OVERRIDE; \
|
||||
NS_IMETHOD SetURITitle(nsIURI* aURI, const nsAString& aTitle) MOZ_OVERRIDE; \
|
||||
NS_IMETHOD NotifyVisited(nsIURI* aURI) MOZ_OVERRIDE;
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -103,14 +103,14 @@ public:
|
||||
return mAgent->SetVisibilityState(visible);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP CanPlayChanged(int32_t canPlay)
|
||||
NS_IMETHODIMP CanPlayChanged(int32_t canPlay) MOZ_OVERRIDE
|
||||
{
|
||||
mCanPlay = static_cast<AudioChannelState>(canPlay);
|
||||
mWaitCallback = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP WindowVolumeChanged()
|
||||
NS_IMETHODIMP WindowVolumeChanged() MOZ_OVERRIDE
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -441,8 +441,10 @@ Link::GetHash(nsAString &_hash, ErrorResult& aError)
|
||||
nsAutoCString ref;
|
||||
nsresult rv = uri->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
|
||||
_hash.Assign(char16_t('#'));
|
||||
if (nsContentUtils::EncodeDecodeURLHash()) {
|
||||
NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
|
||||
}
|
||||
AppendUTF8toUTF16(ref, _hash);
|
||||
}
|
||||
}
|
||||
|
@ -514,8 +514,10 @@ URL::GetHash(nsString& aHash, ErrorResult& aRv) const
|
||||
nsAutoCString ref;
|
||||
nsresult rv = mURI->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
|
||||
aHash.Assign(char16_t('#'));
|
||||
if (nsContentUtils::EncodeDecodeURLHash()) {
|
||||
NS_UnescapeURL(ref); // XXX may result in random non-ASCII bytes!
|
||||
}
|
||||
AppendUTF8toUTF16(ref, aHash);
|
||||
}
|
||||
}
|
||||
|
@ -243,6 +243,7 @@ bool nsContentUtils::sFullscreenApiIsContentOnly = false;
|
||||
bool nsContentUtils::sIsPerformanceTimingEnabled = false;
|
||||
bool nsContentUtils::sIsResourceTimingEnabled = false;
|
||||
bool nsContentUtils::sIsExperimentalAutocompleteEnabled = false;
|
||||
bool nsContentUtils::sEncodeDecodeURLHash = false;
|
||||
|
||||
uint32_t nsContentUtils::sHandlingInputTimeout = 1000;
|
||||
|
||||
@ -520,6 +521,9 @@ nsContentUtils::Init()
|
||||
Preferences::AddBoolVarCache(&sIsExperimentalAutocompleteEnabled,
|
||||
"dom.forms.autocomplete.experimental", false);
|
||||
|
||||
Preferences::AddBoolVarCache(&sEncodeDecodeURLHash,
|
||||
"dom.url.encode_decode_hash", false);
|
||||
|
||||
Preferences::AddUintVarCache(&sHandlingInputTimeout,
|
||||
"dom.event.handling-user-input-time-limit",
|
||||
1000);
|
||||
|
@ -1860,6 +1860,15 @@ public:
|
||||
return sIsResourceTimingEnabled;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if URL setters should percent encode the Hash/Ref segment
|
||||
* and getters should return the percent decoded value of the segment
|
||||
*/
|
||||
static bool EncodeDecodeURLHash()
|
||||
{
|
||||
return sEncodeDecodeURLHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the doc tree branch which contains aDoc contains any
|
||||
* plugins which we don't control event dispatch for, i.e. do any plugins
|
||||
@ -2323,6 +2332,7 @@ private:
|
||||
static bool sIsPerformanceTimingEnabled;
|
||||
static bool sIsResourceTimingEnabled;
|
||||
static bool sIsExperimentalAutocompleteEnabled;
|
||||
static bool sEncodeDecodeURLHash;
|
||||
|
||||
static nsHtml5StringParser* sHTMLFragmentParser;
|
||||
static nsIParser* sXMLFragmentParser;
|
||||
|
@ -2305,7 +2305,7 @@ nsFrameLoader::CreateStaticClone(nsIFrameLoader* aDest)
|
||||
bool
|
||||
nsFrameLoader::DoLoadFrameScript(const nsAString& aURL, bool aRunInGlobalScope)
|
||||
{
|
||||
mozilla::dom::PBrowserParent* tabParent = GetRemoteBrowser();
|
||||
auto* tabParent = static_cast<TabParent*>(GetRemoteBrowser());
|
||||
if (tabParent) {
|
||||
return tabParent->SendLoadRemoteScript(nsString(aURL), aRunInGlobalScope);
|
||||
}
|
||||
|
@ -298,28 +298,36 @@ nsLocation::GetHash(nsAString& aHash)
|
||||
nsAutoString unicodeRef;
|
||||
|
||||
rv = uri->GetRef(ref);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsITextToSubURI> textToSubURI(
|
||||
do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
|
||||
|
||||
if (nsContentUtils::EncodeDecodeURLHash()) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoCString charset;
|
||||
uri->GetOriginCharset(charset);
|
||||
|
||||
rv = textToSubURI->UnEscapeURIForUI(charset, ref, unicodeRef);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// Oh, well. No intl here!
|
||||
NS_UnescapeURL(ref);
|
||||
CopyASCIItoUTF16(ref, unicodeRef);
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsITextToSubURI> textToSubURI(
|
||||
do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !unicodeRef.IsEmpty()) {
|
||||
aHash.Assign(char16_t('#'));
|
||||
aHash.Append(unicodeRef);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoCString charset;
|
||||
uri->GetOriginCharset(charset);
|
||||
|
||||
rv = textToSubURI->UnEscapeURIForUI(charset, ref, unicodeRef);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// Oh, well. No intl here!
|
||||
NS_UnescapeURL(ref);
|
||||
CopyASCIItoUTF16(ref, unicodeRef);
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !unicodeRef.IsEmpty()) {
|
||||
aHash.Assign(char16_t('#'));
|
||||
aHash.Append(unicodeRef);
|
||||
}
|
||||
} else { // URL Hash should simply return the value of the Ref segment
|
||||
if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
|
||||
aHash.Assign(char16_t('#'));
|
||||
AppendUTF8toUTF16(ref, aHash);
|
||||
}
|
||||
}
|
||||
|
||||
if (aHash == mCachedHash) {
|
||||
|
@ -288,7 +288,8 @@ nsXMLHttpRequest::sDontWarnAboutSyncXHR = false;
|
||||
nsXMLHttpRequest::nsXMLHttpRequest()
|
||||
: mResponseBodyDecodedPos(0),
|
||||
mResponseType(XML_HTTP_RESPONSE_TYPE_DEFAULT),
|
||||
mRequestObserver(nullptr), mState(XML_HTTP_REQUEST_UNSENT),
|
||||
mRequestObserver(nullptr),
|
||||
mState(XML_HTTP_REQUEST_UNSENT | XML_HTTP_REQUEST_ASYNC),
|
||||
mUploadTransferred(0), mUploadTotal(0), mUploadComplete(true),
|
||||
mProgressSinceLastProgressEvent(false),
|
||||
mRequestSentTime(0), mTimeoutMilliseconds(0),
|
||||
@ -915,10 +916,9 @@ void
|
||||
nsXMLHttpRequest::SetResponseType(nsXMLHttpRequest::ResponseTypeEnum aResponseType,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
// If the state is not OPENED or HEADERS_RECEIVED raise an
|
||||
// INVALID_STATE_ERR exception and terminate these steps.
|
||||
if (!(mState & (XML_HTTP_REQUEST_OPENED | XML_HTTP_REQUEST_SENT |
|
||||
XML_HTTP_REQUEST_HEADERS_RECEIVED))) {
|
||||
// If the state is LOADING or DONE raise an INVALID_STATE_ERR exception
|
||||
// and terminate these steps.
|
||||
if ((mState & (XML_HTTP_REQUEST_LOADING | XML_HTTP_REQUEST_DONE))) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
|
@ -323,7 +323,6 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop spec
|
||||
[test_CrossSiteXHR_cache.html]
|
||||
[test_CrossSiteXHR_origin.html]
|
||||
skip-if = buildapp == 'b2g' || e10s # last test fails to trigger onload on e10s/b2g
|
||||
[test_DOMException.html]
|
||||
[test_EventSource_redirects.html]
|
||||
[test_NodeIterator_basics_filters.xhtml]
|
||||
[test_NodeIterator_mutations_1.xhtml]
|
||||
|
@ -1,67 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test for DOMException constants</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script>
|
||||
var constants = [
|
||||
null,
|
||||
"INDEX_SIZE_ERR",
|
||||
"DOMSTRING_SIZE_ERR",
|
||||
"HIERARCHY_REQUEST_ERR",
|
||||
"WRONG_DOCUMENT_ERR",
|
||||
"INVALID_CHARACTER_ERR",
|
||||
"NO_DATA_ALLOWED_ERR",
|
||||
"NO_MODIFICATION_ALLOWED_ERR",
|
||||
"NOT_FOUND_ERR",
|
||||
"NOT_SUPPORTED_ERR",
|
||||
"INUSE_ATTRIBUTE_ERR",
|
||||
"INVALID_STATE_ERR",
|
||||
"SYNTAX_ERR",
|
||||
"INVALID_MODIFICATION_ERR",
|
||||
"NAMESPACE_ERR",
|
||||
"INVALID_ACCESS_ERR",
|
||||
"VALIDATION_ERR",
|
||||
"TYPE_MISMATCH_ERR",
|
||||
"SECURITY_ERR",
|
||||
"NETWORK_ERR",
|
||||
"ABORT_ERR",
|
||||
"URL_MISMATCH_ERR",
|
||||
"QUOTA_EXCEEDED_ERR",
|
||||
"TIMEOUT_ERR",
|
||||
"INVALID_NODE_TYPE_ERR",
|
||||
"DATA_CLONE_ERR"
|
||||
];
|
||||
for (var i = 0; i < constants.length; ++i) {
|
||||
var constant = constants[i];
|
||||
if (constant)
|
||||
is(DOMException[constant], i, constant)
|
||||
}
|
||||
|
||||
var ex = new DOMException();
|
||||
ise(ex.name, "Error",
|
||||
"Not passing a name should end up with 'Error' as the name");
|
||||
ise(ex.message, "",
|
||||
"Not passing a message should end up with empty string as the message");
|
||||
|
||||
ex = new DOMException("foo");
|
||||
ise(ex.name, "Error",
|
||||
"Not passing a name should still end up with 'Error' as the name");
|
||||
ise(ex.message, "foo", "Should be using passed-in message");
|
||||
|
||||
ex = new DOMException("bar", "NotSupportedError");
|
||||
ise(ex.name, "NotSupportedError", "Should be using the passed-in name");
|
||||
ise(ex.message, "bar", "Should still be using passed-in message");
|
||||
ise(ex.code, DOMException.NOT_SUPPORTED_ERR,
|
||||
"Should have the right exception code");
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -104,6 +104,12 @@ function checkResponseXMLAccessThrows(xhr) {
|
||||
try { xhr.responseXML } catch (e) { didthrow = true; }
|
||||
ok(didthrow, "should have thrown when accessing responseXML");
|
||||
}
|
||||
function checkSetResponseType(xhr, type) {
|
||||
var didthrow = false;
|
||||
try { xhr.responseType = type; } catch (e) { didthrow = true; }
|
||||
ise(xhr.responseType, type, "responseType should be " + type);
|
||||
ok(!didthrow, "should not have thrown when setting responseType");
|
||||
}
|
||||
function checkSetResponseTypeThrows(xhr, type) {
|
||||
var didthrow = false;
|
||||
try { xhr.responseType = type; } catch (e) { didthrow = true; }
|
||||
@ -115,6 +121,18 @@ function checkOpenThrows(xhr, method, url, async) {
|
||||
ok(didthrow, "should have thrown when open is called");
|
||||
}
|
||||
|
||||
// test if setting responseType before calling open() works
|
||||
xhr = new XMLHttpRequest();
|
||||
checkSetResponseType(xhr, "");
|
||||
checkSetResponseType(xhr, "text");
|
||||
checkSetResponseType(xhr, "document");
|
||||
checkSetResponseType(xhr, "arraybuffer");
|
||||
checkSetResponseType(xhr, "blob");
|
||||
checkSetResponseType(xhr, "json");
|
||||
checkSetResponseType(xhr, "moz-chunked-text");
|
||||
checkSetResponseType(xhr, "moz-chunked-arraybuffer");
|
||||
checkOpenThrows(xhr, "GET", "file_XHR_pass2.txt", false);
|
||||
|
||||
// test response (sync, responseType is not changeable)
|
||||
xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", 'file_XHR_pass2.txt', false);
|
||||
|
@ -117,7 +117,7 @@
|
||||
{ url: 'http://example.com/carrot#question%3f',
|
||||
base: undefined,
|
||||
error: false,
|
||||
hash: '#question?'
|
||||
hash: '#question%3f'
|
||||
},
|
||||
{ url: 'https://example.com:4443?',
|
||||
base: undefined,
|
||||
|
@ -4,20 +4,329 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGL2Context.h"
|
||||
|
||||
#include "GLContext.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
// Returns one of FLOAT, INT, UNSIGNED_INT.
|
||||
// Fixed-points (normalized ints) are considered FLOAT.
|
||||
static GLenum
|
||||
ValueTypeForFormat(GLenum internalFormat)
|
||||
{
|
||||
switch (internalFormat) {
|
||||
// Fixed-point
|
||||
case LOCAL_GL_R8:
|
||||
case LOCAL_GL_RG8:
|
||||
case LOCAL_GL_RGB565:
|
||||
case LOCAL_GL_RGB8:
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
case LOCAL_GL_RGBA8:
|
||||
case LOCAL_GL_RGB10_A2:
|
||||
case LOCAL_GL_ALPHA8:
|
||||
case LOCAL_GL_LUMINANCE8:
|
||||
case LOCAL_GL_LUMINANCE8_ALPHA8:
|
||||
case LOCAL_GL_SRGB8:
|
||||
case LOCAL_GL_SRGB8_ALPHA8:
|
||||
case LOCAL_GL_R8_SNORM:
|
||||
case LOCAL_GL_RG8_SNORM:
|
||||
case LOCAL_GL_RGB8_SNORM:
|
||||
case LOCAL_GL_RGBA8_SNORM:
|
||||
|
||||
// Floating-point
|
||||
case LOCAL_GL_R16F:
|
||||
case LOCAL_GL_RG16F:
|
||||
case LOCAL_GL_RGB16F:
|
||||
case LOCAL_GL_RGBA16F:
|
||||
case LOCAL_GL_ALPHA16F_EXT:
|
||||
case LOCAL_GL_LUMINANCE16F_EXT:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA16F_EXT:
|
||||
|
||||
case LOCAL_GL_R32F:
|
||||
case LOCAL_GL_RG32F:
|
||||
case LOCAL_GL_RGB32F:
|
||||
case LOCAL_GL_RGBA32F:
|
||||
case LOCAL_GL_ALPHA32F_EXT:
|
||||
case LOCAL_GL_LUMINANCE32F_EXT:
|
||||
case LOCAL_GL_LUMINANCE_ALPHA32F_EXT:
|
||||
|
||||
case LOCAL_GL_R11F_G11F_B10F:
|
||||
case LOCAL_GL_RGB9_E5:
|
||||
return LOCAL_GL_FLOAT;
|
||||
|
||||
// Int
|
||||
case LOCAL_GL_R8I:
|
||||
case LOCAL_GL_RG8I:
|
||||
case LOCAL_GL_RGB8I:
|
||||
case LOCAL_GL_RGBA8I:
|
||||
|
||||
case LOCAL_GL_R16I:
|
||||
case LOCAL_GL_RG16I:
|
||||
case LOCAL_GL_RGB16I:
|
||||
case LOCAL_GL_RGBA16I:
|
||||
|
||||
case LOCAL_GL_R32I:
|
||||
case LOCAL_GL_RG32I:
|
||||
case LOCAL_GL_RGB32I:
|
||||
case LOCAL_GL_RGBA32I:
|
||||
return LOCAL_GL_INT;
|
||||
|
||||
// Unsigned int
|
||||
case LOCAL_GL_R8UI:
|
||||
case LOCAL_GL_RG8UI:
|
||||
case LOCAL_GL_RGB8UI:
|
||||
case LOCAL_GL_RGBA8UI:
|
||||
|
||||
case LOCAL_GL_R16UI:
|
||||
case LOCAL_GL_RG16UI:
|
||||
case LOCAL_GL_RGB16UI:
|
||||
case LOCAL_GL_RGBA16UI:
|
||||
|
||||
case LOCAL_GL_R32UI:
|
||||
case LOCAL_GL_RG32UI:
|
||||
case LOCAL_GL_RGB32UI:
|
||||
case LOCAL_GL_RGBA32UI:
|
||||
|
||||
case LOCAL_GL_RGB10_A2UI:
|
||||
return LOCAL_GL_UNSIGNED_INT;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad `internalFormat`.");
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Framebuffer objects
|
||||
|
||||
static bool
|
||||
GetFBInfoForBlit(const WebGLFramebuffer* fb, WebGLContext* webgl,
|
||||
const char* const fbInfo, GLsizei* const out_samples,
|
||||
GLenum* const out_colorFormat, GLenum* const out_depthFormat,
|
||||
GLenum* const out_stencilFormat)
|
||||
{
|
||||
auto status = fb->PrecheckFramebufferStatus();
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) {
|
||||
webgl->ErrorInvalidOperation("blitFramebuffer: %s is not"
|
||||
" framebuffer-complete.", fbInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
*out_samples = 1; // TODO
|
||||
|
||||
if (fb->ColorAttachment(0).IsDefined()) {
|
||||
const auto& attachement = fb->ColorAttachment(0);
|
||||
*out_colorFormat = attachement.EffectiveInternalFormat().get();
|
||||
} else {
|
||||
*out_colorFormat = 0;
|
||||
}
|
||||
|
||||
if (fb->DepthStencilAttachment().IsDefined()) {
|
||||
const auto& attachement = fb->DepthStencilAttachment();
|
||||
*out_depthFormat = attachement.EffectiveInternalFormat().get();
|
||||
*out_stencilFormat = *out_depthFormat;
|
||||
} else {
|
||||
if (fb->DepthAttachment().IsDefined()) {
|
||||
const auto& attachement = fb->DepthAttachment();
|
||||
*out_depthFormat = attachement.EffectiveInternalFormat().get();
|
||||
} else {
|
||||
*out_depthFormat = 0;
|
||||
}
|
||||
|
||||
if (fb->StencilAttachment().IsDefined()) {
|
||||
const auto& attachement = fb->StencilAttachment();
|
||||
*out_stencilFormat = attachement.EffectiveInternalFormat().get();
|
||||
} else {
|
||||
*out_stencilFormat = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebGL2Context::BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
|
||||
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
|
||||
GLbitfield mask, GLenum filter)
|
||||
{
|
||||
MOZ_CRASH("Not Implemented.");
|
||||
const GLbitfield validBits = LOCAL_GL_COLOR_BUFFER_BIT |
|
||||
LOCAL_GL_DEPTH_BUFFER_BIT |
|
||||
LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
if ((mask | validBits) != validBits) {
|
||||
ErrorInvalidValue("blitFramebuffer: Invalid bit set in mask.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (filter) {
|
||||
case LOCAL_GL_NEAREST:
|
||||
case LOCAL_GL_LINEAR:
|
||||
break;
|
||||
default:
|
||||
ErrorInvalidEnumInfo("blitFramebuffer: Bad `filter`:", filter);
|
||||
return;
|
||||
}
|
||||
|
||||
const GLbitfield depthAndStencilBits = LOCAL_GL_DEPTH_BUFFER_BIT |
|
||||
LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
if (mask & depthAndStencilBits &&
|
||||
filter != LOCAL_GL_NEAREST)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: DEPTH_BUFFER_BIT and"
|
||||
" STENCIL_BUFFER_BIT can only be used with"
|
||||
" NEAREST filtering.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBoundReadFramebuffer == mBoundDrawFramebuffer) {
|
||||
// TODO: It's actually more complicated than this. We need to check that
|
||||
// the underlying buffers are not the same, not the framebuffers
|
||||
// themselves.
|
||||
ErrorInvalidOperation("blitFramebuffer: Source and destination must"
|
||||
" differ.");
|
||||
return;
|
||||
}
|
||||
|
||||
GLsizei srcSamples;
|
||||
GLenum srcColorFormat;
|
||||
GLenum srcDepthFormat;
|
||||
GLenum srcStencilFormat;
|
||||
|
||||
if (mBoundReadFramebuffer) {
|
||||
if (!GetFBInfoForBlit(mBoundReadFramebuffer, this, "READ_FRAMEBUFFER",
|
||||
&srcSamples, &srcColorFormat, &srcDepthFormat,
|
||||
&srcStencilFormat))
|
||||
{
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
srcSamples = 1; // Always 1.
|
||||
|
||||
// TODO: Don't hardcode these.
|
||||
srcColorFormat = mOptions.alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
|
||||
|
||||
if (mOptions.depth && mOptions.stencil) {
|
||||
srcDepthFormat = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
srcStencilFormat = srcDepthFormat;
|
||||
} else {
|
||||
if (mOptions.depth) {
|
||||
srcDepthFormat = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
if (mOptions.stencil) {
|
||||
srcStencilFormat = LOCAL_GL_STENCIL_INDEX8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLsizei dstSamples;
|
||||
GLenum dstColorFormat;
|
||||
GLenum dstDepthFormat;
|
||||
GLenum dstStencilFormat;
|
||||
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (!GetFBInfoForBlit(mBoundDrawFramebuffer, this, "DRAW_FRAMEBUFFER",
|
||||
&dstSamples, &dstColorFormat, &dstDepthFormat,
|
||||
&dstStencilFormat))
|
||||
{
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
dstSamples = gl->Screen()->Samples();
|
||||
|
||||
// TODO: Don't hardcode these.
|
||||
dstColorFormat = mOptions.alpha ? LOCAL_GL_RGBA8 : LOCAL_GL_RGB8;
|
||||
|
||||
if (mOptions.depth && mOptions.stencil) {
|
||||
dstDepthFormat = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
dstStencilFormat = dstDepthFormat;
|
||||
} else {
|
||||
if (mOptions.depth) {
|
||||
dstDepthFormat = LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
if (mOptions.stencil) {
|
||||
dstStencilFormat = LOCAL_GL_STENCIL_INDEX8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
|
||||
const GLenum srcColorType = srcColorFormat ? ValueTypeForFormat(srcColorFormat)
|
||||
: 0;
|
||||
const GLenum dstColorType = dstColorFormat ? ValueTypeForFormat(dstColorFormat)
|
||||
: 0;
|
||||
if (dstColorType != srcColorType) {
|
||||
ErrorInvalidOperation("blitFramebuffer: Color buffer value type"
|
||||
" mismatch.");
|
||||
return;
|
||||
}
|
||||
|
||||
const bool srcIsInt = srcColorType == LOCAL_GL_INT ||
|
||||
srcColorType == LOCAL_GL_UNSIGNED_INT;
|
||||
if (srcIsInt && filter != LOCAL_GL_NEAREST) {
|
||||
ErrorInvalidOperation("blitFramebuffer: Integer read buffers can only"
|
||||
" be filtered with NEAREST.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* GLES 3.0.4, p199:
|
||||
* Calling BlitFramebuffer will result in an INVALID_OPERATION error if
|
||||
* mask includes DEPTH_BUFFER_BIT or STENCIL_BUFFER_BIT, and the source
|
||||
* and destination depth and stencil buffer formats do not match.
|
||||
*
|
||||
* jgilbert: The wording is such that if only DEPTH_BUFFER_BIT is specified,
|
||||
* the stencil formats must match. This seems wrong. It could be a spec bug,
|
||||
* or I could be missing an interaction in one of the earlier paragraphs.
|
||||
*/
|
||||
if (mask & LOCAL_GL_DEPTH_BUFFER_BIT &&
|
||||
dstDepthFormat != srcDepthFormat)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: Depth buffer formats must match"
|
||||
" if selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask & LOCAL_GL_STENCIL_BUFFER_BIT &&
|
||||
dstStencilFormat != srcStencilFormat)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: Stencil buffer formats must"
|
||||
" match if selected.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dstSamples != 1) {
|
||||
ErrorInvalidOperation("blitFramebuffer: DRAW_FRAMEBUFFER may not have"
|
||||
" multiple samples.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (srcSamples != 1) {
|
||||
if (mask & LOCAL_GL_COLOR_BUFFER_BIT &&
|
||||
dstColorFormat != srcColorFormat)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: Color buffer formats must"
|
||||
" match if selected, when reading from a"
|
||||
" multisampled source.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dstX0 != srcX0 ||
|
||||
dstX1 != srcX1 ||
|
||||
dstY0 != srcY0 ||
|
||||
dstY1 != srcY1)
|
||||
{
|
||||
ErrorInvalidOperation("blitFramebuffer: If the source is"
|
||||
" multisampled, then the source and dest"
|
||||
" regions must match exactly.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
|
||||
dstX0, dstY0, dstX1, dstY1,
|
||||
mask, filter);
|
||||
}
|
||||
|
||||
void
|
||||
@ -57,16 +366,39 @@ WebGL2Context::InvalidateFramebuffer(GLenum target, const dom::Sequence<GLenum>&
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnumInfo("invalidateFramebuffer: target", target);
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(attachments[i], "invalidateFramebuffer"))
|
||||
return;
|
||||
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
|
||||
return;
|
||||
|
||||
const WebGLFramebuffer* fb;
|
||||
bool isDefaultFB;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsDrawFramebufferDefault();
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
if (!mBoundFramebuffer && !gl->IsDrawingToDefaultFramebuffer()) {
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i],
|
||||
"invalidateFramebuffer"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fb && !isDefaultFB) {
|
||||
dom::Sequence<GLenum> tmpAttachments;
|
||||
TranslateDefaultAttachments(attachments, &tmpAttachments);
|
||||
gl->fInvalidateFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements());
|
||||
@ -81,16 +413,39 @@ WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenu
|
||||
{
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnumInfo("invalidateFramebuffer: target", target);
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(attachments[i], "invalidateSubFramebuffer"))
|
||||
return;
|
||||
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
|
||||
return;
|
||||
|
||||
const WebGLFramebuffer* fb;
|
||||
bool isDefaultFB;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsDrawFramebufferDefault();
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
if (!mBoundFramebuffer && !gl->IsDrawingToDefaultFramebuffer()) {
|
||||
for (size_t i = 0; i < attachments.Length(); i++) {
|
||||
if (!ValidateFramebufferAttachment(fb, attachments[i],
|
||||
"invalidateSubFramebuffer"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fb && !isDefaultFB) {
|
||||
dom::Sequence<GLenum> tmpAttachments;
|
||||
TranslateDefaultAttachments(attachments, &tmpAttachments);
|
||||
gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements(),
|
||||
|
@ -330,7 +330,8 @@ WebGLContext::DestroyResourcesAndContext()
|
||||
mBoundTransformFeedbackBuffer = nullptr;
|
||||
mBoundUniformBuffer = nullptr;
|
||||
mCurrentProgram = nullptr;
|
||||
mBoundFramebuffer = nullptr;
|
||||
mBoundDrawFramebuffer = nullptr;
|
||||
mBoundReadFramebuffer = nullptr;
|
||||
mActiveOcclusionQuery = nullptr;
|
||||
mBoundRenderbuffer = nullptr;
|
||||
mBoundVertexArray = nullptr;
|
||||
@ -1887,7 +1888,8 @@ NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLContext,
|
||||
mBoundTransformFeedbackBuffer,
|
||||
mBoundUniformBuffer,
|
||||
mCurrentProgram,
|
||||
mBoundFramebuffer,
|
||||
mBoundDrawFramebuffer,
|
||||
mBoundReadFramebuffer,
|
||||
mBoundRenderbuffer,
|
||||
mBoundVertexArray,
|
||||
mDefaultVertexArray,
|
||||
|
@ -312,7 +312,8 @@ public:
|
||||
uint32_t Generation() { return mGeneration.value(); }
|
||||
|
||||
// Returns null if the current bound FB is not likely complete.
|
||||
const WebGLRectangleObject* CurValidFBRectObject() const;
|
||||
const WebGLRectangleObject* CurValidDrawFBRectObject() const;
|
||||
const WebGLRectangleObject* CurValidReadFBRectObject() const;
|
||||
|
||||
static const size_t kMaxColorAttachments = 16;
|
||||
|
||||
@ -415,7 +416,8 @@ public:
|
||||
GLint level);
|
||||
|
||||
// Framebuffer validation
|
||||
bool ValidateFramebufferAttachment(GLenum attachment, const char* funcName);
|
||||
bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb,
|
||||
GLenum attachment, const char* funcName);
|
||||
|
||||
void FrontFace(GLenum mode);
|
||||
void GenerateMipmap(GLenum target);
|
||||
@ -1404,7 +1406,10 @@ protected:
|
||||
|
||||
uint32_t mMaxFramebufferColorAttachments;
|
||||
|
||||
WebGLRefPtr<WebGLFramebuffer> mBoundFramebuffer;
|
||||
bool ValidateFramebufferTarget(GLenum target, const char* const info);
|
||||
|
||||
WebGLRefPtr<WebGLFramebuffer> mBoundDrawFramebuffer;
|
||||
WebGLRefPtr<WebGLFramebuffer> mBoundReadFramebuffer;
|
||||
WebGLRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
|
||||
WebGLRefPtr<WebGLTransformFeedback> mBoundTransformFeedback;
|
||||
WebGLRefPtr<WebGLVertexArray> mBoundVertexArray;
|
||||
|
@ -99,8 +99,8 @@ bool WebGLContext::DrawArrays_check(GLint first, GLsizei count, GLsizei primcoun
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (!mBoundDrawFramebuffer->CheckAndInitializeAttachments()) {
|
||||
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
|
||||
return false;
|
||||
}
|
||||
@ -280,8 +280,8 @@ WebGLContext::DrawElements_check(GLsizei count, GLenum type,
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (!mBoundDrawFramebuffer->CheckAndInitializeAttachments()) {
|
||||
ErrorInvalidFramebufferOperation("%s: incomplete framebuffer", info);
|
||||
return false;
|
||||
}
|
||||
@ -370,7 +370,7 @@ void WebGLContext::Draw_cleanup()
|
||||
UndoFakeVertexAttrib0();
|
||||
UnbindFakeBlackTextures();
|
||||
|
||||
if (!mBoundFramebuffer) {
|
||||
if (!mBoundDrawFramebuffer) {
|
||||
Invalidate();
|
||||
mShouldPresent = true;
|
||||
MOZ_ASSERT(!mBackbufferNeedsClear);
|
||||
@ -388,7 +388,7 @@ void WebGLContext::Draw_cleanup()
|
||||
}
|
||||
|
||||
// Let's check the viewport
|
||||
const WebGLRectangleObject* rect = CurValidFBRectObject();
|
||||
const WebGLRectangleObject* rect = CurValidDrawFBRectObject();
|
||||
if (rect) {
|
||||
if (mViewportWidth > rect->Width() ||
|
||||
mViewportHeight > rect->Height())
|
||||
|
@ -29,8 +29,8 @@ WebGLContext::Clear(GLbitfield mask)
|
||||
GenerateWarning("Calling gl.clear() with RASTERIZER_DISCARD enabled has no effects.");
|
||||
}
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (!mBoundDrawFramebuffer->CheckAndInitializeAttachments())
|
||||
return ErrorInvalidFramebufferOperation("clear: incomplete framebuffer");
|
||||
|
||||
gl->fClear(mask);
|
||||
@ -131,12 +131,11 @@ WebGLContext::DrawBuffers(const dom::Sequence<GLenum>& buffers)
|
||||
|
||||
const size_t buffersLength = buffers.Length();
|
||||
|
||||
if (buffersLength == 0) {
|
||||
if (!buffersLength) {
|
||||
return ErrorInvalidValue("drawBuffers: invalid <buffers> (buffers must not be empty)");
|
||||
}
|
||||
|
||||
if (mBoundFramebuffer == 0)
|
||||
{
|
||||
if (!mBoundDrawFramebuffer) {
|
||||
// OK: we are rendering in the default framebuffer
|
||||
|
||||
/* EXT_draw_buffers :
|
||||
|
@ -58,24 +58,37 @@ using namespace mozilla::gfx;
|
||||
static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum* baseType,
|
||||
GLint* unitSize);
|
||||
|
||||
const WebGLRectangleObject*
|
||||
WebGLContext::CurValidFBRectObject() const
|
||||
static const WebGLRectangleObject*
|
||||
CurValidFBRectObject(const WebGLContext* webgl,
|
||||
const WebGLFramebuffer* boundFB)
|
||||
{
|
||||
const WebGLRectangleObject* rect = nullptr;
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (boundFB) {
|
||||
// We don't really need to ask the driver.
|
||||
// Use 'precheck' to just check that our internal state looks good.
|
||||
FBStatus precheckStatus = mBoundFramebuffer->PrecheckFramebufferStatus();
|
||||
FBStatus precheckStatus = boundFB->PrecheckFramebufferStatus();
|
||||
if (precheckStatus == LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
rect = &mBoundFramebuffer->RectangleObject();
|
||||
rect = &boundFB->RectangleObject();
|
||||
} else {
|
||||
rect = static_cast<const WebGLRectangleObject*>(this);
|
||||
rect = static_cast<const WebGLRectangleObject*>(webgl);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
const WebGLRectangleObject*
|
||||
WebGLContext::CurValidDrawFBRectObject() const
|
||||
{
|
||||
return CurValidFBRectObject(this, mBoundDrawFramebuffer);
|
||||
}
|
||||
|
||||
const WebGLRectangleObject*
|
||||
WebGLContext::CurValidReadFBRectObject() const
|
||||
{
|
||||
return CurValidFBRectObject(this, mBoundReadFramebuffer);
|
||||
}
|
||||
|
||||
//
|
||||
// WebGL API
|
||||
//
|
||||
@ -164,8 +177,8 @@ WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer* wfb)
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnum("bindFramebuffer: target must be GL_FRAMEBUFFER");
|
||||
if (!ValidateFramebufferTarget(target, "bindFramebuffer"))
|
||||
return;
|
||||
|
||||
if (!ValidateObjectAllowDeletedOrNull("bindFramebuffer", wfb))
|
||||
return;
|
||||
@ -184,7 +197,20 @@ WebGLContext::BindFramebuffer(GLenum target, WebGLFramebuffer* wfb)
|
||||
gl->fBindFramebuffer(target, framebuffername);
|
||||
}
|
||||
|
||||
mBoundFramebuffer = wfb;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
mBoundDrawFramebuffer = wfb;
|
||||
mBoundReadFramebuffer = wfb;
|
||||
break;
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
mBoundDrawFramebuffer = wfb;
|
||||
break;
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
mBoundReadFramebuffer = wfb;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -351,30 +377,38 @@ WebGLContext::CheckFramebufferStatus(GLenum target)
|
||||
if (IsContextLost())
|
||||
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER) {
|
||||
ErrorInvalidEnum("checkFramebufferStatus: target must be FRAMEBUFFER");
|
||||
if (!ValidateFramebufferTarget(target, "invalidateFramebuffer"))
|
||||
return 0;
|
||||
|
||||
WebGLFramebuffer* fb;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
if (!fb)
|
||||
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
|
||||
|
||||
return mBoundFramebuffer->CheckFramebufferStatus().get();
|
||||
return fb->CheckFramebufferStatus().get();
|
||||
}
|
||||
|
||||
void
|
||||
WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
|
||||
GLint level,
|
||||
WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget, GLint level,
|
||||
TexInternalFormat internalformat,
|
||||
GLint xoffset,
|
||||
GLint yoffset,
|
||||
GLint x,
|
||||
GLint y,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLint xoffset, GLint yoffset, GLint x,
|
||||
GLint y, GLsizei width, GLsizei height,
|
||||
bool sub)
|
||||
{
|
||||
const WebGLRectangleObject* framebufferRect = CurValidFBRectObject();
|
||||
const WebGLRectangleObject* framebufferRect = CurValidReadFBRectObject();
|
||||
GLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
|
||||
GLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
|
||||
|
||||
@ -399,7 +433,7 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
|
||||
if (!ValidateCopyTexImage(internalformat.get(), func, dims))
|
||||
return;
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
if (!mBoundReadFramebuffer)
|
||||
ClearBackbufferIfNeeded();
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -416,8 +450,8 @@ WebGLContext::CopyTexSubImage2D_base(TexImageTarget texImageTarget,
|
||||
}
|
||||
|
||||
TexType framebuffertype = LOCAL_GL_NONE;
|
||||
if (mBoundFramebuffer) {
|
||||
TexInternalFormat framebuffereffectiveformat = mBoundFramebuffer->ColorAttachment(0).EffectiveInternalFormat();
|
||||
if (mBoundReadFramebuffer) {
|
||||
TexInternalFormat framebuffereffectiveformat = mBoundReadFramebuffer->ColorAttachment(0).EffectiveInternalFormat();
|
||||
framebuffertype = TypeFromInternalFormat(framebuffereffectiveformat);
|
||||
} else {
|
||||
// FIXME - here we're assuming that the default framebuffer is backed by UNSIGNED_BYTE
|
||||
@ -541,7 +575,7 @@ WebGLContext::CopyTexImage2D(GLenum rawTexImgTarget,
|
||||
if (!ValidateCopyTexImage(internalformat, func, dims))
|
||||
return;
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
if (!mBoundReadFramebuffer)
|
||||
ClearBackbufferIfNeeded();
|
||||
|
||||
CopyTexSubImage2D_base(rawTexImgTarget, level, internalformat, 0, 0, x, y, width, height, false);
|
||||
@ -605,7 +639,7 @@ WebGLContext::CopyTexSubImage2D(GLenum rawTexImgTarget,
|
||||
if (yoffset + height > texHeight || yoffset + height < 0)
|
||||
return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
if (!mBoundReadFramebuffer)
|
||||
ClearBackbufferIfNeeded();
|
||||
|
||||
if (imageInfo.HasUninitializedImageData()) {
|
||||
@ -681,9 +715,18 @@ WebGLContext::DeleteFramebuffer(WebGLFramebuffer* fbuf)
|
||||
|
||||
fbuf->RequestDelete();
|
||||
|
||||
if (mBoundFramebuffer == fbuf)
|
||||
BindFramebuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
if (mBoundReadFramebuffer == mBoundDrawFramebuffer) {
|
||||
if (mBoundDrawFramebuffer == fbuf) {
|
||||
BindFramebuffer(LOCAL_GL_FRAMEBUFFER,
|
||||
static_cast<WebGLFramebuffer*>(nullptr));
|
||||
}
|
||||
} else if (mBoundDrawFramebuffer == fbuf) {
|
||||
BindFramebuffer(LOCAL_GL_DRAW_FRAMEBUFFER,
|
||||
static_cast<WebGLFramebuffer*>(nullptr));
|
||||
} else if (mBoundReadFramebuffer == fbuf) {
|
||||
BindFramebuffer(LOCAL_GL_READ_FRAMEBUFFER,
|
||||
static_cast<WebGLFramebuffer*>(nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -698,8 +741,11 @@ WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer* rbuf)
|
||||
if (!rbuf || rbuf->IsDeleted())
|
||||
return;
|
||||
|
||||
if (mBoundFramebuffer)
|
||||
mBoundFramebuffer->DetachRenderbuffer(rbuf);
|
||||
if (mBoundDrawFramebuffer)
|
||||
mBoundDrawFramebuffer->DetachRenderbuffer(rbuf);
|
||||
|
||||
if (mBoundReadFramebuffer)
|
||||
mBoundReadFramebuffer->DetachRenderbuffer(rbuf);
|
||||
|
||||
// Invalidate framebuffer status cache
|
||||
rbuf->NotifyFBsStatusChanged();
|
||||
@ -723,8 +769,11 @@ WebGLContext::DeleteTexture(WebGLTexture* tex)
|
||||
if (!tex || tex->IsDeleted())
|
||||
return;
|
||||
|
||||
if (mBoundFramebuffer)
|
||||
mBoundFramebuffer->DetachTexture(tex);
|
||||
if (mBoundDrawFramebuffer)
|
||||
mBoundDrawFramebuffer->DetachTexture(tex);
|
||||
|
||||
if (mBoundReadFramebuffer)
|
||||
mBoundReadFramebuffer->DetachTexture(tex);
|
||||
|
||||
// Invalidate framebuffer status cache
|
||||
tex->NotifyFBsStatusChanged();
|
||||
@ -823,19 +872,41 @@ WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment,
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify framebuffer 0");
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
|
||||
|
||||
if (rbtarget != LOCAL_GL_RENDERBUFFER)
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
|
||||
|
||||
if (!ValidateFramebufferAttachment(attachment, "framebufferRenderbuffer"))
|
||||
if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
|
||||
return;
|
||||
|
||||
return mBoundFramebuffer->FramebufferRenderbuffer(attachment, rbtarget, wrb);
|
||||
WebGLFramebuffer* fb;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify"
|
||||
" framebuffer 0.");
|
||||
}
|
||||
|
||||
if (rbtarget != LOCAL_GL_RENDERBUFFER) {
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: rbtarget:",
|
||||
rbtarget);
|
||||
}
|
||||
|
||||
if (!ValidateFramebufferAttachment(fb, attachment,
|
||||
"framebufferRenderbuffer"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
fb->FramebufferRenderbuffer(attachment, rbtarget, wrb);
|
||||
}
|
||||
|
||||
void
|
||||
@ -848,23 +919,41 @@ WebGLContext::FramebufferTexture2D(GLenum target,
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify framebuffer 0");
|
||||
if (!ValidateFramebufferTarget(target, "framebufferTexture2D"))
|
||||
return;
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnumInfo("framebufferTexture2D: target", target);
|
||||
WebGLFramebuffer* fb;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
return ErrorInvalidOperation("framebufferTexture2D: cannot modify"
|
||||
" framebuffer 0.");
|
||||
}
|
||||
|
||||
if (textarget != LOCAL_GL_TEXTURE_2D &&
|
||||
(textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
|
||||
textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
|
||||
{
|
||||
return ErrorInvalidEnumInfo("framebufferTexture2D: invalid texture target", textarget);
|
||||
return ErrorInvalidEnumInfo("framebufferTexture2D: textarget:",
|
||||
textarget);
|
||||
}
|
||||
|
||||
if (!ValidateFramebufferAttachment(attachment, "framebufferTexture2D"))
|
||||
if (!ValidateFramebufferAttachment(fb, attachment, "framebufferTexture2D"))
|
||||
return;
|
||||
|
||||
return mBoundFramebuffer->FramebufferTexture2D(attachment, textarget, tobj, level);
|
||||
fb->FramebufferTexture2D(attachment, textarget, tobj, level);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1148,25 +1237,42 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
||||
if (IsContextLost())
|
||||
return JS::NullValue();
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER) {
|
||||
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: target", target);
|
||||
if (!ValidateFramebufferTarget(target, "getFramebufferAttachmentParameter"))
|
||||
return JS::NullValue();
|
||||
|
||||
WebGLFramebuffer* fb;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
fb = mBoundDrawFramebuffer;
|
||||
break;
|
||||
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
fb = mBoundReadFramebuffer;
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_CRASH("Bad target.");
|
||||
}
|
||||
|
||||
if (!fb) {
|
||||
ErrorInvalidOperation("getFramebufferAttachmentParameter: cannot query"
|
||||
" framebuffer 0.");
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
if (!mBoundFramebuffer) {
|
||||
ErrorInvalidOperation("getFramebufferAttachmentParameter: cannot query framebuffer 0");
|
||||
if (!ValidateFramebufferAttachment(fb, attachment,
|
||||
"getFramebufferAttachmentParameter"))
|
||||
{
|
||||
return JS::NullValue();
|
||||
}
|
||||
|
||||
if (!ValidateFramebufferAttachment(attachment, "getFramebufferAttachmentParameter"))
|
||||
return JS::NullValue();
|
||||
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
|
||||
mBoundFramebuffer->EnsureColorAttachments(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
fb->EnsureColorAttachments(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
const WebGLFramebuffer::Attachment& fba = mBoundFramebuffer->GetAttachment(attachment);
|
||||
const WebGLFramebuffer::Attachment& fba = fb->GetAttachment(attachment);
|
||||
|
||||
if (fba.Renderbuffer()) {
|
||||
switch (pname) {
|
||||
@ -2256,7 +2362,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||
if (pixels.IsNull())
|
||||
return ErrorInvalidValue("readPixels: null destination buffer");
|
||||
|
||||
const WebGLRectangleObject* framebufferRect = CurValidFBRectObject();
|
||||
const WebGLRectangleObject* framebufferRect = CurValidReadFBRectObject();
|
||||
GLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
|
||||
GLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
|
||||
|
||||
@ -2344,11 +2450,11 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||
}
|
||||
|
||||
bool isSourceTypeFloat = false;
|
||||
if (mBoundFramebuffer &&
|
||||
mBoundFramebuffer->ColorAttachmentCount() &&
|
||||
mBoundFramebuffer->ColorAttachment(0).IsDefined())
|
||||
if (mBoundReadFramebuffer &&
|
||||
mBoundReadFramebuffer->ColorAttachmentCount() &&
|
||||
mBoundReadFramebuffer->ColorAttachment(0).IsDefined())
|
||||
{
|
||||
isSourceTypeFloat = mBoundFramebuffer->ColorAttachment(0).IsReadableFloat();
|
||||
isSourceTypeFloat = mBoundReadFramebuffer->ColorAttachment(0).IsReadableFloat();
|
||||
}
|
||||
|
||||
if (isReadTypeFloat != isSourceTypeFloat)
|
||||
@ -2357,13 +2463,13 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||
// Check the format and type params to assure they are an acceptable pair (as per spec)
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (mBoundReadFramebuffer) {
|
||||
// prevent readback of arbitrary video memory through uninitialized renderbuffers!
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments())
|
||||
if (!mBoundReadFramebuffer->CheckAndInitializeAttachments())
|
||||
return ErrorInvalidFramebufferOperation("readPixels: incomplete framebuffer");
|
||||
|
||||
GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
|
||||
if (!mBoundReadFramebuffer->HasCompletePlanes(readPlaneBits)) {
|
||||
return ErrorInvalidOperation("readPixels: Read source attachment doesn't have the"
|
||||
" correct color/depth/stencil type.");
|
||||
}
|
||||
@ -2486,8 +2592,8 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||
return;
|
||||
|
||||
bool needAlphaFilled;
|
||||
if (mBoundFramebuffer) {
|
||||
needAlphaFilled = !mBoundFramebuffer->ColorAttachment(0).HasAlpha();
|
||||
if (mBoundReadFramebuffer) {
|
||||
needAlphaFilled = !mBoundReadFramebuffer->ColorAttachment(0).HasAlpha();
|
||||
} else {
|
||||
needAlphaFilled = !mOptions.alpha;
|
||||
}
|
||||
|
@ -74,15 +74,15 @@ bool
|
||||
WebGLContext::GetStencilBits(GLint* out_stencilBits)
|
||||
{
|
||||
*out_stencilBits = 0;
|
||||
if (mBoundFramebuffer) {
|
||||
if (mBoundFramebuffer->HasDepthStencilConflict()) {
|
||||
if (mBoundDrawFramebuffer) {
|
||||
if (mBoundDrawFramebuffer->HasDepthStencilConflict()) {
|
||||
// Error, we don't know which stencil buffer's bits to use
|
||||
ErrorInvalidFramebufferOperation("getParameter: framebuffer has two stencil buffers bound");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mBoundFramebuffer->StencilAttachment().IsDefined() ||
|
||||
mBoundFramebuffer->DepthStencilAttachment().IsDefined())
|
||||
if (mBoundDrawFramebuffer->StencilAttachment().IsDefined() ||
|
||||
mBoundDrawFramebuffer->DepthStencilAttachment().IsDefined())
|
||||
{
|
||||
*out_stencilBits = 8;
|
||||
}
|
||||
@ -150,7 +150,7 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
} else if (pname >= LOCAL_GL_DRAW_BUFFER0 &&
|
||||
pname < GLenum(LOCAL_GL_DRAW_BUFFER0 + mGLMaxDrawBuffers))
|
||||
{
|
||||
if (mBoundFramebuffer) {
|
||||
if (mBoundDrawFramebuffer) {
|
||||
GLint iv = 0;
|
||||
gl->fGetIntegerv(pname, &iv);
|
||||
return JS::Int32Value(iv);
|
||||
@ -190,6 +190,10 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
case LOCAL_GL_TEXTURE_BINDING_3D: {
|
||||
return WebGLObjectAsJSValue(cx, mBound3DTextures[mActiveTexture].get(), rv);
|
||||
}
|
||||
|
||||
// DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
|
||||
case LOCAL_GL_READ_FRAMEBUFFER_BINDING:
|
||||
return WebGLObjectAsJSValue(cx, mBoundReadFramebuffer.get(), rv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -509,8 +513,9 @@ WebGLContext::GetParameter(JSContext* cx, GLenum pname, ErrorResult& rv)
|
||||
return WebGLObjectAsJSValue(cx, mBoundRenderbuffer.get(), rv);
|
||||
}
|
||||
|
||||
// DRAW_FRAMEBUFFER_BINDING is the same as FRAMEBUFFER_BINDING.
|
||||
case LOCAL_GL_FRAMEBUFFER_BINDING: {
|
||||
return WebGLObjectAsJSValue(cx, mBoundFramebuffer.get(), rv);
|
||||
return WebGLObjectAsJSValue(cx, mBoundDrawFramebuffer.get(), rv);
|
||||
}
|
||||
|
||||
case LOCAL_GL_CURRENT_PROGRAM: {
|
||||
|
@ -598,11 +598,14 @@ WebGLContext::EnumName(GLenum glenum)
|
||||
XX(DEPTH_COMPONENT32);
|
||||
XX(DEPTH_STENCIL);
|
||||
XX(DEPTH24_STENCIL8);
|
||||
XX(DRAW_FRAMEBUFFER);
|
||||
XX(ETC1_RGB8_OES);
|
||||
XX(FLOAT);
|
||||
XX(FRAMEBUFFER);
|
||||
XX(HALF_FLOAT);
|
||||
XX(LUMINANCE);
|
||||
XX(LUMINANCE_ALPHA);
|
||||
XX(READ_FRAMEBUFFER);
|
||||
XX(RGB);
|
||||
XX(RGB16F);
|
||||
XX(RGB32F);
|
||||
@ -771,8 +774,6 @@ WebGLContext::EnumName(GLenum glenum)
|
||||
XX(DEPTH_STENCIL_ATTACHMENT);
|
||||
XX(UNSIGNED_NORMALIZED);
|
||||
XX(DRAW_FRAMEBUFFER_BINDING);
|
||||
XX(READ_FRAMEBUFFER);
|
||||
XX(DRAW_FRAMEBUFFER);
|
||||
XX(READ_FRAMEBUFFER_BINDING);
|
||||
XX(RENDERBUFFER_SAMPLES);
|
||||
XX(FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
|
||||
@ -1028,10 +1029,21 @@ WebGLContext::AssertCachedBindings()
|
||||
}
|
||||
|
||||
// Bound object state
|
||||
GLuint bound = mBoundFramebuffer ? mBoundFramebuffer->GLName() : 0;
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_FRAMEBUFFER_BINDING, bound);
|
||||
if (IsWebGL2()) {
|
||||
GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->GLName()
|
||||
: 0;
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_DRAW_FRAMEBUFFER_BINDING, bound);
|
||||
|
||||
bound = mCurrentProgram ? mCurrentProgram->GLName() : 0;
|
||||
bound = mBoundReadFramebuffer ? mBoundReadFramebuffer->GLName() : 0;
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_READ_FRAMEBUFFER_BINDING, bound);
|
||||
} else {
|
||||
MOZ_ASSERT(mBoundDrawFramebuffer == mBoundReadFramebuffer);
|
||||
GLuint bound = mBoundDrawFramebuffer ? mBoundDrawFramebuffer->GLName()
|
||||
: 0;
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_FRAMEBUFFER_BINDING, bound);
|
||||
}
|
||||
|
||||
GLuint bound = mCurrentProgram ? mCurrentProgram->GLName() : 0;
|
||||
AssertUintParamCorrect(gl, LOCAL_GL_CURRENT_PROGRAM, bound);
|
||||
|
||||
// Textures
|
||||
|
@ -416,10 +416,10 @@ bool WebGLContext::ValidateGLSLString(const nsAString& string, const char* info)
|
||||
* be one of depth/stencil/depth_stencil/color attachment.
|
||||
*/
|
||||
bool
|
||||
WebGLContext::ValidateFramebufferAttachment(GLenum attachment,
|
||||
WebGLContext::ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
|
||||
const char* funcName)
|
||||
{
|
||||
if (!mBoundFramebuffer) {
|
||||
if (!fb) {
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_COLOR:
|
||||
case LOCAL_GL_DEPTH:
|
||||
@ -1328,27 +1328,26 @@ WebGLContext::ValidateCopyTexImage(GLenum format, WebGLTexImageFunc func,
|
||||
// Default framebuffer format
|
||||
GLenum fboFormat = mOptions.alpha ? LOCAL_GL_RGBA : LOCAL_GL_RGB;
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
if (!mBoundFramebuffer->CheckAndInitializeAttachments()) {
|
||||
if (mBoundReadFramebuffer) {
|
||||
if (!mBoundReadFramebuffer->CheckAndInitializeAttachments()) {
|
||||
ErrorInvalidFramebufferOperation("%s: Incomplete framebuffer.",
|
||||
InfoFrom(func, dims));
|
||||
return false;
|
||||
}
|
||||
|
||||
GLenum readPlaneBits = LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
if (!mBoundFramebuffer->HasCompletePlanes(readPlaneBits)) {
|
||||
if (!mBoundReadFramebuffer->HasCompletePlanes(readPlaneBits)) {
|
||||
ErrorInvalidOperation("%s: Read source attachment doesn't have the"
|
||||
" correct color/depth/stencil type.",
|
||||
InfoFrom(func, dims));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the correct format for the framebuffer, as it's not the default
|
||||
// one.
|
||||
// Get the correct format for the framebuffer, as it's not the default one.
|
||||
const WebGLFramebuffer::Attachment& color0 =
|
||||
mBoundFramebuffer->GetAttachment(LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
mBoundReadFramebuffer->GetAttachment(LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
|
||||
fboFormat = mBoundFramebuffer->GetFormatForAttachment(color0);
|
||||
fboFormat = mBoundReadFramebuffer->GetFormatForAttachment(color0);
|
||||
}
|
||||
|
||||
// Make sure the format of the framebuffer is a superset of the format
|
||||
@ -1949,7 +1948,8 @@ WebGLContext::InitAndValidateGL()
|
||||
mBoundTransformFeedbackBuffer = nullptr;
|
||||
mCurrentProgram = nullptr;
|
||||
|
||||
mBoundFramebuffer = nullptr;
|
||||
mBoundDrawFramebuffer = nullptr;
|
||||
mBoundReadFramebuffer = nullptr;
|
||||
mBoundRenderbuffer = nullptr;
|
||||
|
||||
MakeContextCurrent();
|
||||
@ -2143,4 +2143,32 @@ WebGLContext::InitAndValidateGL()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLContext::ValidateFramebufferTarget(GLenum target,
|
||||
const char* const info)
|
||||
{
|
||||
bool isValid = true;
|
||||
switch (target) {
|
||||
case LOCAL_GL_FRAMEBUFFER:
|
||||
break;
|
||||
|
||||
case LOCAL_GL_DRAW_FRAMEBUFFER:
|
||||
case LOCAL_GL_READ_FRAMEBUFFER:
|
||||
isValid = IsWebGL2();
|
||||
break;
|
||||
|
||||
default:
|
||||
isValid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (MOZ_LIKELY(isValid)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ErrorInvalidEnum("%s: Invalid target: %s (0x%04x).", info, EnumName(target),
|
||||
target);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -455,7 +455,8 @@ WebGLFramebuffer::FramebufferRenderbuffer(FBAttachment attachPoint,
|
||||
RBTarget rbtarget,
|
||||
WebGLRenderbuffer* rb)
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
|
||||
mContext->mBoundReadFramebuffer == this);
|
||||
|
||||
if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer",
|
||||
rb))
|
||||
@ -496,7 +497,8 @@ WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachPoint,
|
||||
TexImageTarget texImageTarget,
|
||||
WebGLTexture* tex, GLint level)
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
|
||||
mContext->mBoundReadFramebuffer == this);
|
||||
|
||||
if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture",
|
||||
tex))
|
||||
@ -564,7 +566,7 @@ WebGLFramebuffer::GetAttachmentOrNull(FBAttachment attachPoint)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mContext->ValidateFramebufferAttachment(attachPoint.get(),
|
||||
if (!mContext->ValidateFramebufferAttachment(this, attachPoint.get(),
|
||||
"getAttachmentOrNull"))
|
||||
{
|
||||
return nullptr;
|
||||
@ -593,7 +595,7 @@ WebGLFramebuffer::GetAttachment(FBAttachment attachPoint) const
|
||||
break;
|
||||
}
|
||||
|
||||
if (!mContext->ValidateFramebufferAttachment(attachPoint.get(),
|
||||
if (!mContext->ValidateFramebufferAttachment(this, attachPoint.get(),
|
||||
"getAttachment"))
|
||||
{
|
||||
MOZ_ASSERT(false);
|
||||
@ -766,7 +768,8 @@ WebGLFramebuffer::RectangleObject() const
|
||||
FBStatus
|
||||
WebGLFramebuffer::PrecheckFramebufferStatus() const
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
|
||||
mContext->mBoundReadFramebuffer == this);
|
||||
|
||||
if (!HasDefinedAttachments())
|
||||
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // No attachments
|
||||
@ -809,7 +812,9 @@ WebGLFramebuffer::HasCompletePlanes(GLbitfield mask)
|
||||
if (CheckFramebufferStatus() != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
|
||||
mContext->mBoundReadFramebuffer == this);
|
||||
|
||||
bool hasPlanes = true;
|
||||
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
|
||||
hasPlanes &= ColorAttachmentCount() &&
|
||||
@ -832,7 +837,8 @@ WebGLFramebuffer::HasCompletePlanes(GLbitfield mask)
|
||||
bool
|
||||
WebGLFramebuffer::CheckAndInitializeAttachments()
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
|
||||
mContext->mBoundReadFramebuffer == this);
|
||||
|
||||
if (CheckFramebufferStatus() != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
@ -578,5 +578,6 @@ skip-if = buildapp == 'b2g' || e10s
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
|
||||
support-files = file_bug871161-1.html file_bug871161-2.html
|
||||
[test_bug1013316.html]
|
||||
[test_hash_encoded.html]
|
||||
[test_bug1081037.html]
|
||||
|
||||
|
91
dom/html/test/test_hash_encoded.html
Normal file
91
dom/html/test/test_hash_encoded.html
Normal file
@ -0,0 +1,91 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test link.hash attribute</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a id="target1" href="http://www.example.com/#q=♥â¥#hello"></a>
|
||||
<a id="target2" href="http://www.example.com/#q=%E2%99%A5%C3%A2%C2%A5"></a>
|
||||
<a id="target3" href="http://www.example.com/#/search/%23important"></a>
|
||||
<a id="target4" href='http://www.example.com/#{"a":[13, 42], "b":{"key":"value"}}'></a>
|
||||
|
||||
<pre id="test">
|
||||
|
||||
<script>
|
||||
// Tests Link::GetHash
|
||||
|
||||
// Check that characters aren't being encoded
|
||||
var target = document.getElementById("target1");
|
||||
is(target.hash, '#q=♥â¥#hello', 'Unexpected link hash');
|
||||
|
||||
// Check that encoded characters aren't being decoded
|
||||
target = document.getElementById("target2");
|
||||
is(target.hash, '#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected link hash');
|
||||
|
||||
// A more regular use case
|
||||
target = document.getElementById("target3");
|
||||
is(target.hash, '#/search/%23important', 'Unexpected link hash');
|
||||
|
||||
// Some JSON
|
||||
target = document.getElementById("target4");
|
||||
is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected link hash');
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Tests URL::GetHash
|
||||
|
||||
var url = new URL("http://www.example.com/#q=♥â¥#hello")
|
||||
is(url.hash, '#q=♥â¥#hello', 'Unexpected url hash');
|
||||
|
||||
url = new URL("http://www.example.com/#q=%E2%99%A5%C3%A2%C2%A5")
|
||||
is(url.hash, '#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected url hash');
|
||||
|
||||
url = new URL("http://www.example.com/#/search/%23important")
|
||||
is(url.hash, '#/search/%23important', 'Unexpected url hash');
|
||||
|
||||
// Test getters and setters
|
||||
|
||||
url = new URL("http://www.example.com/");
|
||||
url.hash = "#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important"
|
||||
is(url.hash, '#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important', 'Unexpected url hash');
|
||||
|
||||
// codepath in nsStandardUrl::SetRef is different if the path is non-empty
|
||||
url = new URL("http://www.example.com/test/");
|
||||
url.hash = "#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important"
|
||||
is(url.hash, '#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important', 'Unexpected url hash');
|
||||
|
||||
url = new URL("http://www.example.com/");
|
||||
url.hash = '#{"a":[13, 42], "b":{"key":"value"}}';
|
||||
is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected url hash');
|
||||
var parsed = JSON.parse(target.hash.substring(1));
|
||||
is(parsed.b.key, 'value', 'JSON not parsed correctly');
|
||||
|
||||
url = new URL("http://www.example.com/test/");
|
||||
url.hash = '#{"a":[13, 42], "b":{"key":"value"}}';
|
||||
is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected url hash');
|
||||
parsed = JSON.parse(target.hash.substring(1));
|
||||
is(parsed.b.key, 'value', 'JSON not parsed correctly');
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Tests nsLocation::GetHash
|
||||
|
||||
window.history.pushState(1, document.title, '#q=♥â¥#hello');
|
||||
is(location.hash,'#q=♥â¥#hello', 'Unexpected location hash');
|
||||
|
||||
window.history.pushState(1, document.title, '#q=%E2%99%A5%C3%A2%C2%A5');
|
||||
is(location.hash,'#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected location hash');
|
||||
|
||||
window.history.pushState(1, document.title, '#/search/%23important');
|
||||
is(location.hash,'#/search/%23important', 'Unexpected location hash');
|
||||
|
||||
window.history.pushState(1, document.title, '#{"a":[13, 42], "b":{"key":"value"}}');
|
||||
is(location.hash,'#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected location hash');
|
||||
</script>
|
||||
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -994,6 +994,11 @@ ContentParent::CreateBrowserOrApp(const TabContext& aContext,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (TabParent* parent = TabParent::GetNextTabParent()) {
|
||||
parent->SetOwnerElement(aFrameElement);
|
||||
return parent;
|
||||
}
|
||||
|
||||
ProcessPriority initialPriority = GetInitialProcessPriority(aFrameElement);
|
||||
bool isInContentProcess = (XRE_GetProcessType() != GeckoProcessType_Default);
|
||||
TabId tabId;
|
||||
|
@ -79,6 +79,12 @@ struct ShowInfo
|
||||
double defaultScale;
|
||||
};
|
||||
|
||||
struct FrameScriptInfo
|
||||
{
|
||||
nsString url;
|
||||
bool runInGlobalScope;
|
||||
};
|
||||
|
||||
prio(normal upto urgent) intr protocol PBrowser
|
||||
{
|
||||
manager PContent or PContentBridge;
|
||||
@ -117,7 +123,8 @@ parent:
|
||||
|
||||
Event(RemoteDOMEvent aEvent);
|
||||
|
||||
intr CreateWindow(uint32_t aChromeFlags,
|
||||
sync CreateWindow(PBrowser aNewTab,
|
||||
uint32_t aChromeFlags,
|
||||
bool aCalledFromJS,
|
||||
bool aPositionSpecified,
|
||||
bool aSizeSpecified,
|
||||
@ -125,7 +132,7 @@ parent:
|
||||
nsString aName,
|
||||
nsString aFeatures,
|
||||
nsString aBaseURI)
|
||||
returns (bool windowIsNew, PBrowser window);
|
||||
returns (bool windowOpened, FrameScriptInfo[] frameScripts);
|
||||
|
||||
sync SyncMessage(nsString aMessage, ClonedMessageData aData,
|
||||
CpowEntry[] aCpows, Principal aPrincipal)
|
||||
|
@ -1429,93 +1429,53 @@ TabChild::ProvideWindow(nsIDOMWindow* aParent, uint32_t aChromeFlags,
|
||||
// isn't a request to open a modal-type window, we're going to create a new
|
||||
// <iframe mozbrowser/mozapp> and return its window here.
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(aParent);
|
||||
if (docshell && docshell->GetIsInBrowserOrApp() &&
|
||||
!(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
|
||||
bool iframeMoz = (docshell && docshell->GetIsInBrowserOrApp() &&
|
||||
!(aChromeFlags & (nsIWebBrowserChrome::CHROME_MODAL |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME)));
|
||||
|
||||
// Note that BrowserFrameProvideWindow may return NS_ERROR_ABORT if the
|
||||
// open window call was canceled. It's important that we pass this error
|
||||
// code back to our caller.
|
||||
return BrowserFrameProvideWindow(aParent, aURI, aName, aFeatures,
|
||||
aWindowIsNew, aReturn);
|
||||
if (!iframeMoz) {
|
||||
int32_t openLocation =
|
||||
nsWindowWatcher::GetWindowOpenLocation(aParent, aChromeFlags, aCalledFromJS,
|
||||
aPositionSpecified, aSizeSpecified);
|
||||
|
||||
// If it turns out we're opening in the current browser, just hand over the
|
||||
// current browser's docshell.
|
||||
if (openLocation == nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
|
||||
nsCOMPtr<nsIWebBrowser> browser = do_GetInterface(WebNavigation());
|
||||
*aWindowIsNew = false;
|
||||
return browser->GetContentDOMWindow(aReturn);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t openLocation =
|
||||
nsWindowWatcher::GetWindowOpenLocation(aParent, aChromeFlags, aCalledFromJS,
|
||||
aPositionSpecified, aSizeSpecified);
|
||||
|
||||
// If it turns out we're opening in the current browser, just hand over the
|
||||
// current browser's docshell.
|
||||
if (openLocation == nsIBrowserDOMWindow::OPEN_CURRENTWINDOW) {
|
||||
nsCOMPtr<nsIWebBrowser> browser = do_GetInterface(WebNavigation());
|
||||
*aWindowIsNew = false;
|
||||
return browser->GetContentDOMWindow(aReturn);
|
||||
}
|
||||
|
||||
// Otherwise, we're opening a new tab or a new window. We have to contact
|
||||
// TabParent in order to do either.
|
||||
|
||||
PBrowserChild* newChild;
|
||||
|
||||
nsAutoCString uriString;
|
||||
if (aURI) {
|
||||
aURI->GetSpec(uriString);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
aParent->GetDocument(getter_AddRefs(domDoc));
|
||||
if (!domDoc) {
|
||||
NS_ERROR("Could retrieve document from nsIBaseWindow");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
doc = do_QueryInterface(domDoc);
|
||||
if (!doc) {
|
||||
NS_ERROR("Document from nsIBaseWindow didn't QI to nsIDocument");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
|
||||
if (!baseURI) {
|
||||
NS_ERROR("nsIDocument didn't return a base URI");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString baseURIString;
|
||||
baseURI->GetSpec(baseURIString);
|
||||
|
||||
nsAutoString nameString;
|
||||
nameString.Assign(aName);
|
||||
nsAutoCString features;
|
||||
|
||||
// We can assume that if content is requesting to open a window from a remote
|
||||
// tab, then we want to enforce that the new window is also a remote tab.
|
||||
features.Assign(aFeatures);
|
||||
features.Append(",remote");
|
||||
|
||||
if (!CallCreateWindow(aChromeFlags, aCalledFromJS, aPositionSpecified,
|
||||
aSizeSpecified, NS_ConvertUTF8toUTF16(uriString),
|
||||
nameString, NS_ConvertUTF8toUTF16(features),
|
||||
NS_ConvertUTF8toUTF16(baseURIString),
|
||||
aWindowIsNew, &newChild)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> win =
|
||||
do_GetInterface(static_cast<TabChild*>(newChild)->WebNavigation());
|
||||
win.forget(aReturn);
|
||||
return NS_OK;
|
||||
// Note that ProvideWindowCommon may return NS_ERROR_ABORT if the
|
||||
// open window call was canceled. It's important that we pass this error
|
||||
// code back to our caller.
|
||||
return ProvideWindowCommon(aParent,
|
||||
iframeMoz,
|
||||
aChromeFlags,
|
||||
aCalledFromJS,
|
||||
aPositionSpecified,
|
||||
aSizeSpecified,
|
||||
aURI,
|
||||
aName,
|
||||
aFeatures,
|
||||
aWindowIsNew,
|
||||
aReturn);
|
||||
}
|
||||
|
||||
nsresult
|
||||
TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
nsIURI* aURI,
|
||||
const nsAString& aName,
|
||||
const nsACString& aFeatures,
|
||||
bool* aWindowIsNew,
|
||||
nsIDOMWindow** aReturn)
|
||||
TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
|
||||
bool aIframeMoz,
|
||||
uint32_t aChromeFlags,
|
||||
bool aCalledFromJS,
|
||||
bool aPositionSpecified,
|
||||
bool aSizeSpecified,
|
||||
nsIURI* aURI,
|
||||
const nsAString& aName,
|
||||
const nsACString& aFeatures,
|
||||
bool* aWindowIsNew,
|
||||
nsIDOMWindow** aReturn)
|
||||
{
|
||||
*aReturn = nullptr;
|
||||
|
||||
@ -1539,7 +1499,7 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
&tabId);
|
||||
|
||||
nsRefPtr<TabChild> newChild = new TabChild(ContentChild::GetSingleton(), tabId,
|
||||
/* TabContext */ *this, /* chromeFlags */ 0);
|
||||
/* TabContext */ *this, aChromeFlags);
|
||||
if (NS_FAILED(newChild->Init())) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
@ -1548,7 +1508,7 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
unused << Manager()->SendPBrowserConstructor(
|
||||
// We release this ref in DeallocPBrowserChild
|
||||
nsRefPtr<TabChild>(newChild).forget().take(),
|
||||
tabId, IPCTabContext(context, mScrolling), /* chromeFlags */ 0,
|
||||
tabId, IPCTabContext(context, mScrolling), aChromeFlags,
|
||||
cc->GetID(), cc->IsForApp(), cc->IsForBrowser());
|
||||
|
||||
nsAutoCString spec;
|
||||
@ -1558,9 +1518,51 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
|
||||
NS_ConvertUTF8toUTF16 url(spec);
|
||||
nsString name(aName);
|
||||
NS_ConvertUTF8toUTF16 features(aFeatures);
|
||||
newChild->SendBrowserFrameOpenWindow(this, url, name,
|
||||
features, aWindowIsNew);
|
||||
nsAutoCString features(aFeatures);
|
||||
nsTArray<FrameScriptInfo> frameScripts;
|
||||
|
||||
if (aIframeMoz) {
|
||||
newChild->SendBrowserFrameOpenWindow(this, url, name,
|
||||
NS_ConvertUTF8toUTF16(features),
|
||||
aWindowIsNew);
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
aOpener->GetDocument(getter_AddRefs(domDoc));
|
||||
if (!domDoc) {
|
||||
NS_ERROR("Could retrieve document from nsIBaseWindow");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
doc = do_QueryInterface(domDoc);
|
||||
if (!doc) {
|
||||
NS_ERROR("Document from nsIBaseWindow didn't QI to nsIDocument");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI();
|
||||
if (!baseURI) {
|
||||
NS_ERROR("nsIDocument didn't return a base URI");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString baseURIString;
|
||||
baseURI->GetSpec(baseURIString);
|
||||
|
||||
// We can assume that if content is requesting to open a window from a remote
|
||||
// tab, then we want to enforce that the new window is also a remote tab.
|
||||
features.AppendLiteral(",remote");
|
||||
|
||||
if (!SendCreateWindow(newChild,
|
||||
aChromeFlags, aCalledFromJS, aPositionSpecified,
|
||||
aSizeSpecified, url,
|
||||
name, NS_ConvertUTF8toUTF16(features),
|
||||
NS_ConvertUTF8toUTF16(baseURIString),
|
||||
aWindowIsNew,
|
||||
&frameScripts)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
if (!*aWindowIsNew) {
|
||||
PBrowserChild::Send__delete__(newChild);
|
||||
return NS_ERROR_ABORT;
|
||||
@ -1583,6 +1585,13 @@ TabChild::BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
// pretty bogus; see bug 763602.
|
||||
newChild->DoFakeShow(scrolling, textureFactoryIdentifier, layersId, renderFrame);
|
||||
|
||||
for (size_t i = 0; i < frameScripts.Length(); i++) {
|
||||
FrameScriptInfo& info = frameScripts[i];
|
||||
if (!newChild->RecvLoadRemoteScript(info.url(), info.runInGlobalScope())) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> win = do_GetInterface(newChild->WebNavigation());
|
||||
win.forget(aReturn);
|
||||
return NS_OK;
|
||||
@ -1914,7 +1923,14 @@ TabChild::ApplyShowInfo(const ShowInfo& aInfo)
|
||||
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIDocShellTreeItem> item = do_GetInterface(docShell);
|
||||
item->SetName(aInfo.name());
|
||||
if (IsBrowserOrApp()) {
|
||||
// B2G allows window.name to be set by changing the name attribute on the
|
||||
// <iframe mozbrowser> element. window.open calls cause this attribute to
|
||||
// be set to the correct value. A normal <xul:browser> element has no such
|
||||
// attribute. The data we get here comes from reading the attribute, so we
|
||||
// shouldn't trust it for <xul:browser> elements.
|
||||
item->SetName(aInfo.name());
|
||||
}
|
||||
docShell->SetFullscreenAllowed(aInfo.fullscreenAllowed());
|
||||
if (aInfo.isPrivate()) {
|
||||
bool nonBlank;
|
||||
|
@ -574,12 +574,17 @@ private:
|
||||
void UpdateTapState(const WidgetTouchEvent& aEvent, nsEventStatus aStatus);
|
||||
|
||||
nsresult
|
||||
BrowserFrameProvideWindow(nsIDOMWindow* aOpener,
|
||||
nsIURI* aURI,
|
||||
const nsAString& aName,
|
||||
const nsACString& aFeatures,
|
||||
bool* aWindowIsNew,
|
||||
nsIDOMWindow** aReturn);
|
||||
ProvideWindowCommon(nsIDOMWindow* aOpener,
|
||||
bool aIframeMoz,
|
||||
uint32_t aChromeFlags,
|
||||
bool aCalledFromJS,
|
||||
bool aPositionSpecified,
|
||||
bool aSizeSpecified,
|
||||
nsIURI* aURI,
|
||||
const nsAString& aName,
|
||||
const nsACString& aFeatures,
|
||||
bool* aWindowIsNew,
|
||||
nsIDOMWindow** aReturn);
|
||||
|
||||
bool HasValidInnerSize();
|
||||
|
||||
|
@ -272,6 +272,7 @@ TabParent::TabParent(nsIContentParent* aManager,
|
||||
, mChromeFlags(aChromeFlags)
|
||||
, mInitedByParent(false)
|
||||
, mTabId(aTabId)
|
||||
, mSkipLoad(false)
|
||||
{
|
||||
MOZ_ASSERT(aManager);
|
||||
}
|
||||
@ -449,18 +450,49 @@ TabParent::RecvEvent(const RemoteDOMEvent& aEvent)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
|
||||
const bool& aCalledFromJS,
|
||||
const bool& aPositionSpecified,
|
||||
const bool& aSizeSpecified,
|
||||
const nsString& aURI,
|
||||
const nsString& aName,
|
||||
const nsString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
bool* aWindowIsNew,
|
||||
PBrowserParent** aRetVal)
|
||||
struct MOZ_STACK_CLASS TabParent::AutoUseNewTab MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
AutoUseNewTab(TabParent* aNewTab, bool* aWindowIsNew)
|
||||
: mNewTab(aNewTab), mWindowIsNew(aWindowIsNew)
|
||||
{
|
||||
MOZ_ASSERT(!TabParent::sNextTabParent);
|
||||
TabParent::sNextTabParent = aNewTab;
|
||||
aNewTab->mSkipLoad = true;
|
||||
}
|
||||
|
||||
~AutoUseNewTab()
|
||||
{
|
||||
mNewTab->mSkipLoad = false;
|
||||
|
||||
if (TabParent::sNextTabParent) {
|
||||
MOZ_ASSERT(TabParent::sNextTabParent == mNewTab);
|
||||
TabParent::sNextTabParent = nullptr;
|
||||
*mWindowIsNew = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
TabParent* mNewTab;
|
||||
bool* mWindowIsNew;
|
||||
};
|
||||
|
||||
bool
|
||||
TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
||||
const uint32_t& aChromeFlags,
|
||||
const bool& aCalledFromJS,
|
||||
const bool& aPositionSpecified,
|
||||
const bool& aSizeSpecified,
|
||||
const nsString& aURI,
|
||||
const nsString& aName,
|
||||
const nsString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
bool* aWindowIsNew,
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts)
|
||||
{
|
||||
// We always expect to open a new window here. If we don't, it's an error.
|
||||
*aWindowIsNew = true;
|
||||
|
||||
if (IsBrowserOrApp()) {
|
||||
return false;
|
||||
}
|
||||
@ -470,6 +502,8 @@ TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
|
||||
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
TabParent* newTab = static_cast<TabParent*>(aNewTab);
|
||||
|
||||
nsCOMPtr<nsIContent> frame(do_QueryInterface(mFrameElement));
|
||||
NS_ENSURE_TRUE(frame, false);
|
||||
|
||||
@ -483,8 +517,6 @@ TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
|
||||
MOZ_ASSERT(openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB ||
|
||||
openLocation == nsIBrowserDOMWindow::OPEN_NEWWINDOW);
|
||||
|
||||
*aWindowIsNew = true;
|
||||
|
||||
// Opening new tabs is the easy case...
|
||||
if (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB) {
|
||||
NS_ENSURE_TRUE(mBrowserDOMWindow, false);
|
||||
@ -497,17 +529,18 @@ TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
|
||||
params->SetReferrer(aBaseURI);
|
||||
params->SetIsPrivate(isPrivate);
|
||||
|
||||
AutoUseNewTab aunt(newTab, aWindowIsNew);
|
||||
|
||||
nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner;
|
||||
mBrowserDOMWindow->OpenURIInFrame(nullptr, params,
|
||||
nsIBrowserDOMWindow::OPEN_NEWTAB,
|
||||
openLocation,
|
||||
nsIBrowserDOMWindow::OPEN_NEW,
|
||||
getter_AddRefs(frameLoaderOwner));
|
||||
NS_ENSURE_TRUE(frameLoaderOwner, false);
|
||||
if (!frameLoaderOwner) {
|
||||
*aWindowIsNew = false;
|
||||
}
|
||||
|
||||
nsRefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader();
|
||||
NS_ENSURE_TRUE(frameLoader, false);
|
||||
|
||||
*aRetVal = frameLoader->GetRemoteBrowser();
|
||||
aFrameScripts->SwapElements(newTab->mDelayedFrameScripts);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -530,6 +563,8 @@ TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
|
||||
AutoUseNewTab aunt(newTab, aWindowIsNew);
|
||||
|
||||
rv = pwwatch->OpenWindow2(parent, finalURIString.get(),
|
||||
NS_ConvertUTF16toUTF8(aName).get(),
|
||||
NS_ConvertUTF16toUTF8(aFeatures).get(), aCalledFromJS,
|
||||
@ -545,15 +580,45 @@ TabParent::AnswerCreateWindow(const uint32_t& aChromeFlags,
|
||||
nsCOMPtr<nsITabParent> newRemoteTab = newDocShell->GetOpenedRemote();
|
||||
NS_ENSURE_TRUE(newRemoteTab, false);
|
||||
|
||||
*aRetVal = static_cast<TabParent*>(newRemoteTab.get());
|
||||
MOZ_ASSERT(static_cast<TabParent*>(newRemoteTab.get()) == newTab);
|
||||
|
||||
aFrameScripts->SwapElements(newTab->mDelayedFrameScripts);
|
||||
return true;
|
||||
}
|
||||
|
||||
TabParent* TabParent::sNextTabParent;
|
||||
|
||||
/* static */ TabParent*
|
||||
TabParent::GetNextTabParent()
|
||||
{
|
||||
TabParent* result = sNextTabParent;
|
||||
sNextTabParent = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::SendLoadRemoteScript(const nsString& aURL,
|
||||
const bool& aRunInGlobalScope)
|
||||
{
|
||||
if (mSkipLoad) {
|
||||
mDelayedFrameScripts.AppendElement(FrameScriptInfo(aURL, aRunInGlobalScope));
|
||||
return true;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mDelayedFrameScripts.IsEmpty());
|
||||
return PBrowserParent::SendLoadRemoteScript(aURL, aRunInGlobalScope);
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::LoadURL(nsIURI* aURI)
|
||||
{
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
if (mSkipLoad) {
|
||||
// Don't send the message if the child wants to load its own URL.
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsDestroyed) {
|
||||
return;
|
||||
}
|
||||
|
@ -134,16 +134,17 @@ public:
|
||||
const nsString& aName,
|
||||
const nsString& aFeatures,
|
||||
bool* aOutWindowOpened) MOZ_OVERRIDE;
|
||||
virtual bool AnswerCreateWindow(const uint32_t& aChromeFlags,
|
||||
const bool& aCalledFromJS,
|
||||
const bool& aPositionSpecified,
|
||||
const bool& aSizeSpecified,
|
||||
const nsString& aURI,
|
||||
const nsString& aName,
|
||||
const nsString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
bool* aWindowIsNew,
|
||||
PBrowserParent** aRetVal) MOZ_OVERRIDE;
|
||||
virtual bool RecvCreateWindow(PBrowserParent* aOpener,
|
||||
const uint32_t& aChromeFlags,
|
||||
const bool& aCalledFromJS,
|
||||
const bool& aPositionSpecified,
|
||||
const bool& aSizeSpecified,
|
||||
const nsString& aURI,
|
||||
const nsString& aName,
|
||||
const nsString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
bool* aWindowIsNew,
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts) MOZ_OVERRIDE;
|
||||
virtual bool RecvSyncMessage(const nsString& aMessage,
|
||||
const ClonedMessageData& aData,
|
||||
const InfallibleTArray<CpowEntry>& aCpows,
|
||||
@ -352,6 +353,11 @@ public:
|
||||
void SetInitedByParent() { mInitedByParent = true; }
|
||||
bool IsInitedByParent() const { return mInitedByParent; }
|
||||
|
||||
static TabParent* GetNextTabParent();
|
||||
|
||||
bool SendLoadRemoteScript(const nsString& aURL,
|
||||
const bool& aRunInGlobalScope);
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
@ -468,6 +474,35 @@ private:
|
||||
|
||||
TabId mTabId;
|
||||
|
||||
// Helper class for RecvCreateWindow.
|
||||
struct AutoUseNewTab;
|
||||
|
||||
// When loading a new tab or window via window.open, the child process sends
|
||||
// a new PBrowser to use. We store that tab in sNextTabParent and then
|
||||
// proceed through the browser's normal paths to create a new
|
||||
// window/tab. When it comes time to create a new TabParent, we instead use
|
||||
// sNextTabParent.
|
||||
static TabParent* sNextTabParent;
|
||||
|
||||
// When loading a new tab or window via window.open, the child is
|
||||
// responsible for loading the URL it wants into the new
|
||||
// TabChild. Simultaneously, though, the parent sends a LoadURL message to
|
||||
// every new PBrowser (usually for about:blank). This message usually
|
||||
// arrives after the child has started to load the URL it wants, and
|
||||
// overrides it. To prevent this, we set mSkipLoad to true when creating the
|
||||
// new tab. This flag prevents the unwanted LoadURL message from being sent
|
||||
// by the parent.
|
||||
bool mSkipLoad;
|
||||
|
||||
// When loading a new tab or window via window.open, we want to ensure that
|
||||
// frame scripts for that tab are loaded before any scripts start to run in
|
||||
// the window. We can't load the frame scripts the normal way, using
|
||||
// separate IPC messages, since they won't be processed by the child until
|
||||
// returning to the event loop, which is too late. Instead, we queue up
|
||||
// frame scripts that we intend to load and send them as part of the
|
||||
// CreateWindow response. Then TabChild loads them immediately.
|
||||
nsTArray<FrameScriptInfo> mDelayedFrameScripts;
|
||||
|
||||
private:
|
||||
// This is used when APZ needs to find the TabParent associated with a layer
|
||||
// to dispatch events.
|
||||
|
@ -1189,7 +1189,13 @@ void MediaDecoderStateMachine::SetSyncPointForMediaStream()
|
||||
}
|
||||
|
||||
mSyncPointInMediaStream = stream->GetLastOutputTime();
|
||||
mSyncPointInDecodedStream = mStartTime + mPlayDuration;
|
||||
TimeDuration timeSincePlayStart = mPlayStartTime.IsNull() ? TimeDuration(0) :
|
||||
TimeStamp::Now() - mPlayStartTime;
|
||||
mSyncPointInDecodedStream = mStartTime + mPlayDuration +
|
||||
timeSincePlayStart.ToMicroseconds();
|
||||
|
||||
DECODER_LOG("SetSyncPointForMediaStream MediaStream=%lldus, DecodedStream=%lldus",
|
||||
mSyncPointInMediaStream, mSyncPointInDecodedStream);
|
||||
}
|
||||
|
||||
void MediaDecoderStateMachine::ResyncMediaStreamClock()
|
||||
@ -1353,6 +1359,13 @@ void MediaDecoderStateMachine::SetAudioCaptured(bool aCaptured)
|
||||
// If mStopAudioThread is true then we're already stopping the audio sink
|
||||
// and since we set mAudioCaptured to true, nothing can start it again.
|
||||
ScheduleStateMachine();
|
||||
|
||||
if (HasAudio()) {
|
||||
// The audio clock is active so force a resync now in case the audio
|
||||
// clock is ahead of us (observed on Android), since after mAudioCaptured
|
||||
// gets set can't call GetAudioClock().
|
||||
ResyncAudioClock();
|
||||
}
|
||||
}
|
||||
mAudioCaptured = aCaptured;
|
||||
}
|
||||
@ -1442,6 +1455,15 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
|
||||
DECODER_LOG("SetDormant=%d", aDormant);
|
||||
|
||||
if (aDormant) {
|
||||
if (mState == DECODER_STATE_SEEKING && !mQueuedSeekTarget.IsValid()) {
|
||||
if (mSeekTarget.IsValid()) {
|
||||
mQueuedSeekTarget = mSeekTarget;
|
||||
} else if (mCurrentSeekTarget.IsValid()) {
|
||||
mQueuedSeekTarget = mCurrentSeekTarget;
|
||||
}
|
||||
}
|
||||
mSeekTarget.Reset();
|
||||
mCurrentSeekTarget.Reset();
|
||||
ScheduleStateMachine();
|
||||
SetState(DECODER_STATE_DORMANT);
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
@ -2916,16 +2938,15 @@ int64_t MediaDecoderStateMachine::GetClock() const
|
||||
int64_t clock_time = -1;
|
||||
if (!IsPlaying()) {
|
||||
clock_time = mPlayDuration + mStartTime;
|
||||
} else if (mDecoder->GetDecodedStream()) {
|
||||
clock_time = GetCurrentTimeViaMediaStreamSync();
|
||||
} else {
|
||||
if (HasAudio() && !mAudioCompleted && !mAudioCaptured) {
|
||||
if (mDecoder->GetDecodedStream()) {
|
||||
clock_time = GetCurrentTimeViaMediaStreamSync();
|
||||
} else if (HasAudio() && !mAudioCompleted && !mAudioCaptured) {
|
||||
clock_time = GetAudioClock();
|
||||
} else {
|
||||
// Audio is disabled on this system. Sync to the system clock.
|
||||
clock_time = GetVideoStreamPosition();
|
||||
}
|
||||
// FIXME: This assertion should also apply the case of decoding to a stream.
|
||||
// Ensure the clock can never go backwards.
|
||||
NS_ASSERTION(GetMediaTime() <= clock_time || mPlaybackRate <= 0,
|
||||
"Clock should go forwards if the playback rate is > 0.");
|
||||
@ -2951,6 +2972,14 @@ void MediaDecoderStateMachine::AdvanceFrame()
|
||||
return;
|
||||
}
|
||||
|
||||
DecodedStreamData* stream = mDecoder->GetDecodedStream();
|
||||
if (stream && !stream->mStreamInitialized) {
|
||||
// Output streams exist but are not initialized yet.
|
||||
// Send the data we already have to allow stream clock to progress and
|
||||
// avoid stalling playback.
|
||||
SendStreamData();
|
||||
}
|
||||
|
||||
const int64_t clock_time = GetClock();
|
||||
TimeStamp nowTime = TimeStamp::Now();
|
||||
// Skip frames up to the frame at the playback position, and figure out
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "MP4Reader.h"
|
||||
#include "MP4Stream.h"
|
||||
#include "MediaResource.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsSize.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
@ -88,32 +89,18 @@ InvokeAndRetry(ThisType* aThisVal, ReturnType(ThisType::*aMethod)(), MP4Stream*
|
||||
return result;
|
||||
}
|
||||
MP4Stream::ReadRecord failure(-1, 0);
|
||||
if (!stream->LastReadFailed(&failure) || failure == prevFailure) {
|
||||
if (NS_WARN_IF(!stream->LastReadFailed(&failure))) {
|
||||
return result;
|
||||
}
|
||||
prevFailure = failure;
|
||||
|
||||
// Our goal here is to forcibly read the data we want into the cache: since
|
||||
// the stream is pinned, the data is guaranteed to stay in the cache once
|
||||
// it's there, which means that retrying the non-blocking read from inside
|
||||
// the demuxer should succeed.
|
||||
//
|
||||
// But there's one wrinkle: if we read less than an entire cache line and
|
||||
// the data ends up in MediaCacheStream's mPartialBlockBuffer, the data can
|
||||
// be returned by a blocking read but never actually committed to the cache,
|
||||
// and abandoned by a subsequent seek (possibly by another stream accessing
|
||||
// the same underlying resource).
|
||||
//
|
||||
// The way to work around this problem is to round our "priming" read up to the
|
||||
// size of an entire cache block. Note that this may hit EOS for bytes that the
|
||||
// original demuxer read never actually requested. This is OK though because the
|
||||
// call to BlockingReadAt will still return true (just with a less-than-expected
|
||||
// number of actually read bytes, which we ignore).
|
||||
size_t bufferSize = failure.mCount + (MediaCacheStream::BLOCK_SIZE - failure.mCount % MediaCacheStream::BLOCK_SIZE);
|
||||
nsAutoArrayPtr<uint8_t> dummyBuffer(new uint8_t[bufferSize]);
|
||||
MonitorAutoUnlock unlock(*aMonitor);
|
||||
size_t ignored;
|
||||
if (NS_WARN_IF(!stream->BlockingReadAt(failure.mOffset, dummyBuffer, bufferSize, &ignored))) {
|
||||
if (NS_WARN_IF(failure == prevFailure)) {
|
||||
NS_WARNING(nsPrintfCString("Failed reading the same block twice: offset=%lld, count=%lu",
|
||||
failure.mOffset, failure.mCount).get());
|
||||
return result;
|
||||
}
|
||||
|
||||
prevFailure = failure;
|
||||
if (NS_WARN_IF(!stream->BlockingReadIntoCache(failure.mOffset, failure.mCount, aMonitor))) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ namespace mozilla {
|
||||
|
||||
MP4Stream::MP4Stream(MediaResource* aResource)
|
||||
: mResource(aResource)
|
||||
, mPinCount(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MP4Stream);
|
||||
MOZ_ASSERT(aResource);
|
||||
@ -19,25 +20,33 @@ MP4Stream::MP4Stream(MediaResource* aResource)
|
||||
MP4Stream::~MP4Stream()
|
||||
{
|
||||
MOZ_COUNT_DTOR(MP4Stream);
|
||||
MOZ_ASSERT(mPinCount == 0);
|
||||
}
|
||||
|
||||
bool
|
||||
MP4Stream::BlockingReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
|
||||
size_t* aBytesRead)
|
||||
MP4Stream::BlockingReadIntoCache(int64_t aOffset, size_t aCount, Monitor* aToUnlock)
|
||||
{
|
||||
MOZ_ASSERT(mPinCount > 0);
|
||||
CacheBlock block(aOffset, aCount);
|
||||
|
||||
uint32_t sum = 0;
|
||||
uint32_t bytesRead = 0;
|
||||
do {
|
||||
uint64_t offset = aOffset + sum;
|
||||
char* buffer = reinterpret_cast<char*>(aBuffer) + sum;
|
||||
char* buffer = reinterpret_cast<char*>(block.mBuffer.get()) + sum;
|
||||
uint32_t toRead = aCount - sum;
|
||||
MonitorAutoUnlock unlock(*aToUnlock);
|
||||
nsresult rv = mResource->ReadAt(offset, buffer, toRead, &bytesRead);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
sum += bytesRead;
|
||||
} while (sum < aCount && bytesRead > 0);
|
||||
*aBytesRead = sum;
|
||||
|
||||
MOZ_ASSERT(block.mCount >= sum);
|
||||
block.mCount = sum;
|
||||
|
||||
mCache.AppendElement(block);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -64,6 +73,14 @@ bool
|
||||
MP4Stream::CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
|
||||
size_t* aBytesRead)
|
||||
{
|
||||
// First, check our local cache.
|
||||
for (size_t i = 0; i < mCache.Length(); ++i) {
|
||||
if (mCache[i].mOffset == aOffset && mCache[i].mCount >= aCount) {
|
||||
memcpy(aBuffer, mCache[i].mBuffer, aCount);
|
||||
*aBytesRead = aCount;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = mResource->ReadFromCache(reinterpret_cast<char*>(aBuffer),
|
||||
aOffset, aCount);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "MediaResource.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@ -21,7 +22,7 @@ class MP4Stream : public mp4_demuxer::Stream {
|
||||
public:
|
||||
explicit MP4Stream(MediaResource* aResource);
|
||||
virtual ~MP4Stream();
|
||||
bool BlockingReadAt(int64_t aOffset, void* aBuffer, size_t aCount, size_t* aBytesRead);
|
||||
bool BlockingReadIntoCache(int64_t aOffset, size_t aCount, Monitor* aToUnlock);
|
||||
virtual bool ReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
|
||||
size_t* aBytesRead) MOZ_OVERRIDE;
|
||||
virtual bool CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
|
||||
@ -44,12 +45,35 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
void Pin() { mResource->Pin(); }
|
||||
void Unpin() { mResource->Unpin(); }
|
||||
void Pin()
|
||||
{
|
||||
mResource->Pin();
|
||||
++mPinCount;
|
||||
}
|
||||
|
||||
void Unpin()
|
||||
{
|
||||
mResource->Unpin();
|
||||
MOZ_ASSERT(mPinCount);
|
||||
--mPinCount;
|
||||
if (mPinCount == 0) {
|
||||
mCache.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<MediaResource> mResource;
|
||||
Maybe<ReadRecord> mFailedRead;
|
||||
uint32_t mPinCount;
|
||||
|
||||
struct CacheBlock {
|
||||
CacheBlock(int64_t aOffset, size_t aCount)
|
||||
: mOffset(aOffset), mCount(aCount), mBuffer(new uint8_t[aCount]) {}
|
||||
int64_t mOffset;
|
||||
size_t mCount;
|
||||
nsAutoArrayPtr<uint8_t> mBuffer;
|
||||
};
|
||||
nsTArray<CacheBlock> mCache;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -338,6 +338,7 @@ skip-if = (toolkit == 'android' && processor == 'x86') #x86 only bug 914439
|
||||
[test_bug919265.html]
|
||||
[test_bug957847.html]
|
||||
[test_bug1018933.html]
|
||||
[test_bug1113600.html]
|
||||
[test_can_play_type.html]
|
||||
[test_can_play_type_mpeg.html]
|
||||
skip-if = buildapp == 'b2g' || (toolkit == 'android' && processor == 'x86') # bug 1021675 #x86 only bug 914439
|
||||
|
48
dom/media/test/test_bug1113600.html
Normal file
48
dom/media/test/test_bug1113600.html
Normal file
@ -0,0 +1,48 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test that a video element captured to a stream mid-playback can be played to the end</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<script type="text/javascript" src="manifest.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var manager = new MediaTestManager;
|
||||
|
||||
function startTest(test, token) {
|
||||
var v = document.createElement('video');
|
||||
v.style = "background-color:#aca;";
|
||||
v.width = 160;
|
||||
v.height = 120;
|
||||
|
||||
manager.started(token);
|
||||
|
||||
v.src = test.name;
|
||||
|
||||
v.ontimeupdate = function() {
|
||||
if (v.currentTime < test.duration / 4) {
|
||||
// Allow some time to pass before starting the capture.
|
||||
return;
|
||||
}
|
||||
v.ontimeupdate = null;
|
||||
v.mozCaptureStreamUntilEnded();
|
||||
info(test.name + " capture started at " + v.currentTime + ". Duration=" + test.duration);
|
||||
};
|
||||
|
||||
v.onended = function() {
|
||||
ok(true, test.name + " ended");
|
||||
removeNodeAndSource(v);
|
||||
manager.finished(token);
|
||||
};
|
||||
|
||||
document.body.appendChild(v);
|
||||
v.play();
|
||||
}
|
||||
|
||||
manager.runTests(gSmallTests, startTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -377,6 +377,7 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
|
||||
parent->mShutdown = true;
|
||||
return nullptr;
|
||||
}
|
||||
parent->mIsFlashPlugin = aPluginTag->mIsFlashPlugin;
|
||||
if (!parent->mIsStartingAsync) {
|
||||
int32_t launchTimeoutSecs = Preferences::GetInt(kLaunchTimeoutPref, 0);
|
||||
if (!parent->mSubprocess->WaitUntilConnected(launchTimeoutSecs * 1000)) {
|
||||
@ -386,7 +387,6 @@ PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId,
|
||||
}
|
||||
TimeStamp launchEnd = TimeStamp::Now();
|
||||
parent->mTimeBlocked = (launchEnd - launchStart);
|
||||
parent->mIsFlashPlugin = aPluginTag->mIsFlashPlugin;
|
||||
return parent.forget();
|
||||
}
|
||||
|
||||
|
@ -418,6 +418,7 @@ Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
|
||||
}
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -434,6 +435,7 @@ Promise::ThenableResolverCommon(JSContext* aCx, uint32_t aTask,
|
||||
JS::Rooted<JSObject*> thisFunc(aCx, &args.callee());
|
||||
if (!MarkAsCalledIfNotCalledBefore(aCx, thisFunc)) {
|
||||
// A function from this pair has been called before.
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -445,6 +447,8 @@ Promise::ThenableResolverCommon(JSContext* aCx, uint32_t aTask,
|
||||
} else {
|
||||
promise->RejectInternal(aCx, args.get(0));
|
||||
}
|
||||
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
[DEFAULT]
|
||||
|
||||
[test_abortable_promise.html]
|
||||
[test_bug883683.html]
|
||||
[test_promise.html]
|
||||
[test_promise_utils.html]
|
||||
[test_resolve.html]
|
||||
[test_abortable_promise.html]
|
||||
[test_resolver_return_value.html]
|
||||
|
40
dom/promise/tests/test_resolver_return_value.html
Normal file
40
dom/promise/tests/test_resolver_return_value.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1120235
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1120235</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1120235 **/
|
||||
var res, rej;
|
||||
var p = new Promise(function(resolve, reject) { res = resolve; rej = reject; });
|
||||
ise(res(1), undefined, "Resolve function should return undefined");
|
||||
ise(rej(2), undefined, "Reject function should return undefined");
|
||||
|
||||
var thenable = {
|
||||
then: function(resolve, reject) {
|
||||
ise(resolve(3), undefined, "Thenable resolve argument should return undefined");
|
||||
ise(reject(4), undefined, "Thenable reject argument should return undefined");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
};
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
p = Promise.resolve(thenable);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1120235">Mozilla Bug 1120235</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -29,7 +29,7 @@ var expected = [
|
||||
{ name: "", message: "uncaught exception: [object Object]" },
|
||||
{ name: "", message: "foo", filename: "baz", lineNumber: 123 },
|
||||
{ name: "", message: "uncaught exception: [object Object]" },
|
||||
{ name: "InvalidStateError", message: "An attempt was made to use an object that is not, or is no longer, usable", filename: location, lineNumber: 60 },
|
||||
{ name: "InvalidStateError", message: "An attempt was made to use an object that is not, or is no longer, usable", filename: location, lineNumber: 62 },
|
||||
{ name: "ReferenceError", message: "xxx is not defined", filename: location, lineNumber: 64 },
|
||||
{ name: "ReferenceError", message: "xxx is not defined", filename: location, lineNumber: 66 }
|
||||
];
|
||||
@ -57,9 +57,9 @@ window.onmessage = function(e) {
|
||||
throw {name:3,message:4,lineNumber:123};
|
||||
} else if (e.data == 7) {
|
||||
var x = new XMLHttpRequest();
|
||||
x.responseType = "arraybuffer";
|
||||
x.open("GET", location, false);
|
||||
var a = x.send();
|
||||
x.responseType = "arraybuffer";
|
||||
} else if (e.data == 8) {
|
||||
throw new ReferenceError("xxx is not defined");
|
||||
} else if (e.data == 9) {
|
||||
|
@ -111,7 +111,7 @@ onmessage = function() {
|
||||
{ url: 'http://example.com/carrot#question%3f',
|
||||
base: undefined,
|
||||
error: false,
|
||||
hash: '#question?'
|
||||
hash: '#question%3f'
|
||||
},
|
||||
{ url: 'https://example.com:4443?',
|
||||
base: undefined,
|
||||
|
@ -7398,7 +7398,8 @@ nsHTMLEditRules::JoinNodesSmart(nsIContent& aNodeLeft, nsIContent& aNodeRight)
|
||||
{
|
||||
// Caller responsible for left and right node being the same type
|
||||
nsCOMPtr<nsINode> parent = aNodeLeft.GetParentNode();
|
||||
int32_t parOffset = parent ? parent->IndexOf(&aNodeLeft) : -1;
|
||||
NS_ENSURE_TRUE(parent, ::DOMPoint());
|
||||
int32_t parOffset = parent->IndexOf(&aNodeLeft);
|
||||
nsCOMPtr<nsINode> rightParent = aNodeRight.GetParentNode();
|
||||
|
||||
// If they don't have the same parent, first move the right node to after the
|
||||
|
@ -155,7 +155,7 @@ public:
|
||||
|
||||
ChromeTooltipListener(nsWebBrowser* inBrowser, nsIWebBrowserChrome* inChrome);
|
||||
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE;
|
||||
NS_IMETHOD MouseMove(nsIDOMEvent* aMouseEvent);
|
||||
|
||||
// Add/remove the relevant listeners, based on what interfaces
|
||||
@ -227,7 +227,7 @@ public:
|
||||
ChromeContextMenuListener(nsWebBrowser* inBrowser, nsIWebBrowserChrome* inChrome);
|
||||
|
||||
// nsIDOMContextMenuListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE;
|
||||
|
||||
// Add/remove the relevant listeners, based on what interfaces
|
||||
// the embedding chrome implements.
|
||||
|
@ -94,12 +94,12 @@ public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsFindContentIterator)
|
||||
|
||||
// nsIContentIterator
|
||||
virtual nsresult Init(nsINode* aRoot)
|
||||
virtual nsresult Init(nsINode* aRoot) MOZ_OVERRIDE
|
||||
{
|
||||
NS_NOTREACHED("internal error");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
virtual nsresult Init(nsIDOMRange* aRange)
|
||||
virtual nsresult Init(nsIDOMRange* aRange) MOZ_OVERRIDE
|
||||
{
|
||||
NS_NOTREACHED("internal error");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
@ -107,13 +107,13 @@ public:
|
||||
// Not a range because one of the endpoints may be anonymous.
|
||||
nsresult Init(nsIDOMNode* aStartNode, int32_t aStartOffset,
|
||||
nsIDOMNode* aEndNode, int32_t aEndOffset);
|
||||
virtual void First();
|
||||
virtual void Last();
|
||||
virtual void Next();
|
||||
virtual void Prev();
|
||||
virtual nsINode* GetCurrentNode();
|
||||
virtual bool IsDone();
|
||||
virtual nsresult PositionAt(nsINode* aCurNode);
|
||||
virtual void First() MOZ_OVERRIDE;
|
||||
virtual void Last() MOZ_OVERRIDE;
|
||||
virtual void Next() MOZ_OVERRIDE;
|
||||
virtual void Prev() MOZ_OVERRIDE;
|
||||
virtual nsINode* GetCurrentNode() MOZ_OVERRIDE;
|
||||
virtual bool IsDone() MOZ_OVERRIDE;
|
||||
virtual nsresult PositionAt(nsINode* aCurNode) MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual ~nsFindContentIterator()
|
||||
|
@ -25,7 +25,7 @@ class PrintProgressDialogChild MOZ_FINAL : public PPrintProgressDialogChild,
|
||||
public:
|
||||
MOZ_IMPLICIT PrintProgressDialogChild(nsIObserver* aOpenObserver);
|
||||
|
||||
virtual bool RecvDialogOpened();
|
||||
virtual bool RecvDialogOpened() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
virtual ~PrintProgressDialogChild();
|
||||
@ -37,4 +37,4 @@ private:
|
||||
} // namespace embedding
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
@ -29,26 +29,26 @@ public:
|
||||
virtual bool
|
||||
RecvStateChange(
|
||||
const long& stateFlags,
|
||||
const nsresult& status);
|
||||
const nsresult& status) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvProgressChange(
|
||||
const long& curSelfProgress,
|
||||
const long& maxSelfProgress,
|
||||
const long& curTotalProgress,
|
||||
const long& maxTotalProgress);
|
||||
const long& maxTotalProgress) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvDocTitleChange(const nsString& newTitle);
|
||||
RecvDocTitleChange(const nsString& newTitle) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvDocURLChange(const nsString& newURL);
|
||||
RecvDocURLChange(const nsString& newURL) MOZ_OVERRIDE;
|
||||
|
||||
virtual void
|
||||
ActorDestroy(ActorDestroyReason aWhy);
|
||||
ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
Recv__delete__();
|
||||
Recv__delete__() MOZ_OVERRIDE;
|
||||
|
||||
private:
|
||||
virtual ~PrintProgressDialogParent();
|
||||
|
@ -23,10 +23,10 @@ public:
|
||||
NS_DECL_NSIPRINTINGPROMPTSERVICE
|
||||
|
||||
virtual PPrintProgressDialogChild*
|
||||
AllocPPrintProgressDialogChild();
|
||||
AllocPPrintProgressDialogChild() MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor);
|
||||
DeallocPPrintProgressDialogChild(PPrintProgressDialogChild* aActor) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -221,7 +221,7 @@ public:
|
||||
nsEncoderNodeFixup();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_IMETHOD FixupNode(nsIDOMNode *aNode, bool *aSerializeCloneKids, nsIDOMNode **aOutNode);
|
||||
NS_IMETHOD FixupNode(nsIDOMNode *aNode, bool *aSerializeCloneKids, nsIDOMNode **aOutNode) MOZ_OVERRIDE;
|
||||
|
||||
nsWebBrowserPersist *mWebBrowserPersist;
|
||||
|
||||
|
@ -143,8 +143,8 @@ class nsWatcherWindowEnumerator : public nsISimpleEnumerator {
|
||||
|
||||
public:
|
||||
explicit nsWatcherWindowEnumerator(nsWindowWatcher *inWatcher);
|
||||
NS_IMETHOD HasMoreElements(bool *retval);
|
||||
NS_IMETHOD GetNext(nsISupports **retval);
|
||||
NS_IMETHOD HasMoreElements(bool *retval) MOZ_OVERRIDE;
|
||||
NS_IMETHOD GetNext(nsISupports **retval) MOZ_OVERRIDE;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
|
@ -193,7 +193,7 @@ public:
|
||||
|
||||
// nsIObserver implementation.
|
||||
NS_IMETHODIMP
|
||||
Observe(nsISupports *aSubject, const char *aTopic, const char16_t *data)
|
||||
Observe(nsISupports *aSubject, const char *aTopic, const char16_t *data) MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(!nsCRT::strcmp(aTopic, "webapps-clear-data"));
|
||||
|
||||
|
@ -29,12 +29,12 @@ class nsXPCOMDetector :
|
||||
NS_DECL_ISUPPORTS
|
||||
public:
|
||||
nsXPCOMDetector();
|
||||
NS_IMETHOD Init(nsICharsetDetectionObserver* aObserver);
|
||||
NS_IMETHOD DoIt(const char* aBuf, uint32_t aLen, bool *oDontFeedMe);
|
||||
NS_IMETHOD Done();
|
||||
NS_IMETHOD Init(nsICharsetDetectionObserver* aObserver) MOZ_OVERRIDE;
|
||||
NS_IMETHOD DoIt(const char* aBuf, uint32_t aLen, bool *oDontFeedMe) MOZ_OVERRIDE;
|
||||
NS_IMETHOD Done() MOZ_OVERRIDE;
|
||||
protected:
|
||||
virtual ~nsXPCOMDetector();
|
||||
virtual void Report(const char* aCharset);
|
||||
virtual void Report(const char* aCharset) MOZ_OVERRIDE;
|
||||
private:
|
||||
nsCOMPtr<nsICharsetDetectionObserver> mObserver;
|
||||
};
|
||||
@ -49,10 +49,10 @@ class nsXPCOMStringDetector :
|
||||
public:
|
||||
nsXPCOMStringDetector();
|
||||
NS_IMETHOD DoIt(const char* aBuf, uint32_t aLen,
|
||||
const char** oCharset, nsDetectionConfident &oConf);
|
||||
const char** oCharset, nsDetectionConfident &oConf) MOZ_OVERRIDE;
|
||||
protected:
|
||||
virtual ~nsXPCOMStringDetector();
|
||||
virtual void Report(const char* aCharset);
|
||||
virtual void Report(const char* aCharset) MOZ_OVERRIDE;
|
||||
private:
|
||||
nsCOMPtr<nsICharsetDetectionObserver> mObserver;
|
||||
const char* mResult;
|
||||
|
@ -620,7 +620,11 @@ DrawBuffer::Create(GLContext* const gl,
|
||||
gl->fGenFramebuffers(1, &fb);
|
||||
gl->AttachBuffersToFB(0, colorMSRB, depthRB, stencilRB, fb);
|
||||
|
||||
UniquePtr<DrawBuffer> ret( new DrawBuffer(gl, size, fb, colorMSRB,
|
||||
GLsizei samples = formats.samples;
|
||||
if (!samples)
|
||||
samples = 1;
|
||||
|
||||
UniquePtr<DrawBuffer> ret( new DrawBuffer(gl, size, samples, fb, colorMSRB,
|
||||
depthRB, stencilRB) );
|
||||
|
||||
GLenum err = localError.GetError();
|
||||
|
@ -46,6 +46,7 @@ protected:
|
||||
GLContext* const mGL;
|
||||
public:
|
||||
const gfx::IntSize mSize;
|
||||
const GLsizei mSamples;
|
||||
const GLuint mFB;
|
||||
protected:
|
||||
const GLuint mColorMSRB;
|
||||
@ -54,12 +55,14 @@ protected:
|
||||
|
||||
DrawBuffer(GLContext* gl,
|
||||
const gfx::IntSize& size,
|
||||
GLsizei samples,
|
||||
GLuint fb,
|
||||
GLuint colorMSRB,
|
||||
GLuint depthRB,
|
||||
GLuint stencilRB)
|
||||
: mGL(gl)
|
||||
, mSize(size)
|
||||
, mSamples(samples)
|
||||
, mFB(fb)
|
||||
, mColorMSRB(colorMSRB)
|
||||
, mDepthRB(depthRB)
|
||||
@ -198,6 +201,13 @@ public:
|
||||
return mRead->mFB;
|
||||
}
|
||||
|
||||
GLsizei Samples() const {
|
||||
if (!mDraw)
|
||||
return 1;
|
||||
|
||||
return mDraw->mSamples;
|
||||
}
|
||||
|
||||
void DeletingFB(GLuint fb);
|
||||
|
||||
const gfx::IntSize& Size() const {
|
||||
|
@ -57,12 +57,6 @@ protected:
|
||||
return static_cast<BasicLayerManager*>(mManager);
|
||||
}
|
||||
|
||||
// only paints the image if aContext is non-null
|
||||
void
|
||||
GetAndPaintCurrentImage(DrawTarget* aTarget,
|
||||
float aOpacity,
|
||||
SourceSurface* aMaskSurface);
|
||||
|
||||
gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
@ -97,46 +91,6 @@ BasicImageLayer::Paint(DrawTarget* aDT,
|
||||
GetContainer()->NotifyPaintedImage(image);
|
||||
}
|
||||
|
||||
void
|
||||
BasicImageLayer::GetAndPaintCurrentImage(DrawTarget* aTarget,
|
||||
float aOpacity,
|
||||
SourceSurface* aMaskSurface)
|
||||
{
|
||||
if (!mContainer) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<ImageFactory> originalIF = mContainer->GetImageFactory();
|
||||
mContainer->SetImageFactory(mManager->IsCompositingCheap() ?
|
||||
nullptr :
|
||||
BasicManager()->GetImageFactory());
|
||||
IntSize size;
|
||||
Image* image = nullptr;
|
||||
RefPtr<SourceSurface> surf =
|
||||
mContainer->LockCurrentAsSourceSurface(&size, &image);
|
||||
|
||||
if (!surf) {
|
||||
mContainer->SetImageFactory(originalIF);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aTarget) {
|
||||
// The visible region can extend outside the image, so just draw
|
||||
// within the image bounds.
|
||||
SurfacePattern pat(surf, ExtendMode::CLAMP, Matrix(), ToFilter(mFilter));
|
||||
CompositionOp op = GetEffectiveOperator(this);
|
||||
DrawOptions opts(aOpacity, op);
|
||||
|
||||
aTarget->MaskSurface(pat, aMaskSurface, Point(0, 0), opts);
|
||||
|
||||
GetContainer()->NotifyPaintedImage(image);
|
||||
}
|
||||
|
||||
mContainer->SetImageFactory(originalIF);
|
||||
|
||||
mContainer->UnlockCurrentImage();
|
||||
}
|
||||
|
||||
TemporaryRef<SourceSurface>
|
||||
BasicImageLayer::GetAsSourceSurface()
|
||||
{
|
||||
|
@ -421,9 +421,20 @@ ContentClientRemoteBuffer::Dump(std::stringstream& aStream,
|
||||
bool aDumpHtml)
|
||||
{
|
||||
// TODO We should combine the OnWhite/OnBlack here an just output a single image.
|
||||
aStream << "\n" << aPrefix << "Surface: ";
|
||||
CompositableClient::DumpTextureClient(aStream, mTextureClient);
|
||||
}
|
||||
|
||||
void
|
||||
ContentClientDoubleBuffered::Dump(std::stringstream& aStream,
|
||||
const char* aPrefix,
|
||||
bool aDumpHtml)
|
||||
{
|
||||
// TODO We should combine the OnWhite/OnBlack here an just output a single image.
|
||||
aStream << "\n" << aPrefix << "Surface: ";
|
||||
CompositableClient::DumpTextureClient(aStream, mFrontClient);
|
||||
}
|
||||
|
||||
void
|
||||
ContentClientDoubleBuffered::DestroyFrontBuffer()
|
||||
{
|
||||
|
@ -347,6 +347,9 @@ public:
|
||||
return TextureInfo(CompositableType::CONTENT_DOUBLE, mTextureFlags);
|
||||
}
|
||||
|
||||
virtual void Dump(std::stringstream& aStream,
|
||||
const char* aPrefix="",
|
||||
bool aDumpHtml=false) MOZ_OVERRIDE;
|
||||
protected:
|
||||
virtual void DestroyFrontBuffer() MOZ_OVERRIDE;
|
||||
|
||||
|
@ -507,6 +507,7 @@ void TextureClient::ForceRemove()
|
||||
{
|
||||
if (mValid && mActor) {
|
||||
if (GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
|
||||
MOZ_PERFORMANCE_WARNING("gfx", "TextureClient/Host pair requires synchronous deallocation");
|
||||
if (mActor->IPCOpen()) {
|
||||
mActor->SendClearTextureHostSync();
|
||||
mActor->SendRemoveTexture();
|
||||
|
@ -282,7 +282,17 @@ public:
|
||||
return gfx::SurfaceFormat::UNKNOWN;
|
||||
}
|
||||
|
||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
|
||||
/**
|
||||
* This method is strictly for debugging. It causes locking and
|
||||
* needless copies.
|
||||
*/
|
||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() {
|
||||
Lock(OpenMode::OPEN_READ);
|
||||
RefPtr<gfx::SourceSurface> surf = BorrowDrawTarget()->Snapshot();
|
||||
RefPtr<gfx::DataSourceSurface> data = surf->GetDataSurface();
|
||||
Unlock();
|
||||
return data;
|
||||
}
|
||||
|
||||
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix);
|
||||
|
||||
|
@ -52,6 +52,12 @@ TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocat
|
||||
mRetainedHeight = aDescriptor.retainedHeight();
|
||||
mResolution = aDescriptor.resolution();
|
||||
mFrameResolution = CSSToParentLayerScale(aDescriptor.frameResolution());
|
||||
if (mResolution == 0 || IsNaN(mResolution)) {
|
||||
// There are divisions by mResolution so this protects the compositor process
|
||||
// against malicious content processes and fuzzing.
|
||||
mIsValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Combine any valid content that wasn't already uploaded
|
||||
nsIntRegion oldPaintedRegion(aOldPaintedRegion);
|
||||
|
@ -30,6 +30,14 @@ public:
|
||||
void AddCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
|
||||
void RemoveCompositorVsyncDispatcher(mozilla::CompositorVsyncDispatcher* aCompositorVsyncDispatcher);
|
||||
// Notified when this display's vsync occurs, on the vsync thread
|
||||
// The aVsyncTimestamp should normalize to the Vsync time that just occured
|
||||
// However, different platforms give different vsync notification times.
|
||||
// b2g - The vsync timestamp of the previous frame that was just displayed
|
||||
// OSX - The vsync timestamp of the upcoming frame, in the future
|
||||
// TODO: Windows / Linux. DOCUMENT THIS WHEN IMPLEMENTING ON THOSE PLATFORMS
|
||||
// Android: TODO
|
||||
// All platforms should normalize to the vsync that just occured.
|
||||
// Large parts of Gecko assume TimeStamps should not be in the future such as animations
|
||||
virtual void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
|
||||
|
||||
// These should all only be called on the main thread
|
||||
|
@ -75,6 +75,7 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
|
||||
: gfxFont(aFontEntry, aFontStyle, anAAOption)
|
||||
, mCairoFontFace(nullptr)
|
||||
, mMetrics(nullptr)
|
||||
, mSpaceGlyph(0)
|
||||
, mNeedsOblique(false)
|
||||
, mNeedsBold(aNeedsBold)
|
||||
, mUseSubpixelPositions(false)
|
||||
@ -228,8 +229,15 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
mMetrics->internalLeading = std::max(mMetrics->maxHeight - mMetrics->emHeight, 0.0);
|
||||
mMetrics->externalLeading = ceil(fontMetrics.lineGap * mFUnitsConvFactor);
|
||||
|
||||
UINT16 glyph = (uint16_t)GetSpaceGlyph();
|
||||
mMetrics->spaceWidth = MeasureGlyphWidth(glyph);
|
||||
UINT32 ucs = L' ';
|
||||
UINT16 glyph;
|
||||
HRESULT hr = mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph);
|
||||
if (FAILED(hr)) {
|
||||
mMetrics->spaceWidth = 0;
|
||||
} else {
|
||||
mSpaceGlyph = glyph;
|
||||
mMetrics->spaceWidth = MeasureGlyphWidth(glyph);
|
||||
}
|
||||
|
||||
// try to get aveCharWidth from the OS/2 table, fall back to measuring 'x'
|
||||
// if the table is not available or if using hinted/pixel-snapped widths
|
||||
@ -251,7 +259,6 @@ gfxDWriteFont::ComputeMetrics(AntialiasOption anAAOption)
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 ucs;
|
||||
if (mMetrics->aveCharWidth < 1) {
|
||||
ucs = L'x';
|
||||
if (SUCCEEDED(mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph))) {
|
||||
@ -442,14 +449,7 @@ gfxDWriteFont::HasBitmapStrikeForSize(uint32_t aSize)
|
||||
uint32_t
|
||||
gfxDWriteFont::GetSpaceGlyph()
|
||||
{
|
||||
UINT32 ucs = L' ';
|
||||
UINT16 glyph;
|
||||
HRESULT hr;
|
||||
hr = mFontFace->GetGlyphIndicesA(&ucs, 1, &glyph);
|
||||
if (FAILED(hr)) {
|
||||
return 0;
|
||||
}
|
||||
return glyph;
|
||||
return mSpaceGlyph;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -98,6 +98,8 @@ protected:
|
||||
// cache of glyph widths in 16.16 fixed-point pixels
|
||||
nsAutoPtr<nsDataHashtable<nsUint32HashKey,int32_t> > mGlyphWidths;
|
||||
|
||||
uint32_t mSpaceGlyph;
|
||||
|
||||
bool mNeedsOblique;
|
||||
bool mNeedsBold;
|
||||
bool mUseSubpixelPositions;
|
||||
|
@ -116,7 +116,7 @@ gfxFT2FontBase::GetHorizontalMetrics()
|
||||
|
||||
if (MOZ_UNLIKELY(GetStyle()->size <= 0.0)) {
|
||||
new(&mMetrics) gfxFont::Metrics(); // zero initialize
|
||||
mSpaceGlyph = 0;
|
||||
mSpaceGlyph = GetGlyph(' ');
|
||||
} else {
|
||||
gfxFT2LockedFace face(this);
|
||||
face.GetMetrics(&mMetrics, &mSpaceGlyph);
|
||||
@ -144,8 +144,6 @@ gfxFT2FontBase::GetHorizontalMetrics()
|
||||
uint32_t
|
||||
gfxFT2FontBase::GetSpaceGlyph()
|
||||
{
|
||||
NS_ASSERTION(GetStyle()->size != 0,
|
||||
"forgot to short-circuit a text run with zero-sized font?");
|
||||
GetHorizontalMetrics();
|
||||
return mSpaceGlyph;
|
||||
}
|
||||
|
@ -2114,6 +2114,23 @@ NeedsGlyphExtents(gfxFont *aFont, gfxTextRun *aTextRun)
|
||||
aFont->GetFontEntry()->IsUserFont();
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFont::IsSpaceGlyphInvisible(gfxContext *aRefContext, gfxTextRun *aTextRun)
|
||||
{
|
||||
if (!mFontEntry->mSpaceGlyphIsInvisibleInitialized &&
|
||||
GetAdjustedSize() >= 1.0) {
|
||||
gfxGlyphExtents *extents =
|
||||
GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit());
|
||||
gfxRect glyphExtents;
|
||||
mFontEntry->mSpaceGlyphIsInvisible =
|
||||
extents->GetTightGlyphExtentsAppUnits(this, eHorizontal,
|
||||
aRefContext, GetSpaceGlyph(), &glyphExtents) &&
|
||||
glyphExtents.IsEmpty();
|
||||
mFontEntry->mSpaceGlyphIsInvisibleInitialized = true;
|
||||
}
|
||||
return mFontEntry->mSpaceGlyphIsInvisible;
|
||||
}
|
||||
|
||||
gfxFont::RunMetrics
|
||||
gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
uint32_t aStart, uint32_t aEnd,
|
||||
@ -2189,16 +2206,22 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
if (aSpacing) {
|
||||
x += direction*aSpacing[0].mBefore;
|
||||
}
|
||||
uint32_t spaceGlyph = GetSpaceGlyph();
|
||||
bool allGlyphsInvisible = true;
|
||||
uint32_t i;
|
||||
for (i = aStart; i < aEnd; ++i) {
|
||||
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i];
|
||||
if (glyphData->IsSimpleGlyph()) {
|
||||
double advance = glyphData->GetSimpleAdvance();
|
||||
uint32_t glyphIndex = glyphData->GetSimpleGlyph();
|
||||
if (glyphIndex != spaceGlyph ||
|
||||
!IsSpaceGlyphInvisible(aRefContext, aTextRun)) {
|
||||
allGlyphsInvisible = false;
|
||||
}
|
||||
// Only get the real glyph horizontal extent if we were asked
|
||||
// for the tight bounding box or we're in quality mode
|
||||
if ((aBoundingBoxType != LOOSE_INK_EXTENTS || needsGlyphExtents) &&
|
||||
extents) {
|
||||
uint32_t glyphIndex = glyphData->GetSimpleGlyph();
|
||||
extents){
|
||||
uint16_t extentsWidth = extents->GetContainedGlyphWidthAppUnits(glyphIndex);
|
||||
if (extentsWidth != gfxGlyphExtents::INVALID_WIDTH &&
|
||||
aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||
@ -2221,6 +2244,7 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
}
|
||||
x += direction*advance;
|
||||
} else {
|
||||
allGlyphsInvisible = false;
|
||||
uint32_t glyphCount = glyphData->GetGlyphCount();
|
||||
if (glyphCount > 0) {
|
||||
const gfxTextRun::DetailedGlyph *details =
|
||||
@ -2261,14 +2285,18 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
}
|
||||
}
|
||||
|
||||
if (aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||
UnionRange(x, &advanceMin, &advanceMax);
|
||||
gfxRect fontBox(advanceMin, -metrics.mAscent,
|
||||
advanceMax - advanceMin, metrics.mAscent + metrics.mDescent);
|
||||
metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox);
|
||||
}
|
||||
if (isRTL) {
|
||||
metrics.mBoundingBox -= gfxPoint(x, 0);
|
||||
if (allGlyphsInvisible) {
|
||||
metrics.mBoundingBox.SetEmpty();
|
||||
} else {
|
||||
if (aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||
UnionRange(x, &advanceMin, &advanceMax);
|
||||
gfxRect fontBox(advanceMin, -metrics.mAscent,
|
||||
advanceMax - advanceMin, metrics.mAscent + metrics.mDescent);
|
||||
metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox);
|
||||
}
|
||||
if (isRTL) {
|
||||
metrics.mBoundingBox -= gfxPoint(x, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// If the font may be rendered with a fake-italic effect, we need to allow
|
||||
|
@ -1846,6 +1846,8 @@ protected:
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool IsSpaceGlyphInvisible(gfxContext *aRefContext, gfxTextRun *aTextRun);
|
||||
|
||||
void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
||||
void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
||||
|
||||
|
@ -85,6 +85,8 @@ gfxFontEntry::gfxFontEntry() :
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mSkipDefaultFeatureSpaceCheck(false),
|
||||
mSpaceGlyphIsInvisible(false),
|
||||
mSpaceGlyphIsInvisibleInitialized(false),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
@ -120,6 +122,8 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mSkipDefaultFeatureSpaceCheck(false),
|
||||
mSpaceGlyphIsInvisible(false),
|
||||
mSpaceGlyphIsInvisibleInitialized(false),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
|
@ -403,6 +403,8 @@ public:
|
||||
bool mHasSpaceFeaturesKerning : 1;
|
||||
bool mHasSpaceFeaturesNonKerning : 1;
|
||||
bool mSkipDefaultFeatureSpaceCheck : 1;
|
||||
bool mSpaceGlyphIsInvisible : 1;
|
||||
bool mSpaceGlyphIsInvisibleInitialized : 1;
|
||||
bool mHasGraphiteTables : 1;
|
||||
bool mCheckedForGraphiteTables : 1;
|
||||
bool mHasCmapTable : 1;
|
||||
|
@ -418,14 +418,7 @@ static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
|
||||
const CVTimeStamp* aOutputTime,
|
||||
CVOptionFlags aFlagsIn,
|
||||
CVOptionFlags* aFlagsOut,
|
||||
void* aDisplayLinkContext)
|
||||
{
|
||||
VsyncSource::Display* display = (VsyncSource::Display*) aDisplayLinkContext;
|
||||
int64_t timestamp = aOutputTime->hostTime;
|
||||
mozilla::TimeStamp vsyncTime = mozilla::TimeStamp::FromSystemTime(timestamp);
|
||||
display->NotifyVsync(vsyncTime);
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
void* aDisplayLinkContext);
|
||||
|
||||
class OSXVsyncSource MOZ_FINAL : public VsyncSource
|
||||
{
|
||||
@ -439,7 +432,6 @@ public:
|
||||
return mGlobalDisplay;
|
||||
}
|
||||
|
||||
protected:
|
||||
class OSXDisplay MOZ_FINAL : public VsyncSource::Display
|
||||
{
|
||||
public:
|
||||
@ -471,6 +463,7 @@ protected:
|
||||
return;
|
||||
}
|
||||
|
||||
mPreviousTimestamp = TimeStamp::Now();
|
||||
if (CVDisplayLinkStart(mDisplayLink) != kCVReturnSuccess) {
|
||||
NS_WARNING("Could not activate the display link");
|
||||
mDisplayLink = nullptr;
|
||||
@ -494,6 +487,13 @@ protected:
|
||||
return mDisplayLink != nullptr;
|
||||
}
|
||||
|
||||
// The vsync timestamps given by the CVDisplayLinkCallback are
|
||||
// in the future for the NEXT frame. Large parts of Gecko, such
|
||||
// as animations assume a timestamp at either now or in the past.
|
||||
// Normalize the timestamps given to the VsyncDispatchers to the vsync
|
||||
// that just occured, not the vsync that is upcoming.
|
||||
TimeStamp mPreviousTimestamp;
|
||||
|
||||
private:
|
||||
// Manages the display link render thread
|
||||
CVDisplayLinkRef mDisplayLink;
|
||||
@ -507,6 +507,26 @@ private:
|
||||
OSXDisplay mGlobalDisplay;
|
||||
}; // OSXVsyncSource
|
||||
|
||||
static CVReturn VsyncCallback(CVDisplayLinkRef aDisplayLink,
|
||||
const CVTimeStamp* aNow,
|
||||
const CVTimeStamp* aOutputTime,
|
||||
CVOptionFlags aFlagsIn,
|
||||
CVOptionFlags* aFlagsOut,
|
||||
void* aDisplayLinkContext)
|
||||
{
|
||||
// Executed on OS X hardware vsync thread
|
||||
OSXVsyncSource::OSXDisplay* display = (OSXVsyncSource::OSXDisplay*) aDisplayLinkContext;
|
||||
int64_t nextVsyncTimestamp = aOutputTime->hostTime;
|
||||
mozilla::TimeStamp nextVsync = mozilla::TimeStamp::FromSystemTime(nextVsyncTimestamp);
|
||||
|
||||
mozilla::TimeStamp previousVsync = display->mPreviousTimestamp;
|
||||
display->mPreviousTimestamp = nextVsync;
|
||||
MOZ_ASSERT(TimeStamp::Now() > previousVsync);
|
||||
|
||||
display->NotifyVsync(previousVsync);
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::gfx::VsyncSource>
|
||||
gfxPlatformMac::CreateHardwareVsyncSource()
|
||||
{
|
||||
|
@ -38,15 +38,9 @@ if CONFIG['INTEL_ARCHITECTURE']:
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
if CONFIG['OS_TEST'] == 'x86_64':
|
||||
if CONFIG['_MSC_VER'] == '1400':
|
||||
# VC8 doesn't support some SSE2 built-in functions
|
||||
SOURCES += [
|
||||
'yuv_row_win.cpp',
|
||||
]
|
||||
else:
|
||||
SOURCES += [
|
||||
'yuv_row_win64.cpp',
|
||||
]
|
||||
SOURCES += [
|
||||
'yuv_row_win64.cpp',
|
||||
]
|
||||
else:
|
||||
SOURCES += [
|
||||
'yuv_row_win.cpp',
|
||||
|
@ -570,7 +570,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Notify(const NetworkInformation& aNetworkInfo) {
|
||||
void Notify(const NetworkInformation& aNetworkInfo) MOZ_OVERRIDE {
|
||||
unused << SendNotifyNetworkChange(aNetworkInfo);
|
||||
}
|
||||
|
||||
@ -612,7 +612,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Notify(const ScreenConfiguration& aScreenConfiguration) {
|
||||
void Notify(const ScreenConfiguration& aScreenConfiguration) MOZ_OVERRIDE {
|
||||
unused << SendNotifyScreenConfigurationChange(aScreenConfiguration);
|
||||
}
|
||||
|
||||
@ -778,7 +778,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Notify(const SensorData& aSensorData) {
|
||||
void Notify(const SensorData& aSensorData) MOZ_OVERRIDE {
|
||||
unused << SendNotifySensorChange(aSensorData);
|
||||
}
|
||||
|
||||
@ -817,7 +817,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Notify(const WakeLockInformation& aWakeLockInfo)
|
||||
void Notify(const WakeLockInformation& aWakeLockInfo) MOZ_OVERRIDE
|
||||
{
|
||||
unused << SendNotifyWakeLockChange(aWakeLockInfo);
|
||||
}
|
||||
@ -837,7 +837,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Notify(const SwitchEvent& aSwitchEvent)
|
||||
void Notify(const SwitchEvent& aSwitchEvent) MOZ_OVERRIDE
|
||||
{
|
||||
unused << SendNotifySwitchChange(aSwitchEvent);
|
||||
}
|
||||
@ -850,12 +850,12 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
void Notify(const int64_t& aClockDeltaMS)
|
||||
void Notify(const int64_t& aClockDeltaMS) MOZ_OVERRIDE
|
||||
{
|
||||
unused << SendNotifySystemClockChange(aClockDeltaMS);
|
||||
}
|
||||
|
||||
void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
|
||||
void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) MOZ_OVERRIDE
|
||||
{
|
||||
unused << SendNotifySystemTimezoneChange(aSystemTimezoneChangeInfo);
|
||||
}
|
||||
@ -938,14 +938,14 @@ public:
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RecvNotifySystemClockChange(const int64_t& aClockDeltaMS) {
|
||||
RecvNotifySystemClockChange(const int64_t& aClockDeltaMS) MOZ_OVERRIDE {
|
||||
hal::NotifySystemClockChange(aClockDeltaMS);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RecvNotifySystemTimezoneChange(
|
||||
const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) {
|
||||
const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) MOZ_OVERRIDE {
|
||||
hal::NotifySystemTimezoneChange(aSystemTimezoneChangeInfo);
|
||||
return true;
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ class NextPartObserver : public IProgressObserver
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(NextPartObserver)
|
||||
NS_INLINE_DECL_REFCOUNTING(NextPartObserver)
|
||||
NS_INLINE_DECL_REFCOUNTING(NextPartObserver, MOZ_OVERRIDE)
|
||||
|
||||
explicit NextPartObserver(MultipartImage* aOwner)
|
||||
: mOwner(aOwner)
|
||||
|
@ -68,33 +68,11 @@ static const PRUint32 H256[8] = {
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
};
|
||||
|
||||
#if (_MSC_VER >= 1300)
|
||||
#if defined(_MSC_VER)
|
||||
#include <stdlib.h>
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#define SHA_HTONL(x) _byteswap_ulong(x)
|
||||
#define BYTESWAP4(x) x = SHA_HTONL(x)
|
||||
#elif defined(_MSC_VER) && defined(NSS_X86_OR_X64)
|
||||
#ifndef FORCEINLINE
|
||||
#if (_MSC_VER >= 1200)
|
||||
#define FORCEINLINE __forceinline
|
||||
#else
|
||||
#define FORCEINLINE __inline
|
||||
#endif
|
||||
#endif
|
||||
#define FASTCALL __fastcall
|
||||
|
||||
static FORCEINLINE PRUint32 FASTCALL
|
||||
swap4b(PRUint32 dwd)
|
||||
{
|
||||
__asm {
|
||||
mov eax,dwd
|
||||
bswap eax
|
||||
}
|
||||
}
|
||||
|
||||
#define SHA_HTONL(x) swap4b(x)
|
||||
#define BYTESWAP4(x) x = SHA_HTONL(x)
|
||||
|
||||
#elif defined(__GNUC__) && defined(NSS_X86_OR_X64)
|
||||
static __inline__ PRUint32 swap4b(PRUint32 value)
|
||||
{
|
||||
|
@ -1452,8 +1452,8 @@ ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type)
|
||||
if (TypeDescr *descr = type->maybeTypeDescr())
|
||||
PushMarkStack(gcmarker, descr);
|
||||
|
||||
if (type->interpretedFunction)
|
||||
PushMarkStack(gcmarker, type->interpretedFunction);
|
||||
if (JSFunction *fun = type->maybeInterpretedFunction())
|
||||
PushMarkStack(gcmarker, fun);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1480,8 +1480,10 @@ gc::MarkChildren(JSTracer *trc, types::TypeObject *type)
|
||||
type->setTypeDescr(&descr->as<TypeDescr>());
|
||||
}
|
||||
|
||||
if (type->interpretedFunction)
|
||||
MarkObject(trc, &type->interpretedFunction, "type_function");
|
||||
if (JSObject *fun = type->maybeInterpretedFunction()) {
|
||||
MarkObjectUnbarriered(trc, &fun, "type_function");
|
||||
type->setInterpretedFunction(&fun->as<JSFunction>());
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -281,6 +281,9 @@ class BaselineFrame
|
||||
void setPrevUpToDate() {
|
||||
flags_ |= PREV_UP_TO_DATE;
|
||||
}
|
||||
void unsetPrevUpToDate() {
|
||||
flags_ &= ~PREV_UP_TO_DATE;
|
||||
}
|
||||
|
||||
bool isDebuggee() const {
|
||||
return flags_ & DEBUGGEE;
|
||||
|
@ -296,12 +296,13 @@ IonBuilder::getPolyCallTargets(types::TemporaryTypeSet *calleeTypes, bool constr
|
||||
if (!obj) {
|
||||
types::TypeObject *typeObj = calleeTypes->getTypeObject(i);
|
||||
MOZ_ASSERT(typeObj);
|
||||
if (!typeObj->interpretedFunction) {
|
||||
obj = typeObj->maybeInterpretedFunction();
|
||||
|
||||
if (!obj) {
|
||||
targets.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
obj = typeObj->interpretedFunction;
|
||||
*gotLambda = true;
|
||||
}
|
||||
|
||||
|
@ -2963,7 +2963,7 @@ class MSimdBox
|
||||
return initialHeap_;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const {
|
||||
AliasSet getAliasSet() const MOZ_OVERRIDE {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
@ -76,6 +76,9 @@ class RematerializedFrame
|
||||
void setPrevUpToDate() {
|
||||
prevUpToDate_ = true;
|
||||
}
|
||||
void unsetPrevUpToDate() {
|
||||
prevUpToDate_ = false;
|
||||
}
|
||||
|
||||
bool isDebuggee() const {
|
||||
return isDebuggee_;
|
||||
|
@ -870,7 +870,7 @@ CreateFunctionPrototype(JSContext *cx, JSProtoKey key)
|
||||
if (!protoType)
|
||||
return nullptr;
|
||||
|
||||
protoType->interpretedFunction = functionProto;
|
||||
protoType->setInterpretedFunction(functionProto);
|
||||
script->setFunction(functionProto);
|
||||
|
||||
/*
|
||||
|
@ -3344,7 +3344,7 @@ TypeObject::print()
|
||||
fprintf(stderr, " noLengthOverflow");
|
||||
if (hasAnyFlags(OBJECT_FLAG_ITERATED))
|
||||
fprintf(stderr, " iterated");
|
||||
if (interpretedFunction)
|
||||
if (maybeInterpretedFunction())
|
||||
fprintf(stderr, " ifun");
|
||||
}
|
||||
|
||||
@ -3749,7 +3749,7 @@ JSFunction::setTypeForScriptedFunction(ExclusiveContext *cx, HandleFunction fun,
|
||||
return false;
|
||||
|
||||
fun->setType(type);
|
||||
type->interpretedFunction = fun;
|
||||
type->setInterpretedFunction(fun);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -4319,7 +4319,7 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
|
||||
type->initSingleton(obj);
|
||||
|
||||
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpreted())
|
||||
type->interpretedFunction = &obj->as<JSFunction>();
|
||||
type->setInterpretedFunction(&obj->as<JSFunction>());
|
||||
|
||||
obj->type_ = type;
|
||||
|
||||
@ -4950,12 +4950,14 @@ TypeObject::fixupAfterMovingGC()
|
||||
if (IsForwarded(&typeDescr()))
|
||||
addendum_ = Forwarded(&typeDescr());
|
||||
break;
|
||||
case Addendum_InterpretedFunction:
|
||||
if (IsForwarded(maybeInterpretedFunction()))
|
||||
addendum_ = Forwarded(maybeInterpretedFunction());
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
if (interpretedFunction && IsForwarded(interpretedFunction.get()))
|
||||
interpretedFunction = Forwarded(interpretedFunction.get());
|
||||
}
|
||||
|
||||
#endif // JSGC_COMPACTING
|
||||
|
@ -513,13 +513,13 @@ enum MOZ_ENUM_TYPE(uint32_t) {
|
||||
| OBJECT_FLAG_SETS_MARKED_UNKNOWN,
|
||||
|
||||
// Mask/shift for the kind of addendum attached to this type object.
|
||||
OBJECT_FLAG_ADDENDUM_MASK = 0x04000000,
|
||||
OBJECT_FLAG_ADDENDUM_MASK = 0x0c000000,
|
||||
OBJECT_FLAG_ADDENDUM_SHIFT = 26,
|
||||
|
||||
// Mask/shift for this type object's generation. If out of sync with the
|
||||
// TypeZone's generation, this TypeObject hasn't been swept yet.
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x08000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 27,
|
||||
OBJECT_FLAG_GENERATION_MASK = 0x10000000,
|
||||
OBJECT_FLAG_GENERATION_SHIFT = 28,
|
||||
};
|
||||
typedef uint32_t TypeObjectFlags;
|
||||
|
||||
@ -1107,8 +1107,19 @@ struct TypeObject : public gc::TenuredCell
|
||||
/* Flags for this object. */
|
||||
TypeObjectFlags flags_;
|
||||
|
||||
// Kinds of addendums which can be attached to TypeObjects.
|
||||
enum AddendumKind {
|
||||
Addendum_None,
|
||||
|
||||
// When used by interpreted function, the addendum stores the
|
||||
// canonical JSFunction object.
|
||||
Addendum_InterpretedFunction,
|
||||
|
||||
// When used by the 'new' type when constructing an interpreted
|
||||
// function, the addendum stores a TypeNewScript.
|
||||
Addendum_NewScript,
|
||||
|
||||
// When used by typed objects, the addendum stores a TypeDescr.
|
||||
Addendum_TypeDescr
|
||||
};
|
||||
|
||||
@ -1172,6 +1183,18 @@ struct TypeObject : public gc::TenuredCell
|
||||
setAddendum(Addendum_TypeDescr, descr);
|
||||
}
|
||||
|
||||
JSFunction *maybeInterpretedFunction() {
|
||||
// Note: as with type descriptors, there is no need to sweep when
|
||||
// accessing the interpreted function associated with an object.
|
||||
if (addendumKind() == Addendum_InterpretedFunction)
|
||||
return reinterpret_cast<JSFunction *>(addendum_);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void setInterpretedFunction(JSFunction *fun) {
|
||||
setAddendum(Addendum_InterpretedFunction, fun);
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* Properties of this object. This may contain JSID_VOID, representing the
|
||||
@ -1217,13 +1240,6 @@ struct TypeObject : public gc::TenuredCell
|
||||
Property **propertySet;
|
||||
public:
|
||||
|
||||
/* If this is an interpreted function, the function object. */
|
||||
HeapPtrFunction interpretedFunction;
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
uint32_t padding;
|
||||
#endif
|
||||
|
||||
inline TypeObject(const Class *clasp, TaggedProto proto, TypeObjectFlags initialFlags);
|
||||
|
||||
bool hasAnyFlags(TypeObjectFlags flags) {
|
||||
|
@ -761,14 +761,14 @@ ToUpperCase(JSContext *cx, JSLinearString *str)
|
||||
return nullptr;
|
||||
|
||||
ToUpperCaseImpl(buf.get(), chars, i, length);
|
||||
newChars.construct<Latin1CharPtr>(buf);
|
||||
newChars.construct<Latin1CharPtr>(Move(buf));
|
||||
} else {
|
||||
TwoByteCharPtr buf = cx->make_pod_array<char16_t>(length + 1);
|
||||
if (!buf)
|
||||
return nullptr;
|
||||
|
||||
ToUpperCaseImpl(buf.get(), chars, i, length);
|
||||
newChars.construct<TwoByteCharPtr>(buf);
|
||||
newChars.construct<TwoByteCharPtr>(Move(buf));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2384,6 +2384,31 @@ DebugScopes::hasLiveScope(ScopeObject &scope)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DebugScopes::unsetPrevUpToDateUntil(JSContext *cx, AbstractFramePtr until)
|
||||
{
|
||||
// This is the one exception where fp->prevUpToDate() is cleared without
|
||||
// popping the frame. When a frame is rematerialized, all frames younger
|
||||
// than the rematerialized frame have their prevUpToDate set to
|
||||
// false. This is because unrematerialized Ion frames have no usable
|
||||
// AbstractFramePtr, and so are skipped by the updateLiveScopes. If in the
|
||||
// future a frame suddenly gains a usable AbstractFramePtr via
|
||||
// rematerialization, the prevUpToDate invariant will no longer hold.
|
||||
for (AllFramesIter i(cx); !i.done(); ++i) {
|
||||
if (!i.hasUsableAbstractFramePtr())
|
||||
continue;
|
||||
|
||||
AbstractFramePtr frame = i.abstractFramePtr();
|
||||
if (frame == until)
|
||||
return;
|
||||
|
||||
if (frame.scopeChain()->compartment() != cx->compartment())
|
||||
continue;
|
||||
|
||||
frame.unsetPrevUpToDate();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
DebugScopes::forwardLiveFrame(JSContext *cx, AbstractFramePtr from, AbstractFramePtr to)
|
||||
{
|
||||
|
@ -942,6 +942,7 @@ class DebugScopes
|
||||
|
||||
static bool updateLiveScopes(JSContext *cx);
|
||||
static ScopeIterVal *hasLiveScope(ScopeObject &scope);
|
||||
static void unsetPrevUpToDateUntil(JSContext *cx, AbstractFramePtr frame);
|
||||
|
||||
// When a frame bails out from Ion to Baseline, there might be missing
|
||||
// scopes keyed on, and live scopes containing, the old
|
||||
|
@ -775,6 +775,20 @@ AbstractFramePtr::setPrevUpToDate() const
|
||||
asRematerializedFrame()->setPrevUpToDate();
|
||||
}
|
||||
|
||||
inline void
|
||||
AbstractFramePtr::unsetPrevUpToDate() const
|
||||
{
|
||||
if (isInterpreterFrame()) {
|
||||
asInterpreterFrame()->unsetPrevUpToDate();
|
||||
return;
|
||||
}
|
||||
if (isBaselineFrame()) {
|
||||
asBaselineFrame()->unsetPrevUpToDate();
|
||||
return;
|
||||
}
|
||||
asRematerializedFrame()->unsetPrevUpToDate();
|
||||
}
|
||||
|
||||
inline Value &
|
||||
AbstractFramePtr::thisValue() const
|
||||
{
|
||||
|
@ -1477,8 +1477,6 @@ jit::JitActivation::clearRematerializedFrames()
|
||||
jit::RematerializedFrame *
|
||||
jit::JitActivation::getRematerializedFrame(JSContext *cx, const JitFrameIterator &iter, size_t inlineDepth)
|
||||
{
|
||||
// Only allow rematerializing from the same thread.
|
||||
MOZ_ASSERT(cx->perThreadData == cx_->perThreadData);
|
||||
MOZ_ASSERT(iter.activation() == this);
|
||||
MOZ_ASSERT(iter.isIonScripted());
|
||||
|
||||
@ -1515,6 +1513,10 @@ jit::JitActivation::getRematerializedFrame(JSContext *cx, const JitFrameIterator
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// All frames younger than the rematerialized frame need to have their
|
||||
// prevUpToDate flag cleared.
|
||||
DebugScopes::unsetPrevUpToDateUntil(cx, p->value()[inlineDepth]);
|
||||
}
|
||||
|
||||
return p->value()[inlineDepth];
|
||||
|
@ -217,6 +217,7 @@ class AbstractFramePtr
|
||||
|
||||
inline bool prevUpToDate() const;
|
||||
inline void setPrevUpToDate() const;
|
||||
inline void unsetPrevUpToDate() const;
|
||||
|
||||
inline bool isDebuggee() const;
|
||||
inline void setIsDebuggee();
|
||||
@ -833,6 +834,10 @@ class InterpreterFrame
|
||||
flags_ |= PREV_UP_TO_DATE;
|
||||
}
|
||||
|
||||
void unsetPrevUpToDate() {
|
||||
flags_ &= ~PREV_UP_TO_DATE;
|
||||
}
|
||||
|
||||
bool isDebuggee() const {
|
||||
return !!(flags_ & DEBUGGEE);
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* states and methods used while laying out a ruby segment */
|
||||
|
||||
#include "RubyReflowState.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
RubyReflowState::RubyReflowState(
|
||||
WritingMode aLineWM,
|
||||
const nsTArray<nsRubyTextContainerFrame*>& aTextContainers)
|
||||
: mCurrentContainerIndex(kBaseContainerIndex)
|
||||
{
|
||||
uint32_t rtcCount = aTextContainers.Length();
|
||||
mTextContainers.SetCapacity(rtcCount);
|
||||
for (uint32_t i = 0; i < rtcCount; i++) {
|
||||
mTextContainers.AppendElement(
|
||||
TextContainerInfo(aLineWM, aTextContainers[i]));
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* states and methods used while laying out a ruby segment */
|
||||
|
||||
#ifndef mozilla_RubyReflowState_h_
|
||||
#define mozilla_RubyReflowState_h_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "WritingModes.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#define RTC_ARRAY_SIZE 1
|
||||
|
||||
class nsRubyTextContainerFrame;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class MOZ_STACK_CLASS RubyReflowState MOZ_FINAL
|
||||
{
|
||||
public:
|
||||
explicit RubyReflowState(
|
||||
WritingMode aLineWM,
|
||||
const nsTArray<nsRubyTextContainerFrame*>& aTextContainers);
|
||||
|
||||
struct TextContainerInfo
|
||||
{
|
||||
nsRubyTextContainerFrame* mFrame;
|
||||
LogicalSize mLineSize;
|
||||
|
||||
TextContainerInfo(WritingMode aLineWM, nsRubyTextContainerFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
, mLineSize(aLineWM) { }
|
||||
};
|
||||
|
||||
void AdvanceCurrentContainerIndex() { mCurrentContainerIndex++; }
|
||||
|
||||
void SetTextContainerInfo(int32_t aIndex,
|
||||
nsRubyTextContainerFrame* aContainer,
|
||||
const LogicalSize& aLineSize)
|
||||
{
|
||||
MOZ_ASSERT(mTextContainers[aIndex].mFrame == aContainer);
|
||||
mTextContainers[aIndex].mLineSize = aLineSize;
|
||||
}
|
||||
|
||||
const TextContainerInfo&
|
||||
GetCurrentTextContainerInfo(nsRubyTextContainerFrame* aFrame) const
|
||||
{
|
||||
MOZ_ASSERT(mTextContainers[mCurrentContainerIndex].mFrame == aFrame);
|
||||
return mTextContainers[mCurrentContainerIndex];
|
||||
}
|
||||
|
||||
private:
|
||||
static MOZ_CONSTEXPR_VAR int32_t kBaseContainerIndex = -1;
|
||||
// The index of the current reflowing container. When it equals to
|
||||
// kBaseContainerIndex, we are reflowing ruby base. Otherwise, it
|
||||
// stands for the index of text containers in the ruby segment.
|
||||
int32_t mCurrentContainerIndex;
|
||||
|
||||
nsAutoTArray<TextContainerInfo, RTC_ARRAY_SIZE> mTextContainers;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // mozilla_RubyReflowState_h_
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user