mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1240749 - Fixes for DPI support in Gtk widget interface: remove incorrect Get[Avail]RectDisplayPix overrides, as desktop pixels == device pixels for the Gtk widget backend, and implement nsScreenGtk::GetDefaultCSSScaleFactor, required by nsGlobalWindow since per-monitor DPI patches in bug 890156. r=karlt (9975cac985)
- Bug 1033488 - Part 2. Make PuppetBidiKeyboard correctly on content process. r=masayuki (3a91ce60a8)
- Bug 1257067 - modified XF86XK_ keysyms to GDK_ ones r=masayuki (4b922f9365)
- Bug 1251984 - allow gfx.xrender.enabled pref to work for compositing even if content backend is not Cairo. r=jrmuizel (257a163074)
- Bug 1235941 - Detect DPI change for GTK3. r=karlt (f8ca209d4b)
- Bug 1256728: Add environment variable to disable force present from bug 1232042. r=BenWa (c3b12a085b)
- Bug 1257124: Add null check for IDWriteFactory in gfxDWriteFontFileLoader::CreateCustomFontFile. r=bas (d33af4b9e1)
- Bug 1266209 - log failure reason when PathBuilderD2D::Finish fails. r=bas.schouten (360d7c2ada)
- Bug 1256552 - Disable C4577 to unblock compilation on VS2015; r=jrmuizel (7375fbf42a)
- Bug 1265960 - Remove gfxReusable* r=Bas (ed0b3aca14)
- Bug 1246290 - Refactoring to get rid of SampleContentTransformForFrame from AsyncPanZoomController. r=botond (3be6b4c1f9)
- Bug 1246290 - Add the ability for APZCs to not expose async transforms. r=botond (48942ceddf)
- Bug 1259296 - Scroll snap in the compositor in response to wheel events. r=kats (5fc694c804)
- Bug 1249040 - Allow wheel scrolls to accumulate in the presence of scroll snapping. r=kats (7514e3f6d6)
- Bug 1237343 - Replace uses of mozilla::Vector with nsTArray. r=botond (b721de19cd)
- Bug 1236046 - Don't use a stupidly small time delta to compute a velocity. r=botond (6c8f298ab6)
- Bug 1257959 - Dynamic toolbar transition seems to slow down flings r=kats (47ec4d0d54)
- Bug 1265513 - Do a fuzzy match when checking to see if a scroll will result in overscroll. r=botond (03ee304916)
- Bug 1254252 - Have Axis::ClampOriginToScrollableRect just return the original value if it falls with in the page bounds. r=kats (f88c0b4d7d)
- Bug 1261373 - Record how long it takes for content response notifications to be delivered to APZ. r=botond f=bsmedberg (b4b24d7602)
- Bug 1265515 - Update nsAutoPtr.h includes in gfx/layers/apz to RefPtr.h. r=kats (48bbc2cda8)
- Bug 1259296 - Make sure APZ smooth scroll animations end at their exact destination scroll offset. r=kats (36cace259b)
- Bug 1251837, part 1 - Use pushPrefEnv in setDeltaMultiplierSettings in window_wheel_default_action.html. r=masayuki (d673d55f02)
- Bug 1251837, part 2 - Use pushPrefEnv in doTestActionOverride in window_wheel_default_action.html. r=masayuki (f0375a3820)
- Bug 1251837, part 3 - Use pushPrefEnv in doTestWholeScroll in window_wheel_default_action.html. r=masayuki (0a7af4e103)
- Bug 1251837, part 4 - Use pushPrefEnv in doTestActionOverride in window_wheel_default_action.html. r=masayuki (51bd9cd1e2)
- Bug 1251837, part 5 - Make prepare() in doTestScroll take a callback, and use pushPrefEnv. r=masayuki (856056a947)
- Bug 1251837, part 6 - Make cleanup() in doTestScroll take a callback, and use pushPrefEnv. r=masayuki (34aa62b7f3)
- Bug 1255173 - Fix onZoomReset() in test_wheel_default_action.html to work with e10s. r=masayuki, r=jmaher (0c248c7587)
- Bug 1255178 - Part 1: Remove a leftover use of clearUserPref. r=masayuki Also, remove some trailing whitespace. (c067affdba)
- Bug 1255178 - Part 2: Remove extraneous argument to sendWheelAndWait. r=masayuki (80ce47c89b)
- Bug 1255634 - APZ should scroll by more than a page with large values of mousewheel.default.delta_multiplier_{x,y}. r=masayuki,kats (d72f77daed)
- Bug 1251638 - Don't clamp the displayport to the scrollable rect on the compositor side. r=botond (5dae2ba82e)
- Bug 1251638 - Do a bit of cleanup on the displayport margin computation in APZC; no functional changes. r=botond (575453b538)
- Bug 1266154 - Don't start a scroll snap animation if we're already at the destination. r=kats (2926d33a07)
- Bug 1258851 - Update HitTestingTreeNode::IsScrollbarNode to include the scrollbar track layers. r=rbarker (1e68081a6a)
- Bug 1265806 - Update scrollbar finding code to deal with layer trees on both OS X and Windows properly. r=rbarker (e8df49352e)
- Bug 1255224 - Add pref to force glFinish in DXGL path. (default:false) - r=dvander (8d399f8a49)
- Bug 1224199 - Destroy SharedSurfaces before ~GLContext(). - r=jrmuizel (5ad8d11f8e)
- Bug 1232480. Use 'precision' instead of 'prevision' (c7310988fa)
- Bug 1232668. Allow using kTex2DBlit_FragShaderSource on non-ES targets. (1951af5c1c)
- Bug 1235299 - Fix WebGL assertions for copyTexImage2D. r=jgilbert (226b7c14a8)
- Bug 1249189 - Use GL_RED to replace GL_ALPHA in YCbCr convert. r=jgilbert (e1d8ae2513)
- Bug 1256552 - fix int-to-float conversions in RadialGradientEffectD2D1. r=jrmuizel (36bb7f7f0f)
- Bug 1249279 - Let subdocuments' presContexts inherit the DPI setting of their parent, instead of retrieving it from their widget, to avoid using stale values from a currently-hidden widget on a screen with a different DPI. r=bz (4b8f6e0960)
- Bug 1237479 -- nsScriptSecurityManager needs to use the correct user context id in the origin attributes in a few places. r=sicking (90504a4130)
- Bug 1105556 - Call Create(originAttributes) when loadinfo->loadingPrincipal is null, instead of CreatePrincipalWithInheritedAttributes(). r=sicking (fdb341ca53)
- Bug 1253788 - Don't reload inline chrome:// style sheets in nsXBLPrototypeResources. r=bzbarsky (862464ea6c)
- Bug 1261123 - don't needlessly construct nsAutoCString temporaries in nsDefaultURIFixup; r=smaug (08f13674a8)
- Bug 1253673, r=bz (03caab3cce)
- Bug 1259511 - Overwrite loadInfo within AboutProtocolHandler and log warning to console. r=sicking (e2fc868326)
- Bug 905460 - Convert http legacy refs to smart pointers r=dragana a=kwierso (d4bdd102fa)
- Bug 1248564 - "Default authentication credentials (NTLM, Kerb) used in private mode". r=mayhemer (37c5674a0d)
- Bug 345580 - Problem decoding quoted-printable question mark in subject r=biesi (00f66a34a7)
- Bug 906986 - Rework fix for Bug 1241690 to avoid reliance on NrIceCtx inside NrIceMediaStream. r=bwc, r=drno (3d6aabeab6)
- Bug 906986 - Disable TestSrflxCandPairingFilter until bug 1226838 is fixed. r=bwc, r=drno (687281bf8b)
- Bug 906986 - Use the streams from the ice_ctx, don't hold a separate set. r=bwc, r=drno (269cd38ed2)
- Bug 906986 - Genericize some of the test setup and improve logging. r=bwc, r=drno (ad735f2459)
- Bug 906986 - Wrap NrIceCtx in NrIceCtxHandler which will allow us to handle ice restart. r=bwc, r=drno (4f2c1e5866)
- Bug 911216 - Part 12: Windows build bustage fix on a CLOSED TREE. r=efaust (f81e40df57)
- Bug 1261329 - Fix OOM handling in shell dissrc function r=efaust (d61eb121de)
- Bug 1263868 - Properly recover from OOM in ShellAutoEntryMonitor. r=jonco (3830ce7aae)
- Bug 1257722 - Prevent stdout/stderr from getting closed, r=jorendorff (48629efc06)
- Bug 1258847 - Set PTHREAD_MUTEX_ERRORCHECK for js::Mutex in debug builds. r=sfink (48cb353190)
- Bug 1252464 - Remove FrameRange cray cray in favor of using GCVectors. (r=jimb) (60ad943599)
- Bug 1257194: Tracelogger - Check for oom in drainTracelogger, r=bbouvier (7d8299958f)
- Bug 1264961 - Fix OOM case in Debugger::replaceFrameGuts. (r=jimb) (203816a8b3)
- Bug 1257588 - Don't ignore self-hosted frames when getting a saved frame's async cause. r=fitzgen (15b467a950)
- Bug 1258535 - Part 0: Add more and stronger asserts that SavedStacks-related JSAPI methods are called correctly; r=jandem (187251c401)
- Bug 1258535 - Check for the existence of a global before checking if its standard classes are resolved; r=jandem (18f7bbcc69)
- Bug 1264975 - Fix assertion in DebugScope wrapping non-syntactic scopes. (r=jimb) (753e315ddb)
- Bug 1259403 - Tracelogger: Always make sure there are 3 free slots for events, r=bbouvier (67a13b7a14)
- Bug 1231926 - add assertions on BYTEOFFSET_SLOT. r=waldo (3508ea1943)
- Bug 1260725 - Handle and report OOM in census breakdown parsing; r=jorendorff a=kwierso (de669940d1)
- Bug 1263074 - Change the JavaScript syntax error message for the old octal literal notation to suggest the new notation. r=Waldo (4e2457b27a)
- Bug 1257096, don't try to report about unusual unhandled rejected Promises, r=bz,waldo (682e4720d9)
- Bug 1262402: Use the new int64 testing features; r=luke (d213bb4f2c)
- Bug 1263882: Set a default value in DescribeScriptedCaller if the filename is null; r=luke (f66ec211f5)
This commit is contained in:
@@ -35,6 +35,13 @@ struct RedirEntry {
|
||||
URI_SAFE_FOR_UNTRUSTED_CONTENT.
|
||||
*/
|
||||
static RedirEntry kRedirMap[] = {
|
||||
#ifdef MOZ_SAFE_BROWSING
|
||||
{ "blocked", "chrome://browser/content/blockedSite.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::URI_CAN_LOAD_IN_CHILD |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
|
||||
#endif
|
||||
{ "certerror", "chrome://browser/content/certerror/aboutCertError.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
@@ -75,6 +82,7 @@ static RedirEntry kRedirMap[] = {
|
||||
{ "sync-tabs", "chrome://browser/content/sync/aboutSyncTabs.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
#endif
|
||||
// Linkable because of indexeddb use (bug 1228118)
|
||||
{ "home", "chrome://browser/content/abouthome/aboutHome.xhtml",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::MAKE_LINKABLE |
|
||||
@@ -85,6 +93,29 @@ static RedirEntry kRedirMap[] = {
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
{ "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml",
|
||||
nsIAboutModule::ALLOW_SCRIPT },
|
||||
// Linkable because of indexeddb use (bug 1228118)
|
||||
{ "loopconversation", "chrome://loop/content/panels/conversation.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
|
||||
nsIAboutModule::MAKE_LINKABLE |
|
||||
nsIAboutModule::ENABLE_INDEXED_DB },
|
||||
// Linkable because of indexeddb use (bug 1228118)
|
||||
{ "looppanel", "chrome://loop/content/panels/panel.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
|
||||
nsIAboutModule::MAKE_LINKABLE |
|
||||
nsIAboutModule::ENABLE_INDEXED_DB,
|
||||
// Shares an IndexedDB origin with about:loopconversation.
|
||||
"loopconversation" },
|
||||
{ "reader", "chrome://global/content/reader/aboutReader.html",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::ALLOW_SCRIPT |
|
||||
nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT },
|
||||
};
|
||||
static const int kRedirTotal = ArrayLength(kRedirMap);
|
||||
|
||||
|
||||
@@ -302,7 +302,12 @@ nsScriptSecurityManager::AppStatusForPrincipal(nsIPrincipal *aPrin)
|
||||
// The app could contain a cross-origin iframe - make sure that the content
|
||||
// is actually same-origin with the app.
|
||||
MOZ_ASSERT(inIsolatedMozBrowser == false, "Checked this above");
|
||||
OriginAttributes attrs(appId, false);
|
||||
nsAutoCString suffix;
|
||||
OriginAttributes attrs;
|
||||
NS_ENSURE_TRUE(attrs.PopulateFromOrigin(NS_ConvertUTF16toUTF8(appOrigin), suffix),
|
||||
nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
attrs.mAppId = appId;
|
||||
attrs.mInBrowser = false;
|
||||
nsCOMPtr<nsIPrincipal> appPrin = BasePrincipal::CreateCodebasePrincipal(appURI, attrs);
|
||||
NS_ENSURE_TRUE(appPrin, nsIPrincipal::APP_STATUS_NOT_INSTALLED);
|
||||
return aPrin->Equals(appPrin) ? status
|
||||
@@ -337,9 +342,17 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
|
||||
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
if (loadInfo) {
|
||||
if (loadInfo->GetLoadingSandboxed()) {
|
||||
RefPtr<nsNullPrincipal> prin =
|
||||
nsNullPrincipal::CreateWithInheritedAttributes(loadInfo->LoadingPrincipal());
|
||||
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
|
||||
RefPtr<nsNullPrincipal> prin;
|
||||
if (loadInfo->LoadingPrincipal()) {
|
||||
prin =
|
||||
nsNullPrincipal::CreateWithInheritedAttributes(loadInfo->LoadingPrincipal());
|
||||
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
|
||||
} else {
|
||||
OriginAttributes oAttrs;
|
||||
loadInfo->GetOriginAttributes(&oAttrs);
|
||||
prin = nsNullPrincipal::Create(oAttrs);
|
||||
NS_ENSURE_TRUE(prin, NS_ERROR_FAILURE);
|
||||
}
|
||||
prin.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -457,11 +457,13 @@ nsresult nsChromeRegistry::RefreshWindow(nsIDOMWindow* aWindow)
|
||||
}
|
||||
|
||||
// Iterate over our old sheets and kick off a sync load of the new
|
||||
// sheet if and only if it's a chrome URL.
|
||||
// sheet if and only if it's a non-inline sheet with a chrome URL.
|
||||
for (StyleSheetHandle sheet : oldSheets) {
|
||||
nsIURI* uri = sheet ? sheet->GetOriginalURI() : nullptr;
|
||||
MOZ_ASSERT(sheet, "GetStyleSheetAt shouldn't return nullptr for "
|
||||
"in-range sheet indexes");
|
||||
nsIURI* uri = sheet->GetSheetURI();
|
||||
|
||||
if (uri && IsChromeURI(uri)) {
|
||||
if (!sheet->IsInline() && IsChromeURI(uri)) {
|
||||
// Reload the sheet.
|
||||
StyleSheetHandle::RefPtr newSheet;
|
||||
// XXX what about chrome sheets that have a title or are disabled? This
|
||||
|
||||
@@ -48,6 +48,7 @@ static RedirEntry kRedirMap[] = {
|
||||
{
|
||||
"logo", "chrome://branding/content/about.png",
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
// Linkable for testing reasons.
|
||||
nsIAboutModule::MAKE_LINKABLE
|
||||
},
|
||||
{
|
||||
@@ -117,7 +118,8 @@ static RedirEntry kRedirMap[] = {
|
||||
nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
|
||||
nsIAboutModule::HIDE_FROM_ABOUTABOUT |
|
||||
// Needs to be linkable so content can touch its own srcdoc frames
|
||||
nsIAboutModule::MAKE_LINKABLE
|
||||
nsIAboutModule::MAKE_LINKABLE |
|
||||
nsIAboutModule::URI_CAN_LOAD_IN_CHILD
|
||||
}
|
||||
};
|
||||
static const int kRedirTotal = mozilla::ArrayLength(kRedirMap);
|
||||
|
||||
@@ -1119,7 +1119,7 @@ nsDefaultURIFixup::KeywordURIFixup(const nsACString& aURIString,
|
||||
}
|
||||
|
||||
bool
|
||||
nsDefaultURIFixup::IsDomainWhitelisted(const nsAutoCString aAsciiHost,
|
||||
nsDefaultURIFixup::IsDomainWhitelisted(const nsACString& aAsciiHost,
|
||||
const uint32_t aDotLoc)
|
||||
{
|
||||
if (sDNSFirstForSingleWords) {
|
||||
@@ -1146,7 +1146,7 @@ nsDefaultURIFixup::IsDomainWhitelisted(const nsACString& aDomain,
|
||||
const uint32_t aDotLoc,
|
||||
bool* aResult)
|
||||
{
|
||||
*aResult = IsDomainWhitelisted(nsAutoCString(aDomain), aDotLoc);
|
||||
*aResult = IsDomainWhitelisted(aDomain, aDotLoc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ private:
|
||||
bool PossiblyHostPortUrl(const nsACString& aUrl);
|
||||
bool MakeAlternateURI(nsIURI* aURI);
|
||||
bool IsLikelyFTP(const nsCString& aHostSpec);
|
||||
bool IsDomainWhitelisted(const nsAutoCString aAsciiHost,
|
||||
bool IsDomainWhitelisted(const nsACString& aAsciiHost,
|
||||
const uint32_t aDotLoc);
|
||||
};
|
||||
|
||||
|
||||
@@ -12064,9 +12064,18 @@ nsDocShell::AddToSessionHistory(nsIURI* aURI, nsIChannel* aChannel,
|
||||
if (loadInfo) {
|
||||
// For now keep storing just the principal in the SHEntry.
|
||||
if (loadInfo->GetLoadingSandboxed()) {
|
||||
owner = nsNullPrincipal::CreateWithInheritedAttributes(
|
||||
loadInfo->LoadingPrincipal());
|
||||
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
|
||||
if (loadInfo->LoadingPrincipal()) {
|
||||
owner = nsNullPrincipal::CreateWithInheritedAttributes(
|
||||
loadInfo->LoadingPrincipal());
|
||||
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
|
||||
} else {
|
||||
// get the OriginAttributes
|
||||
OriginAttributes oAttrs;
|
||||
loadInfo->GetOriginAttributes(&oAttrs);
|
||||
|
||||
owner = nsNullPrincipal::Create(oAttrs);
|
||||
NS_ENSURE_TRUE(owner, NS_ERROR_FAILURE);
|
||||
}
|
||||
} else if (loadInfo->GetForceInheritPrincipal()) {
|
||||
owner = loadInfo->TriggeringPrincipal();
|
||||
}
|
||||
|
||||
@@ -75,6 +75,18 @@ public:
|
||||
|
||||
void GetName(nsString& retval);
|
||||
|
||||
virtual void GetErrorMessage(nsAString& aRetVal)
|
||||
{
|
||||
// Since GetName and GetMessageMoz are non-virtual and they deal with
|
||||
// different member variables in Exception vs. DOMException, have a
|
||||
// virtual method to ensure the right error message creation.
|
||||
nsAutoString name;
|
||||
nsAutoString message;
|
||||
GetName(name);
|
||||
GetMessageMoz(message);
|
||||
CreateErrorMessage(name, message, aRetVal);
|
||||
}
|
||||
|
||||
// The XPCOM GetFilename does the right thing. It might throw, but we want to
|
||||
// return an empty filename in that case anyway, instead of throwing.
|
||||
|
||||
@@ -102,6 +114,23 @@ public:
|
||||
protected:
|
||||
virtual ~Exception();
|
||||
|
||||
void CreateErrorMessage(const nsAString& aName, const nsAString& aMessage,
|
||||
nsAString& aRetVal)
|
||||
{
|
||||
// Create similar error message as what ErrorReport::init does in jsexn.cpp.
|
||||
if (!aName.IsEmpty() && !aMessage.IsEmpty()) {
|
||||
aRetVal.Assign(aName);
|
||||
aRetVal.AppendLiteral(": ");
|
||||
aRetVal.Append(aMessage);
|
||||
} else if (!aName.IsEmpty()) {
|
||||
aRetVal.Assign(aName);
|
||||
} else if (!aMessage.IsEmpty()) {
|
||||
aRetVal.Assign(aMessage);
|
||||
} else {
|
||||
aRetVal.Truncate();
|
||||
}
|
||||
}
|
||||
|
||||
nsCString mMessage;
|
||||
nsresult mResult;
|
||||
nsCString mName;
|
||||
@@ -151,6 +180,16 @@ public:
|
||||
void GetMessageMoz(nsString& retval);
|
||||
void GetName(nsString& retval);
|
||||
|
||||
virtual void GetErrorMessage(nsAString& aRetVal) override
|
||||
{
|
||||
// See the comment in Exception::GetErrorMessage.
|
||||
nsAutoString name;
|
||||
nsAutoString message;
|
||||
GetName(name);
|
||||
GetMessageMoz(message);
|
||||
CreateErrorMessage(name, message, aRetVal);
|
||||
}
|
||||
|
||||
static already_AddRefed<DOMException>
|
||||
Create(nsresult aRv);
|
||||
|
||||
|
||||
@@ -572,7 +572,8 @@ AutoJSAPI::ReportException()
|
||||
JSAutoCompartment ac(cx(), errorGlobal);
|
||||
JS::Rooted<JS::Value> exn(cx());
|
||||
js::ErrorReport jsReport(cx());
|
||||
if (StealException(&exn) && jsReport.init(cx(), exn)) {
|
||||
if (StealException(&exn) &&
|
||||
jsReport.init(cx(), exn, js::ErrorReport::WithSideEffects)) {
|
||||
if (mIsMainThread) {
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
|
||||
|
||||
@@ -219,7 +219,7 @@ nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
|
||||
nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ?
|
||||
thisContent->OwnerDoc() : thisContent->GetUncomposedDoc();
|
||||
if (doc && doc->CSSLoader()->GetEnabled() &&
|
||||
mStyleSheet && mStyleSheet->GetOriginalURI()) {
|
||||
mStyleSheet && !mStyleSheet->IsInline()) {
|
||||
doc->CSSLoader()->ObsoleteSheet(mStyleSheet->GetOriginalURI());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,6 +294,15 @@ public:
|
||||
static nsWeakPtr sPointerLockedElement;
|
||||
static nsWeakPtr sPointerLockedDoc;
|
||||
|
||||
/**
|
||||
* If the absolute values of mMultiplierX and/or mMultiplierY are equal or
|
||||
* larger than this value, the computed scroll amount isn't rounded down to
|
||||
* the page width or height.
|
||||
*/
|
||||
enum {
|
||||
MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000
|
||||
};
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Prefs class capsules preference management.
|
||||
@@ -567,15 +576,6 @@ protected:
|
||||
|
||||
void Reset();
|
||||
|
||||
/**
|
||||
* If the abosolute values of mMultiplierX and/or mMultiplierY are equals or
|
||||
* larger than this value, the computed scroll amount isn't rounded down to
|
||||
* the page width or height.
|
||||
*/
|
||||
enum {
|
||||
MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL = 1000
|
||||
};
|
||||
|
||||
bool mInit[COUNT_OF_MULTIPLIERS];
|
||||
double mMultiplierX[COUNT_OF_MULTIPLIERS];
|
||||
double mMultiplierY[COUNT_OF_MULTIPLIERS];
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</div>
|
||||
<div id="spacerForBody"></div>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
@@ -85,34 +85,39 @@ function hitEventLoop(aFunc, aTimes)
|
||||
}
|
||||
}
|
||||
|
||||
const zoomResetTopic = "browser-fullZoom:zoomReset";
|
||||
SpecialPowers.registerObservers(zoomResetTopic);
|
||||
|
||||
function onZoomReset(aCallback) {
|
||||
var topic = "browser-fullZoom:zoomReset";
|
||||
var specialPowersTopic = "specialpowers-" + zoomResetTopic;
|
||||
SpecialPowers.addObserver(function observe() {
|
||||
SpecialPowers.removeObserver(observe, topic);
|
||||
SpecialPowers.removeObserver(observe, specialPowersTopic);
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
}, topic, false);
|
||||
}, specialPowersTopic, false);
|
||||
}
|
||||
|
||||
function setDeltaMultiplierSettings(aSettings)
|
||||
function setDeltaMultiplierSettings(aSettings, aCallback)
|
||||
{
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_x", aSettings.deltaMultiplierX * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_y", aSettings.deltaMultiplierY * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_z", aSettings.deltaMultiplierZ * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_x", aSettings.deltaMultiplierX * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_y", aSettings.deltaMultiplierY * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_alt.delta_multiplier_z", aSettings.deltaMultiplierZ * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_x", aSettings.deltaMultiplierX * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_y", aSettings.deltaMultiplierY * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.delta_multiplier_z", aSettings.deltaMultiplierZ * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_x", aSettings.deltaMultiplierX * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_y", aSettings.deltaMultiplierY * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_meta.delta_multiplier_z", aSettings.deltaMultiplierZ * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_x", aSettings.deltaMultiplierX * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_y", aSettings.deltaMultiplierY * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.delta_multiplier_z", aSettings.deltaMultiplierZ * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_x", aSettings.deltaMultiplierX * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_y", aSettings.deltaMultiplierY * 100);
|
||||
SpecialPowers.setIntPref("mousewheel.with_win.delta_multiplier_z", aSettings.deltaMultiplierZ * 100);
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["mousewheel.default.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
|
||||
["mousewheel.default.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
|
||||
["mousewheel.default.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
|
||||
["mousewheel.with_alt.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
|
||||
["mousewheel.with_alt.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
|
||||
["mousewheel.with_alt.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
|
||||
["mousewheel.with_control.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
|
||||
["mousewheel.with_control.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
|
||||
["mousewheel.with_control.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
|
||||
["mousewheel.with_meta.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
|
||||
["mousewheel.with_meta.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
|
||||
["mousewheel.with_meta.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
|
||||
["mousewheel.with_shift.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
|
||||
["mousewheel.with_shift.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
|
||||
["mousewheel.with_shift.delta_multiplier_z", aSettings.deltaMultiplierZ * 100],
|
||||
["mousewheel.with_win.delta_multiplier_x", aSettings.deltaMultiplierX * 100],
|
||||
["mousewheel.with_win.delta_multiplier_y", aSettings.deltaMultiplierY * 100],
|
||||
["mousewheel.with_win.delta_multiplier_z", aSettings.deltaMultiplierZ * 100]
|
||||
]}, aCallback);
|
||||
}
|
||||
|
||||
function doTestScroll(aSettings, aCallback)
|
||||
@@ -502,8 +507,8 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
|
||||
shiftKey: false, ctrlKey: true, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kNoScroll,
|
||||
prepare: function () { SpecialPowers.setIntPref("mousewheel.default.action", 0); },
|
||||
cleanup: function () { SpecialPowers.setIntPref("mousewheel.default.action", 1); } },
|
||||
prepare: function (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 0]]}, cb); },
|
||||
cleanup: function (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 1]]}, cb); } },
|
||||
|
||||
// momentum scroll should cause scroll even if the action is history, but if the default action is none,
|
||||
// shouldn't do it.
|
||||
@@ -605,8 +610,8 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
|
||||
shiftKey: true, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kNoScroll,
|
||||
prepare: function () { SpecialPowers.setIntPref("mousewheel.default.action", 0); },
|
||||
cleanup: function () { SpecialPowers.setIntPref("mousewheel.default.action", 1); } },
|
||||
prepare: function (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 0]]}, cb); },
|
||||
cleanup: function (cb) { SpecialPowers.pushPrefEnv({"set": [["mousewheel.default.action", 1]]}, cb); } },
|
||||
|
||||
// Don't scroll along axis whose overflow style is hidden.
|
||||
{ description: "Scroll to only bottom by oblique pixel wheel event with overflow-x: hidden",
|
||||
@@ -616,7 +621,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 0,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollDown,
|
||||
prepare: function() { gScrollableElement.style.overflowX = "hidden"; } },
|
||||
prepare: function(cb) { gScrollableElement.style.overflowX = "hidden"; cb(); } },
|
||||
{ description: "Scroll to only bottom by oblique line wheel event with overflow-x: hidden",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
|
||||
@@ -652,7 +657,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: -1, expectedOverflowDeltaY: 0,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollUp,
|
||||
cleanup: function () { gScrollableElement.style.overflowX = "auto"; } },
|
||||
cleanup: function (cb) { gScrollableElement.style.overflowX = "auto"; cb(); } },
|
||||
{ description: "Scroll to only right by oblique pixel wheel event with overflow-y: hidden",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
|
||||
@@ -660,7 +665,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 1,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollRight,
|
||||
prepare: function() { gScrollableElement.style.overflowY = "hidden"; } },
|
||||
prepare: function(cb) { gScrollableElement.style.overflowY = "hidden"; cb(); } },
|
||||
{ description: "Scroll to only right by oblique line wheel event with overflow-y: hidden",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
|
||||
@@ -696,7 +701,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: -1,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollLeft,
|
||||
cleanup: function () { gScrollableElement.style.overflowY = "auto"; } },
|
||||
cleanup: function (cb) { gScrollableElement.style.overflowY = "auto"; cb(); } },
|
||||
{ description: "Don't be scrolled by oblique pixel wheel event with overflow: hidden",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
|
||||
@@ -704,7 +709,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 1, expectedOverflowDeltaY: 1,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kNoScroll,
|
||||
prepare: function() { gScrollableElement.style.overflow = "hidden"; } },
|
||||
prepare: function(cb) { gScrollableElement.style.overflow = "hidden"; cb(); } },
|
||||
{ description: "Don't be scrolled by oblique line wheel event with overflow: hidden",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
|
||||
@@ -740,7 +745,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: -1, expectedOverflowDeltaY: -1,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kNoScroll,
|
||||
cleanup: function () { gScrollableElement.style.overflow = "auto"; } },
|
||||
cleanup: function (cb) { gScrollableElement.style.overflow = "auto"; cb(); } },
|
||||
|
||||
// Don't scroll along axis whose overflow style is hidden and overflow delta values should
|
||||
// be zero if there is ancestor scrollable element.
|
||||
@@ -751,7 +756,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollDown,
|
||||
prepare: function() {
|
||||
prepare: function(cb) {
|
||||
gScrollableElement.style.overflowX = "hidden";
|
||||
gScrollableElement.style.position = "fixed";
|
||||
gScrollableElement.style.top = "30px";
|
||||
@@ -761,6 +766,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
gSpacerForBodyElement.style.height = "5000px";
|
||||
document.documentElement.scrollTop = 500;
|
||||
document.documentElement.scrollLeft = 500;
|
||||
cb();
|
||||
} },
|
||||
{ description: "Scroll to only bottom by oblique line wheel event with overflow-x: hidden (body is scrollable)",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
@@ -796,7 +802,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollUp,
|
||||
cleanup: function () { gScrollableElement.style.overflowX = "auto"; } },
|
||||
cleanup: function (cb) { gScrollableElement.style.overflowX = "auto"; cb(); } },
|
||||
{ description: "Scroll to only right by oblique pixel wheel event with overflow-y: hidden (body is scrollable)",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_PIXEL,
|
||||
deltaX: 16.0, deltaY: 16.0, deltaZ: 0.0,
|
||||
@@ -804,7 +810,7 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollRight,
|
||||
prepare: function() { gScrollableElement.style.overflowY = "hidden"; } },
|
||||
prepare: function(cb) { gScrollableElement.style.overflowY = "hidden"; cb(); } },
|
||||
{ description: "Scroll to only right by oblique line wheel event with overflow-y: hidden (body is scrollable)",
|
||||
event: { deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 1.0, deltaY: 1.0, deltaZ: 0.0,
|
||||
@@ -840,11 +846,12 @@ function doTestScroll(aSettings, aCallback)
|
||||
expectedOverflowDeltaX: 0, expectedOverflowDeltaY: 0,
|
||||
shiftKey: false, ctrlKey: false, altKey: false, metaKey: false, osKey: false },
|
||||
expected: kScrollLeft,
|
||||
cleanup: function () {
|
||||
cleanup: function (cb) {
|
||||
gScrollableElement.style.overflowY = "auto";
|
||||
gScrollableElement.style.position = "static";
|
||||
gSpacerForBodyElement.style.width = "";
|
||||
gSpacerForBodyElement.style.height = "";
|
||||
cb();
|
||||
} },
|
||||
];
|
||||
|
||||
@@ -867,9 +874,14 @@ function doTestScroll(aSettings, aCallback)
|
||||
var currentTest = kTests[currentTestIndex];
|
||||
description = "doTestScroll(aSettings=" + aSettings.description + "), " + currentTest.description + ": ";
|
||||
if (currentTest.prepare) {
|
||||
currentTest.prepare();
|
||||
currentTest.prepare(doTestCurrentScroll);
|
||||
} else {
|
||||
doTestCurrentScroll();
|
||||
}
|
||||
}
|
||||
|
||||
function doTestCurrentScroll() {
|
||||
var currentTest = kTests[currentTestIndex];
|
||||
sendWheelAndWait(10, 10, currentTest.event, function () {
|
||||
if (currentTest.expected == kNoScroll) {
|
||||
is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
|
||||
@@ -899,11 +911,16 @@ function doTestScroll(aSettings, aCallback)
|
||||
}
|
||||
}
|
||||
if (currentTest.cleanup) {
|
||||
currentTest.cleanup();
|
||||
currentTest.cleanup(nextStep);
|
||||
} else {
|
||||
nextStep();
|
||||
}
|
||||
winUtils.advanceTimeAndRefresh(100);
|
||||
doNextTest();
|
||||
}, 10);
|
||||
|
||||
function nextStep() {
|
||||
winUtils.advanceTimeAndRefresh(100);
|
||||
doNextTest();
|
||||
}
|
||||
});
|
||||
}
|
||||
doNextTest();
|
||||
}
|
||||
@@ -1144,7 +1161,7 @@ function doTestZoom(aSettings, aCallback)
|
||||
onZoomReset(function () {
|
||||
hitEventLoop(doNextTest, 20);
|
||||
});
|
||||
}, 20);
|
||||
});
|
||||
}
|
||||
doNextTest();
|
||||
}
|
||||
@@ -1235,9 +1252,9 @@ function doTestZoomedScroll(aCallback)
|
||||
|
||||
synthesizeKey("0", { accelKey: true });
|
||||
onZoomReset(prepareTestZoomedLineScroll);
|
||||
}, 20);
|
||||
});
|
||||
}, 20);
|
||||
}, 20);
|
||||
});
|
||||
}, 20);
|
||||
}
|
||||
|
||||
@@ -1320,9 +1337,9 @@ function doTestZoomedScroll(aCallback)
|
||||
|
||||
synthesizeKey("0", { accelKey: true });
|
||||
onZoomReset(aCallback);
|
||||
}, 20);
|
||||
});
|
||||
}, 20);
|
||||
}, 20);
|
||||
});
|
||||
}, 20);
|
||||
}
|
||||
|
||||
@@ -1334,9 +1351,14 @@ function doTestZoomedScroll(aCallback)
|
||||
|
||||
function doTestWholeScroll(aCallback)
|
||||
{
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_x", 99999999);
|
||||
SpecialPowers.setIntPref("mousewheel.default.delta_multiplier_y", 99999999);
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["mousewheel.default.delta_multiplier_x", 999999],
|
||||
["mousewheel.default.delta_multiplier_y", 999999]]},
|
||||
function() { doTestWholeScroll2(aCallback); });
|
||||
}
|
||||
|
||||
function doTestWholeScroll2(aCallback)
|
||||
{
|
||||
const kTests = [
|
||||
{ description: "try whole-scroll to top (line)",
|
||||
prepare: function () {
|
||||
@@ -1574,14 +1596,11 @@ function doTestWholeScroll(aCallback)
|
||||
is(gScrollableElement.scrollLeft, kTest.expectedScrollLeft,
|
||||
"doTestWholeScroll, " + kTest.description + ": unexpected scrollLeft");
|
||||
if (++index == kTests.length) {
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_z");
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
} else {
|
||||
doIt();
|
||||
}
|
||||
}, 20);
|
||||
});
|
||||
}
|
||||
doIt();
|
||||
}
|
||||
@@ -1708,14 +1727,22 @@ function doTestActionOverride(aCallback)
|
||||
var index = 0;
|
||||
|
||||
function doIt()
|
||||
{
|
||||
const kTest = kTests[index];
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["mousewheel.default.action", kTest.action],
|
||||
["mousewheel.default.action.override_x", kTest.override_x]]},
|
||||
doIt2
|
||||
);
|
||||
}
|
||||
|
||||
function doIt2()
|
||||
{
|
||||
const kTest = kTests[index];
|
||||
description = "doTestActionOverride(action=" + kTest.action + ", " +
|
||||
"override_x=" + kTest.override_x + ", " +
|
||||
"deltaX=" + kTest.event.deltaX + ", " +
|
||||
"deltaY=" + kTest.event.deltaY + "): ";
|
||||
SpecialPowers.setIntPref("mousewheel.default.action", kTest.action);
|
||||
SpecialPowers.setIntPref("mousewheel.default.action.override_x", kTest.override_x);
|
||||
gScrollableElement.scrollTop = 1000;
|
||||
gScrollableElement.scrollLeft = 1000;
|
||||
sendWheelAndWait(10, 10, kTest.event, function () {
|
||||
@@ -1734,28 +1761,31 @@ function doTestActionOverride(aCallback)
|
||||
is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
|
||||
}
|
||||
if (++index == kTests.length) {
|
||||
SpecialPowers.setIntPref("mousewheel.default.action", 1);
|
||||
SpecialPowers.setIntPref("mousewheel.default.action.override_x", -1);
|
||||
SimpleTest.executeSoon(aCallback);
|
||||
} else {
|
||||
doIt();
|
||||
}
|
||||
}, 20);
|
||||
});
|
||||
}
|
||||
doIt();
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
SpecialPowers.setBoolPref("general.smoothScroll", false);
|
||||
|
||||
SpecialPowers.setIntPref("mousewheel.default.action", 1); // scroll
|
||||
SpecialPowers.setIntPref("mousewheel.default.action.override_x", -1);
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.action", 2); // history
|
||||
SpecialPowers.setIntPref("mousewheel.with_shift.action.override_x", -1);
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.action", 3); // zoom
|
||||
SpecialPowers.setIntPref("mousewheel.with_control.action.override_x", -1);
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["test.events.async.enabled", true],
|
||||
["general.smoothScroll", false],
|
||||
["mousewheel.default.action", 1], // scroll
|
||||
["mousewheel.default.action.override_x", -1],
|
||||
["mousewheel.with_shift.action", 2], // history
|
||||
["mousewheel.with_shift.action.override_x", -1],
|
||||
["mousewheel.with_control.action", 3], // zoom
|
||||
["mousewheel.with_control.action.override_x", -1]]},
|
||||
runTests2);
|
||||
}
|
||||
|
||||
function runTests2()
|
||||
{
|
||||
const kSettings = [
|
||||
{ description: "all delta values are not customized",
|
||||
deltaMultiplierX: 1.0, deltaMultiplierY: 1.0, deltaMultiplierZ: 1.0 },
|
||||
@@ -1782,21 +1812,23 @@ function runTests()
|
||||
var index = 0;
|
||||
|
||||
function doTest() {
|
||||
setDeltaMultiplierSettings(kSettings[index]);
|
||||
doTestScroll(kSettings[index], function () {
|
||||
doTestZoom(kSettings[index], function() {
|
||||
if (++index == kSettings.length) {
|
||||
setDeltaMultiplierSettings(kSettings[0]);
|
||||
doTestZoomedScroll(function() {
|
||||
doTestWholeScroll(function() {
|
||||
doTestActionOverride(function() {
|
||||
finishTests();
|
||||
setDeltaMultiplierSettings(kSettings[index], function () {
|
||||
doTestScroll(kSettings[index], function () {
|
||||
doTestZoom(kSettings[index], function() {
|
||||
if (++index == kSettings.length) {
|
||||
setDeltaMultiplierSettings(kSettings[0], function() {
|
||||
doTestZoomedScroll(function() {
|
||||
doTestWholeScroll(function() {
|
||||
doTestActionOverride(function() {
|
||||
finishTests();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
doTest();
|
||||
}
|
||||
} else {
|
||||
doTest();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1805,34 +1837,6 @@ function runTests()
|
||||
|
||||
function finishTests()
|
||||
{
|
||||
SpecialPowers.clearUserPref("general.smoothScroll");
|
||||
|
||||
SpecialPowers.clearUserPref("mousewheel.default.action");
|
||||
SpecialPowers.clearUserPref("mousewheel.default.action.override_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.action");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.action.override_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.action");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.action.override_x");
|
||||
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.default.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_alt.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_control.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_meta.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_shift.delta_multiplier_z");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_x");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_y");
|
||||
SpecialPowers.clearUserPref("mousewheel.with_win.delta_multiplier_z");
|
||||
|
||||
winUtils.restoreNormalRefresh();
|
||||
|
||||
window.opener.finish();
|
||||
|
||||
@@ -1,26 +1,4 @@
|
||||
let gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
|
||||
|
||||
// Returns the chrome side nsIPluginTag for this plugin
|
||||
function getTestPlugin(aName) {
|
||||
let pluginName = aName || "Test Plug-in";
|
||||
let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
|
||||
let tags = ph.getPluginTags();
|
||||
|
||||
// Find the test plugin
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
if (tags[i].name == pluginName)
|
||||
return tags[i];
|
||||
}
|
||||
ok(false, "Unable to find plugin");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set the test plugin state, disabling features like click-to-play
|
||||
function setTestPluginEnabledState(newEnabledState, pluginName) {
|
||||
let name = pluginName || "Test Plug-in";
|
||||
let plugin = getTestPlugin(name);
|
||||
plugin.enabledState = newEnabledState;
|
||||
}
|
||||
var gTestRoot = getRootDirectory(gTestPath).replace("chrome://mochitests/content/", "http://127.0.0.1:8888/");
|
||||
|
||||
// simple tab load helper, pilfered from browser plugin tests
|
||||
function promiseTabLoad(tab, url, eventType="load") {
|
||||
@@ -61,33 +39,27 @@ function promiseWaitForEvent(object, eventName, capturing = false, chrome = fals
|
||||
|
||||
add_task(function* () {
|
||||
registerCleanupFunction(function () {
|
||||
Services.prefs.clearUserPref("browser.uiCustomization.disableAnimation");
|
||||
window.focus();
|
||||
});
|
||||
});
|
||||
|
||||
add_task(function* () {
|
||||
Services.prefs.setBoolPref("browser.uiCustomization.disableAnimation", true);
|
||||
setTestPluginEnabledState(Ci.nsIPluginTag.STATE_ENABLED, "Test Plug-in");
|
||||
|
||||
let pluginTab = gBrowser.selectedTab = gBrowser.addTab();
|
||||
let customizeTab = gBrowser.addTab();
|
||||
let prefTab = gBrowser.addTab();
|
||||
|
||||
yield promiseTabLoad(pluginTab, gTestRoot + "plugin_test.html");
|
||||
yield promiseTabLoad(customizeTab, "about:customizing");
|
||||
yield promiseTabLoad(prefTab, "about:preferences");
|
||||
|
||||
let result = yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
|
||||
yield ContentTask.spawn(gBrowser.selectedBrowser, null, function*() {
|
||||
let doc = content.document;
|
||||
let plugin = doc.getElementById("testplugin");
|
||||
return !!plugin;
|
||||
Assert.ok(!!plugin, "plugin is loaded");
|
||||
});
|
||||
|
||||
is(result, true, "plugin is loaded");
|
||||
|
||||
let cpromise = promiseWaitForEvent(window.gNavToolbox, "customizationready");
|
||||
let ppromise = promiseWaitForEvent(window, "MozAfterPaint");
|
||||
gBrowser.selectedTab = customizeTab;
|
||||
yield cpromise;
|
||||
gBrowser.selectedTab = prefTab;
|
||||
yield ppromise;
|
||||
|
||||
// We're going to switch tabs using actual mouse clicks, which helps
|
||||
@@ -99,42 +71,32 @@ add_task(function* () {
|
||||
info("-> " + tabStripContainer.firstChild.tagName); // tab
|
||||
info("-> " + tabStripContainer.childNodes[0].label); // test harness tab
|
||||
info("-> " + tabStripContainer.childNodes[1].label); // plugin tab
|
||||
info("-> " + tabStripContainer.childNodes[2].label); // customize tab
|
||||
info("-> " + tabStripContainer.childNodes[2].label); // preferences tab
|
||||
|
||||
for (let iteration = 0; iteration < 5; iteration++) {
|
||||
cpromise = promiseWaitForEvent(window.gNavToolbox, "aftercustomization");
|
||||
ppromise = promiseWaitForEvent(window, "MozAfterPaint");
|
||||
EventUtils.synthesizeMouseAtCenter(tabStripContainer.childNodes[1], {}, window);
|
||||
yield cpromise;
|
||||
yield ppromise;
|
||||
|
||||
result = yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() {
|
||||
yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() {
|
||||
let doc = content.document;
|
||||
let plugin = doc.getElementById("testplugin");
|
||||
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
|
||||
Assert.ok(XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible(),
|
||||
"plugin is visible");
|
||||
});
|
||||
|
||||
is(result, true, "plugin is visible");
|
||||
|
||||
cpromise = promiseWaitForEvent(window.gNavToolbox, "customizationready");
|
||||
ppromise = promiseWaitForEvent(window, "MozAfterPaint");
|
||||
EventUtils.synthesizeMouseAtCenter(tabStripContainer.childNodes[2], {}, window);
|
||||
yield cpromise;
|
||||
yield ppromise;
|
||||
|
||||
result = yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() {
|
||||
yield ContentTask.spawn(pluginTab.linkedBrowser, null, function*() {
|
||||
let doc = content.document;
|
||||
let plugin = doc.getElementById("testplugin");
|
||||
return XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible();
|
||||
Assert.ok(!XPCNativeWrapper.unwrap(plugin).nativeWidgetIsVisible(),
|
||||
"plugin is hidden");
|
||||
});
|
||||
is(result, false, "plugin is hidden");
|
||||
}
|
||||
|
||||
// wait for customize view to shutdown cleanly otherwise we get
|
||||
// a ton of error spew on shutdown.
|
||||
cpromise = promiseWaitForEvent(window.gNavToolbox, "aftercustomization");
|
||||
gBrowser.removeTab(customizeTab);
|
||||
yield cpromise;
|
||||
|
||||
gBrowser.removeTab(prefTab);
|
||||
gBrowser.removeTab(pluginTab);
|
||||
});
|
||||
|
||||
+19
-4
@@ -15,6 +15,8 @@
|
||||
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/DOMError.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/DOMExceptionBinding.h"
|
||||
#include "mozilla/dom/MediaStreamError.h"
|
||||
#include "mozilla/dom/PromiseBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
@@ -2499,9 +2501,17 @@ Promise::MaybeReportRejected()
|
||||
}
|
||||
|
||||
js::ErrorReport report(cx);
|
||||
if (!report.init(cx, val)) {
|
||||
JS_ClearPendingException(cx);
|
||||
return;
|
||||
RefPtr<Exception> exp;
|
||||
bool isObject = val.isObject();
|
||||
if (!isObject || NS_FAILED(UNWRAP_OBJECT(Exception, &val.toObject(), exp))) {
|
||||
if (!isObject ||
|
||||
NS_FAILED(UNWRAP_OBJECT(DOMException, &val.toObject(), exp))) {
|
||||
if (!report.init(cx, val, js::ErrorReport::NoSideEffects)) {
|
||||
NS_WARNING("Couldn't convert the unhandled rejected value to an exception.");
|
||||
JS_ClearPendingException(cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
@@ -2509,7 +2519,12 @@ Promise::MaybeReportRejected()
|
||||
bool isChrome = isMainThread ? nsContentUtils::IsSystemPrincipal(nsContentUtils::ObjectPrincipal(obj))
|
||||
: GetCurrentThreadWorkerPrivate()->IsChromeWorker();
|
||||
nsPIDOMWindow* win = isMainThread ? xpc::WindowGlobalOrNull(obj) : nullptr;
|
||||
xpcReport->Init(report.report(), report.message(), isChrome, win ? win->WindowID() : 0);
|
||||
uint64_t windowID = win ? win->WindowID() : 0;
|
||||
if (exp) {
|
||||
xpcReport->Init(cx, exp, isChrome, windowID);
|
||||
} else {
|
||||
xpcReport->Init(report.report(), report.message(), isChrome, windowID);
|
||||
}
|
||||
|
||||
// Now post an event to do the real reporting async
|
||||
// Since Promises preserve their wrapper, it is essential to RefPtr<> the
|
||||
|
||||
@@ -7,6 +7,7 @@ support-files =
|
||||
test_bug1004814.html
|
||||
worker_bug1004814.js
|
||||
geo_leak_test.html
|
||||
dummy.html
|
||||
!/dom/tests/mochitest/geolocation/network_geolocation.sjs
|
||||
|
||||
[browser_test_toolbars_visibility.js]
|
||||
@@ -15,7 +16,6 @@ support-files =
|
||||
[browser_bug1008941_dismissGeolocationHanger.js]
|
||||
skip-if = buildapp == 'mulet'
|
||||
[browser_test__content.js]
|
||||
skip-if = e10s
|
||||
[browser_ConsoleAPITests.js]
|
||||
skip-if = e10s
|
||||
[browser_ConsoleAPI_originAttributes.js]
|
||||
|
||||
@@ -39,7 +39,6 @@ Cu.import("resource://gre/modules/Task.jsm");
|
||||
|
||||
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const kContentDoc = "http://www.example.com/browser/dom/tests/browser/test_new_window_from_content_child.html";
|
||||
const kContentScript = "chrome://mochitests/content/browser/dom/tests/browser/test_new_window_from_content_child.js";
|
||||
const kNewWindowPrefKey = "browser.link.open_newwindow";
|
||||
const kNewWindowRestrictionPrefKey = "browser.link.open_newwindow.restriction";
|
||||
const kSameTab = "same tab";
|
||||
@@ -48,7 +47,7 @@ const kNewTab = "new tab";
|
||||
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.require_user_interaction_for_beforeunload", false]]});
|
||||
|
||||
requestLongerTimeout(2);
|
||||
requestLongerTimeout(3);
|
||||
|
||||
// The following "matrices" represent the result of content attempting to
|
||||
// open a window with window.open with the default feature set. The key of
|
||||
@@ -80,8 +79,8 @@ const kTargetBlank = {
|
||||
|
||||
// We'll be changing these preferences a lot, so we'll stash their original
|
||||
// values and make sure we restore them at the end of the test.
|
||||
let originalNewWindowPref = Services.prefs.getIntPref(kNewWindowPrefKey);
|
||||
let originalNewWindowRestrictionPref =
|
||||
var originalNewWindowPref = Services.prefs.getIntPref(kNewWindowPrefKey);
|
||||
var originalNewWindowRestrictionPref =
|
||||
Services.prefs.getIntPref(kNewWindowRestrictionPrefKey);
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
@@ -107,11 +106,12 @@ registerCleanupFunction(function() {
|
||||
* and cleaned up after.
|
||||
*/
|
||||
function prepareForResult(aBrowser, aExpectation) {
|
||||
let expectedSpec = kContentDoc.replace(/[^\/]*$/, "dummy.html");
|
||||
switch(aExpectation) {
|
||||
case kSameTab:
|
||||
return Task.spawn(function*() {
|
||||
yield BrowserTestUtils.browserLoaded(aBrowser);
|
||||
is(aBrowser.currentURI.spec, "about:robots", "Should be at about:robots");
|
||||
is(aBrowser.currentURI.spec, expectedSpec, "Should be at dummy.html");
|
||||
// Now put the browser back where it came from
|
||||
yield BrowserTestUtils.loadURI(aBrowser, kContentDoc);
|
||||
yield BrowserTestUtils.browserLoaded(aBrowser);
|
||||
@@ -122,15 +122,15 @@ function prepareForResult(aBrowser, aExpectation) {
|
||||
let newWin = yield BrowserTestUtils.waitForNewWindow();
|
||||
let newBrowser = newWin.gBrowser.selectedBrowser;
|
||||
yield BrowserTestUtils.browserLoaded(newBrowser);
|
||||
is(newBrowser.currentURI.spec, "about:robots", "Should be at about:robots");
|
||||
is(newBrowser.currentURI.spec, expectedSpec, "Should be at dummy.html");
|
||||
yield BrowserTestUtils.closeWindow(newWin);
|
||||
});
|
||||
break;
|
||||
case kNewTab:
|
||||
return Task.spawn(function*() {
|
||||
let newTab = yield BrowserTestUtils.waitForNewTab(gBrowser);
|
||||
is(newTab.linkedBrowser.currentURI.spec, "about:robots",
|
||||
"Should be at about:robots");
|
||||
is(newTab.linkedBrowser.currentURI.spec, expectedSpec,
|
||||
"Should be at dummy.html");
|
||||
yield BrowserTestUtils.removeTab(newTab);
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Tests that toolbars have proper visibility when opening a new window
|
||||
// in either content or chrome context.
|
||||
|
||||
const CONTENT_PAGE = "http://www.example.com/browser/dom/tests/browser/test_new_window_from_content_child.html";
|
||||
const ROOT = "http://www.example.com/browser/dom/tests/browser/";
|
||||
const CONTENT_PAGE = ROOT + "test_new_window_from_content_child.html";
|
||||
const TARGET_PAGE = ROOT + "dummy.html";
|
||||
|
||||
/**
|
||||
* This function retrieves the visibility state of the toolbars of a
|
||||
@@ -164,7 +166,7 @@ add_task(function*() {
|
||||
add_task(function* () {
|
||||
// First open a default window from this chrome context
|
||||
let defaultWindowPromise = BrowserTestUtils.waitForNewWindow();
|
||||
window.open("about:robots", "_blank");
|
||||
window.open(TARGET_PAGE, "_blank");
|
||||
let defaultWindow = yield defaultWindowPromise;
|
||||
|
||||
// Check that all toolbars are visible
|
||||
@@ -174,7 +176,7 @@ add_task(function* () {
|
||||
// Now lets open a window with toolbars hidden from this chrome context
|
||||
let features = "location=no, personalbar=no, toolbar=no, scrollbars=no, menubar=no, status=no";
|
||||
let popupWindowPromise = BrowserTestUtils.waitForNewWindow();
|
||||
window.open("about:robots", "_blank", features);
|
||||
window.open(TARGET_PAGE, "_blank", features);
|
||||
let popupWindow = yield popupWindowPromise;
|
||||
|
||||
// Test none of the tooolbars are visible
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Dummy test page</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"></meta>
|
||||
</head>
|
||||
<body>
|
||||
<p>Dummy test page</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -7,13 +7,14 @@
|
||||
<p><a id="winOpenDefault" href="#" onclick="return openWindow();">Open a new window via window.open with default features.</a></p>
|
||||
<p><a id="winOpenNonDefault" href="#" onclick="return openWindow('resizable=no, location=no, personalbar=no, toolbar=no, scrollbars=no, menubar=no, status=no, directories=no, height=100, width=500');">Open a new window via window.open with non-default features.</a></p>
|
||||
<p><a id="winOpenDialog" href="#" onclick="return openWindow('dialog=yes');">Open a new window via window.open with dialog=1.</a></p>
|
||||
<p><a id="targetBlank" href="about:robots" target="_blank">Open a new window via target="_blank".</a></p>
|
||||
<p><a id="winOpenNoURLNonDefault" href="#" onclick="return openBlankWindow('location=no, toolbar=no, height=100, width=100');">Open a blank new window via window.open with non-default features.</a></p>
|
||||
<p><a id="targetBlank" href="dummy.html" target="_blank">Open a new window via target="_blank".</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script>
|
||||
function openWindow(aFeatures="") {
|
||||
window.open("about:robots", "_blank", aFeatures);
|
||||
window.open("dummy.html", "_blank", aFeatures);
|
||||
return false;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1941,7 +1941,7 @@ ScriptExecutorRunnable::LogExceptionToConsole(JSContext* aCx,
|
||||
MOZ_ASSERT(!mScriptLoader.mRv.Failed());
|
||||
|
||||
js::ErrorReport report(aCx);
|
||||
if (!report.init(aCx, exn)) {
|
||||
if (!report.init(aCx, exn, js::ErrorReport::WithSideEffects)) {
|
||||
JS_ClearPendingException(aCx);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,9 @@ nsXBLPrototypeResources::FlushSkinSheets()
|
||||
|
||||
// We have scoped stylesheets. Reload any chrome stylesheets we
|
||||
// encounter. (If they aren't skin sheets, it doesn't matter, since
|
||||
// they'll still be in the chrome cache.
|
||||
// they'll still be in the chrome cache. Skip inline sheets, which
|
||||
// skin sheets can't be, and which in any case don't have a usable
|
||||
// URL to reload.)
|
||||
|
||||
nsTArray<StyleSheetHandle::RefPtr> oldSheets;
|
||||
|
||||
@@ -94,7 +96,7 @@ nsXBLPrototypeResources::FlushSkinSheets()
|
||||
nsIURI* uri = oldSheet->GetSheetURI();
|
||||
|
||||
StyleSheetHandle::RefPtr newSheet;
|
||||
if (IsChromeURI(uri)) {
|
||||
if (!oldSheet->IsInline() && IsChromeURI(uri)) {
|
||||
if (NS_FAILED(cssLoader->LoadSheetSync(uri, &newSheet)))
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "prnetdb.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Snprintf.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -52,6 +54,15 @@ static const char kNegotiateAuthSSPI[] = "network.auth.use-sspi";
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Return false when the channel comes from a Private browsing window.
|
||||
static bool
|
||||
TestNotInPBMode(nsIHttpAuthenticableChannel *authChannel)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> bareChannel = do_QueryInterface(authChannel);
|
||||
MOZ_ASSERT(bareChannel);
|
||||
return !NS_UsePrivateBrowsing(bareChannel);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpNegotiateAuth::GetAuthFlags(uint32_t *flags)
|
||||
{
|
||||
@@ -113,8 +124,9 @@ nsHttpNegotiateAuth::ChallengeReceived(nsIHttpAuthenticableChannel *authChannel,
|
||||
proxyInfo->GetHost(service);
|
||||
}
|
||||
else {
|
||||
bool allowed = TestNonFqdn(uri) ||
|
||||
TestPref(uri, kNegotiateAuthTrustedURIs);
|
||||
bool allowed = TestNotInPBMode(authChannel) &&
|
||||
(TestNonFqdn(uri) ||
|
||||
TestPref(uri, kNegotiateAuthTrustedURIs));
|
||||
if (!allowed) {
|
||||
LOG(("nsHttpNegotiateAuth::ChallengeReceived URI blocked\n"));
|
||||
return NS_ERROR_ABORT;
|
||||
|
||||
+1
-1
@@ -334,7 +334,7 @@ PathBuilderD2D::Finish()
|
||||
|
||||
HRESULT hr = mSink->Close();
|
||||
if (FAILED(hr)) {
|
||||
gfxDebug() << "Failed to close PathSink. Code: " << hexa(hr);
|
||||
gfxCriticalNote << "Failed to close PathSink. Code: " << hexa(hr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -153,13 +153,13 @@ RadialGradientEffectD2D1::PrepareForRender(D2D1_CHANGE_TYPE changeType)
|
||||
float transform[8];
|
||||
};
|
||||
|
||||
PSConstantBuffer buffer = { { dc.x, dc.y, dr }, 0,
|
||||
PSConstantBuffer buffer = { { dc.x, dc.y, dr }, 0.0f,
|
||||
{ mCenter1.x, mCenter1.y },
|
||||
A, mRadius1, mRadius1 * mRadius1,
|
||||
mStopCollection->GetExtendMode() != D2D1_EXTEND_MODE_CLAMP ? 1 : 0,
|
||||
mStopCollection->GetExtendMode() == D2D1_EXTEND_MODE_MIRROR ? 1 : 0,
|
||||
{ 0 }, { mat._11, mat._21, mat._31, 0,
|
||||
mat._12, mat._22, mat._32, 0 } };
|
||||
mStopCollection->GetExtendMode() != D2D1_EXTEND_MODE_CLAMP ? 1.0f : 0.0f,
|
||||
mStopCollection->GetExtendMode() == D2D1_EXTEND_MODE_MIRROR ? 1.0f : 0.0f,
|
||||
{ 0.0f }, { mat._11, mat._21, mat._31, 0.0f,
|
||||
mat._12, mat._22, mat._32, 0.0f } };
|
||||
|
||||
hr = mDrawInfo->SetPixelShaderConstantBuffer((BYTE*)&buffer, sizeof(buffer));
|
||||
|
||||
|
||||
+40
-15
@@ -68,6 +68,9 @@ GLBlitHelper::GLBlitHelper(GLContext* gl)
|
||||
|
||||
GLBlitHelper::~GLBlitHelper()
|
||||
{
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
DeleteTexBlitProgram();
|
||||
|
||||
GLuint tex[] = {
|
||||
@@ -91,6 +94,7 @@ bool
|
||||
GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
{
|
||||
const char kTexBlit_VertShaderSource[] = "\
|
||||
#version 100 \n\
|
||||
#ifdef GL_ES \n\
|
||||
precision mediump float; \n\
|
||||
#endif \n\
|
||||
@@ -109,10 +113,13 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
";
|
||||
|
||||
const char kTex2DBlit_FragShaderSource[] = "\
|
||||
#version 100 \n\
|
||||
#ifdef GL_ES \n\
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
|
||||
precision highp float; \n\
|
||||
#else \n\
|
||||
prevision mediump float; \n\
|
||||
precision mediump float; \n\
|
||||
#endif \n\
|
||||
#endif \n\
|
||||
uniform sampler2D uTexUnit; \n\
|
||||
\n\
|
||||
@@ -125,6 +132,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
";
|
||||
|
||||
const char kTex2DRectBlit_FragShaderSource[] = "\
|
||||
#version 100 \n\
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
|
||||
precision highp float; \n\
|
||||
#else \n\
|
||||
@@ -144,6 +152,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
";
|
||||
#ifdef ANDROID /* MOZ_WIDGET_ANDROID || MOZ_WIDGET_GONK */
|
||||
const char kTexExternalBlit_FragShaderSource[] = "\
|
||||
#version 100 \n\
|
||||
#extension GL_OES_EGL_image_external : require \n\
|
||||
#ifdef GL_FRAGMENT_PRECISION_HIGH \n\
|
||||
precision highp float; \n\
|
||||
@@ -172,6 +181,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196]
|
||||
*/
|
||||
const char kTexYUVPlanarBlit_FragShaderSource[] = "\
|
||||
#version 100 \n\
|
||||
#ifdef GL_ES \n\
|
||||
precision mediump float; \n\
|
||||
#endif \n\
|
||||
@@ -183,9 +193,9 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
uniform vec2 uCbCrTexScale; \n\
|
||||
void main() \n\
|
||||
{ \n\
|
||||
float y = texture2D(uYTexture, vTexCoord * uYTexScale).a; \n\
|
||||
float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).a; \n\
|
||||
float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).a; \n\
|
||||
float y = texture2D(uYTexture, vTexCoord * uYTexScale).r; \n\
|
||||
float cb = texture2D(uCbTexture, vTexCoord * uCbCrTexScale).r; \n\
|
||||
float cr = texture2D(uCrTexture, vTexCoord * uCbCrTexScale).r; \n\
|
||||
y = (y - 0.06275) * 1.16438; \n\
|
||||
cb = cb - 0.50196; \n\
|
||||
cr = cr - 0.50196; \n\
|
||||
@@ -198,6 +208,7 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
const char kTexNV12PlanarBlit_FragShaderSource[] = "\
|
||||
#version 100 \n\
|
||||
#extension GL_ARB_texture_rectangle : require \n\
|
||||
#ifdef GL_ES \n\
|
||||
precision mediump float \n\
|
||||
@@ -381,18 +392,16 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
// Cache and set attribute and uniform
|
||||
mGL->fUseProgram(program);
|
||||
switch (target) {
|
||||
#ifdef ANDROID
|
||||
case ConvertSurfaceTexture:
|
||||
case ConvertGralloc:
|
||||
#endif
|
||||
case BlitTex2D:
|
||||
case BlitTexRect:
|
||||
case ConvertEGLImage:
|
||||
case ConvertSurfaceTexture:
|
||||
case ConvertGralloc: {
|
||||
#ifdef ANDROID
|
||||
case ConvertEGLImage: {
|
||||
GLint texUnitLoc = mGL->fGetUniformLocation(program, "uTexUnit");
|
||||
MOZ_ASSERT(texUnitLoc != -1, "uniform uTexUnit not found");
|
||||
mGL->fUniform1i(texUnitLoc, 0);
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE("gralloc not support on non-android");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case ConvertPlanarYCbCr: {
|
||||
@@ -432,6 +441,8 @@ GLBlitHelper::InitTexQuadProgram(BlitType target)
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(mGL->fGetAttribLocation(program, "aPosition") == 0);
|
||||
mYFlipLoc = mGL->fGetUniformLocation(program, "uYflip");
|
||||
@@ -596,9 +607,23 @@ GLBlitHelper::BindAndUploadYUVTexture(Channel which,
|
||||
MOZ_ASSERT(which < Channel_Max, "Invalid channel!");
|
||||
GLuint* srcTexArr[3] = {&mSrcTexY, &mSrcTexCb, &mSrcTexCr};
|
||||
GLuint& tex = *srcTexArr[which];
|
||||
|
||||
// RED textures aren't valid in GLES2, and ALPHA textures are not valid in desktop GL Core Profiles.
|
||||
// So use R8 textures on GL3.0+ and GLES3.0+, but LUMINANCE/LUMINANCE/UNSIGNED_BYTE otherwise.
|
||||
GLenum format;
|
||||
GLenum internalFormat;
|
||||
if (mGL->IsAtLeast(gl::ContextProfile::OpenGLCore, 300) ||
|
||||
mGL->IsAtLeast(gl::ContextProfile::OpenGLES, 300)) {
|
||||
format = LOCAL_GL_RED;
|
||||
internalFormat = LOCAL_GL_R8;
|
||||
} else {
|
||||
format = LOCAL_GL_LUMINANCE;
|
||||
internalFormat = LOCAL_GL_LUMINANCE;
|
||||
}
|
||||
|
||||
if (!tex) {
|
||||
MOZ_ASSERT(needsAllocation);
|
||||
tex = CreateTexture(mGL, LOCAL_GL_ALPHA, LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE,
|
||||
tex = CreateTexture(mGL, internalFormat, format, LOCAL_GL_UNSIGNED_BYTE,
|
||||
gfx::IntSize(width, height), false);
|
||||
}
|
||||
mGL->fActiveTexture(LOCAL_GL_TEXTURE0 + which);
|
||||
@@ -611,17 +636,17 @@ GLBlitHelper::BindAndUploadYUVTexture(Channel which,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
LOCAL_GL_ALPHA,
|
||||
format,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
data);
|
||||
} else {
|
||||
mGL->fTexImage2D(LOCAL_GL_TEXTURE_2D,
|
||||
0,
|
||||
LOCAL_GL_ALPHA,
|
||||
internalFormat,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
LOCAL_GL_ALPHA,
|
||||
format,
|
||||
LOCAL_GL_UNSIGNED_BYTE,
|
||||
data);
|
||||
}
|
||||
|
||||
+6
-13
@@ -2322,12 +2322,13 @@ GLContext::MarkDestroyed()
|
||||
if (IsDestroyed())
|
||||
return;
|
||||
|
||||
// Null these before they're naturally nulled after dtor, as we want GLContext to
|
||||
// still be alive in *their* dtors.
|
||||
mScreen = nullptr;
|
||||
mBlitHelper = nullptr;
|
||||
mReadTexImageHelper = nullptr;
|
||||
|
||||
if (MakeCurrent()) {
|
||||
DestroyScreenBuffer();
|
||||
|
||||
mBlitHelper = nullptr;
|
||||
mReadTexImageHelper = nullptr;
|
||||
|
||||
mTexGarbageBin->GLContextTeardown();
|
||||
} else {
|
||||
NS_WARNING("MakeCurrent() failed during MarkDestroyed! Skipping GL object teardown.");
|
||||
@@ -2571,8 +2572,6 @@ GLContext::CreateScreenBufferImpl(const IntSize& size, const SurfaceCaps& caps)
|
||||
return false;
|
||||
}
|
||||
|
||||
DestroyScreenBuffer();
|
||||
|
||||
// This will rebind to 0 (Screen) if needed when
|
||||
// it falls out of scope.
|
||||
ScopedBindFramebuffer autoFB(this);
|
||||
@@ -2591,12 +2590,6 @@ GLContext::ResizeScreenBuffer(const IntSize& size)
|
||||
return mScreen->Resize(size);
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::DestroyScreenBuffer()
|
||||
{
|
||||
mScreen = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
GLContext::ForceDirtyScreen()
|
||||
{
|
||||
|
||||
+2
-4
@@ -284,8 +284,8 @@ public:
|
||||
}
|
||||
|
||||
if (profile == ContextProfile::OpenGL) {
|
||||
return profile == ContextProfile::OpenGLCore ||
|
||||
profile == ContextProfile::OpenGLCompatibility;
|
||||
return mProfile == ContextProfile::OpenGLCore ||
|
||||
mProfile == ContextProfile::OpenGLCompatibility;
|
||||
}
|
||||
|
||||
return profile == mProfile;
|
||||
@@ -3455,8 +3455,6 @@ protected:
|
||||
friend class GLScreenBuffer;
|
||||
UniquePtr<GLScreenBuffer> mScreen;
|
||||
|
||||
void DestroyScreenBuffer();
|
||||
|
||||
SharedSurface* mLockedSurface;
|
||||
|
||||
public:
|
||||
|
||||
@@ -32,6 +32,9 @@ GLReadTexImageHelper::GLReadTexImageHelper(GLContext* gl)
|
||||
|
||||
GLReadTexImageHelper::~GLReadTexImageHelper()
|
||||
{
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
mGL->fDeleteProgram(mPrograms[0]);
|
||||
mGL->fDeleteProgram(mPrograms[1]);
|
||||
mGL->fDeleteProgram(mPrograms[2]);
|
||||
|
||||
@@ -117,8 +117,10 @@ SharedSurface_ANGLEShareHandle::~SharedSurface_ANGLEShareHandle()
|
||||
{
|
||||
mEGL->fDestroySurface(Display(), mPBuffer);
|
||||
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
if (mFence) {
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteFences(1, &mFence);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "SharedSurfaceD3D11Interop.h"
|
||||
|
||||
#include <d3d11.h>
|
||||
#include "gfxPrefs.h"
|
||||
#include "GLContext.h"
|
||||
#include "WGLLibrary.h"
|
||||
|
||||
@@ -264,15 +265,9 @@ SharedSurface_D3D11Interop::Create(const RefPtr<DXGLDevice>& dxgl,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLuint fence = 0;
|
||||
if (gl->IsExtensionSupported(GLContext::NV_fence)) {
|
||||
gl->MakeCurrent();
|
||||
gl->fGenFences(1, &fence);
|
||||
}
|
||||
|
||||
typedef SharedSurface_D3D11Interop ptrT;
|
||||
UniquePtr<ptrT> ret ( new ptrT(gl, size, hasAlpha, renderbufferGL, dxgl, objectWGL,
|
||||
textureD3D, sharedHandle, keyedMutex, fence) );
|
||||
textureD3D, sharedHandle, keyedMutex) );
|
||||
return Move(ret);
|
||||
}
|
||||
|
||||
@@ -284,8 +279,7 @@ SharedSurface_D3D11Interop::SharedSurface_D3D11Interop(GLContext* gl,
|
||||
HANDLE objectWGL,
|
||||
const RefPtr<ID3D11Texture2D>& textureD3D,
|
||||
HANDLE sharedHandle,
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
|
||||
GLuint fence)
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex)
|
||||
: SharedSurface(SharedSurfaceType::DXGLInterop2,
|
||||
AttachmentType::GLRenderbuffer,
|
||||
gl,
|
||||
@@ -296,9 +290,9 @@ SharedSurface_D3D11Interop::SharedSurface_D3D11Interop(GLContext* gl,
|
||||
, mDXGL(dxgl)
|
||||
, mObjectWGL(objectWGL)
|
||||
, mTextureD3D(textureD3D)
|
||||
, mNeedsFinish(gfxPrefs::WebGLDXGLNeedsFinish())
|
||||
, mSharedHandle(sharedHandle)
|
||||
, mKeyedMutex(keyedMutex)
|
||||
, mFence(fence)
|
||||
, mLockedForGL(false)
|
||||
{ }
|
||||
|
||||
@@ -306,16 +300,14 @@ SharedSurface_D3D11Interop::~SharedSurface_D3D11Interop()
|
||||
{
|
||||
MOZ_ASSERT(!mLockedForGL);
|
||||
|
||||
mGL->fDeleteRenderbuffers(1, &mProdRB);
|
||||
|
||||
if (!mDXGL->UnregisterObject(mObjectWGL)) {
|
||||
NS_WARNING("Failed to release a DXGL object, possibly leaking it.");
|
||||
}
|
||||
|
||||
if (mFence) {
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteFences(1, &mFence);
|
||||
}
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
mGL->fDeleteRenderbuffers(1, &mProdRB);
|
||||
|
||||
// mDXGL is closed when it runs out of refs.
|
||||
}
|
||||
@@ -364,8 +356,9 @@ SharedSurface_D3D11Interop::ProducerReleaseImpl()
|
||||
mKeyedMutex->ReleaseSync(0);
|
||||
}
|
||||
|
||||
// TODO fence properly. This kills performance.
|
||||
mGL->fFinish();
|
||||
if (mNeedsFinish) {
|
||||
mGL->fFinish();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -373,8 +366,8 @@ SharedSurface_D3D11Interop::ToSurfaceDescriptor(layers::SurfaceDescriptor* const
|
||||
{
|
||||
gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
|
||||
: gfx::SurfaceFormat::B8G8R8X8;
|
||||
*out_descriptor = layers::SurfaceDescriptorD3D10((WindowsHandle)GetSharedHandle(),
|
||||
format, mSize);
|
||||
*out_descriptor = layers::SurfaceDescriptorD3D10(WindowsHandle(mSharedHandle), format,
|
||||
mSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,17 +22,19 @@ class WGLLibrary;
|
||||
class SharedSurface_D3D11Interop
|
||||
: public SharedSurface
|
||||
{
|
||||
public:
|
||||
const GLuint mProdRB;
|
||||
const RefPtr<DXGLDevice> mDXGL;
|
||||
const HANDLE mObjectWGL;
|
||||
const HANDLE mSharedHandle;
|
||||
const RefPtr<ID3D11Texture2D> mTextureD3D;
|
||||
const bool mNeedsFinish;
|
||||
|
||||
protected:
|
||||
RefPtr<IDXGIKeyedMutex> mKeyedMutex;
|
||||
RefPtr<IDXGIKeyedMutex> mConsumerKeyedMutex;
|
||||
RefPtr<ID3D11Texture2D> mConsumerTexture;
|
||||
const GLuint mFence;
|
||||
|
||||
protected:
|
||||
bool mLockedForGL;
|
||||
|
||||
public:
|
||||
@@ -56,8 +58,7 @@ protected:
|
||||
HANDLE objectWGL,
|
||||
const RefPtr<ID3D11Texture2D>& textureD3D,
|
||||
HANDLE sharedHandle,
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex,
|
||||
GLuint fence);
|
||||
const RefPtr<IDXGIKeyedMutex>& keyedMutex);
|
||||
|
||||
public:
|
||||
virtual ~SharedSurface_D3D11Interop();
|
||||
@@ -73,11 +74,6 @@ public:
|
||||
}
|
||||
|
||||
virtual bool ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) override;
|
||||
|
||||
// Implementation-specific functions below:
|
||||
HANDLE GetSharedHandle() const {
|
||||
return mSharedHandle;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -88,9 +88,12 @@ SharedSurface_EGLImage::~SharedSurface_EGLImage()
|
||||
{
|
||||
mEGL->fDestroyImage(Display(), mImage);
|
||||
|
||||
mGL->MakeCurrent();
|
||||
mGL->fDeleteTextures(1, &mProdTex);
|
||||
mProdTex = 0;
|
||||
if (mSync) {
|
||||
// We can't call this unless we have the ext, but we will always have
|
||||
// the ext if we have something to destroy.
|
||||
mEGL->fDestroySync(Display(), mSync);
|
||||
mSync = 0;
|
||||
}
|
||||
|
||||
if (mConsTex) {
|
||||
MOZ_ASSERT(mGarbageBin);
|
||||
@@ -98,12 +101,11 @@ SharedSurface_EGLImage::~SharedSurface_EGLImage()
|
||||
mConsTex = 0;
|
||||
}
|
||||
|
||||
if (mSync) {
|
||||
// We can't call this unless we have the ext, but we will always have
|
||||
// the ext if we have something to destroy.
|
||||
mEGL->fDestroySync(Display(), mSync);
|
||||
mSync = 0;
|
||||
}
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
mGL->fDeleteTextures(1, &mProdTex);
|
||||
mProdTex = 0;
|
||||
}
|
||||
|
||||
layers::TextureFlags
|
||||
|
||||
@@ -77,11 +77,11 @@ SharedSurface_GLXDrawable::UnlockProdImpl()
|
||||
bool
|
||||
SharedSurface_GLXDrawable::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
|
||||
{
|
||||
if (!mXlibSurface)
|
||||
return false;
|
||||
if (!mXlibSurface)
|
||||
return false;
|
||||
|
||||
*out_descriptor = layers::SurfaceDescriptorX11(mXlibSurface, mInSameProcess);
|
||||
return true;
|
||||
*out_descriptor = layers::SurfaceDescriptorX11(mXlibSurface, mInSameProcess);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -135,7 +135,6 @@ SharedSurface_Gralloc::SharedSurface_Gralloc(GLContext* prodGL,
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
|
||||
{
|
||||
@@ -145,10 +144,11 @@ SharedSurface_Gralloc::HasExtensions(GLLibraryEGL* egl, GLContext* gl)
|
||||
|
||||
SharedSurface_Gralloc::~SharedSurface_Gralloc()
|
||||
{
|
||||
|
||||
DEBUG_PRINT("[SharedSurface_Gralloc %p] destroyed\n", this);
|
||||
|
||||
mGL->MakeCurrent();
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
mGL->fDeleteTextures(1, &mProdTex);
|
||||
|
||||
if (mSync) {
|
||||
|
||||
@@ -165,11 +165,10 @@ SharedSurface_IOSurface::SharedSurface_IOSurface(const RefPtr<MacIOSurface>& ioS
|
||||
|
||||
SharedSurface_IOSurface::~SharedSurface_IOSurface()
|
||||
{
|
||||
if (mProdTex) {
|
||||
DebugOnly<bool> success = mGL->MakeCurrent();
|
||||
MOZ_ASSERT(success);
|
||||
mGL->fDeleteTextures(1, &mProdTex);
|
||||
}
|
||||
if (!mGL->MakeCurrent())
|
||||
return;
|
||||
|
||||
mGL->fDeleteTextures(1, &mProdTex);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -36,6 +36,7 @@ TextureGarbageBin::EmptyGarbage()
|
||||
if (!mGL)
|
||||
return;
|
||||
|
||||
MOZ_RELEASE_ASSERT(mGL->IsCurrent());
|
||||
while (!mGarbageTextures.empty()) {
|
||||
GLuint tex = mGarbageTextures.top();
|
||||
mGarbageTextures.pop();
|
||||
|
||||
@@ -58,7 +58,7 @@ AxisPhysicsMSDModel::Acceleration(const State &aState)
|
||||
|
||||
|
||||
double
|
||||
AxisPhysicsMSDModel::GetDestination()
|
||||
AxisPhysicsMSDModel::GetDestination() const
|
||||
{
|
||||
return mDestination;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
/**
|
||||
* Gets the raw destination of this axis at this moment.
|
||||
*/
|
||||
double GetDestination();
|
||||
double GetDestination() const;
|
||||
|
||||
/**
|
||||
* Sets the raw destination of this axis at this moment.
|
||||
|
||||
@@ -423,6 +423,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool IsScrollbarContainer() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mLayer->IsScrollbarContainer();
|
||||
}
|
||||
|
||||
// Expose an opaque pointer to the layer. Mostly used for printf
|
||||
// purposes. This is not intended to be a general-purpose accessor
|
||||
// for the underlying layer.
|
||||
|
||||
@@ -367,7 +367,8 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
|
||||
GetEventRegionsOverride(aParent, aLayer));
|
||||
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
|
||||
aLayer.GetScrollbarDirection(),
|
||||
aLayer.GetScrollbarSize());
|
||||
aLayer.GetScrollbarSize(),
|
||||
aLayer.IsScrollbarContainer());
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -546,7 +547,8 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
|
||||
|
||||
node->SetScrollbarData(aLayer.GetScrollbarTargetContainerId(),
|
||||
aLayer.GetScrollbarDirection(),
|
||||
aLayer.GetScrollbarSize());
|
||||
aLayer.GetScrollbarSize(),
|
||||
aLayer.IsScrollbarContainer());
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1080,6 +1082,14 @@ APZCTreeManager::ProcessMouseEvent(WidgetMouseEventBase& aEvent,
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY)
|
||||
{
|
||||
if (mApzcForInputBlock) {
|
||||
mApzcForInputBlock->HandleTouchVelocity(aTimestampMs, aSpeedY);
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
APZCTreeManager::ProcessWheelEvent(WidgetWheelEvent& aEvent,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
@@ -1938,7 +1948,7 @@ APZCTreeManager::GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) c
|
||||
// ancestorUntransform is updated to RC.Inverse() * QC.Inverse() when parent == P
|
||||
ancestorUntransform = parent->GetAncestorTransform().Inverse();
|
||||
// asyncUntransform is updated to PA.Inverse() when parent == P
|
||||
Matrix4x4 asyncUntransform = parent->GetCurrentAsyncTransformWithOverscroll().Inverse().ToUnknownMatrix();
|
||||
Matrix4x4 asyncUntransform = parent->GetCurrentAsyncTransformWithOverscroll(AsyncPanZoomController::NORMAL).Inverse().ToUnknownMatrix();
|
||||
// untransformSinceLastApzc is RC.Inverse() * QC.Inverse() * PA.Inverse()
|
||||
Matrix4x4 untransformSinceLastApzc = ancestorUntransform * asyncUntransform;
|
||||
|
||||
@@ -1970,7 +1980,7 @@ APZCTreeManager::GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) co
|
||||
// leftmost matrix in a multiplication is applied first.
|
||||
|
||||
// asyncUntransform is LA.Inverse()
|
||||
Matrix4x4 asyncUntransform = aApzc->GetCurrentAsyncTransformWithOverscroll().Inverse().ToUnknownMatrix();
|
||||
Matrix4x4 asyncUntransform = aApzc->GetCurrentAsyncTransformWithOverscroll(AsyncPanZoomController::NORMAL).Inverse().ToUnknownMatrix();
|
||||
|
||||
// aTransformToGeckoOut is initialized to LA.Inverse() * LD * MC * NC * OC * PC
|
||||
result = asyncUntransform * aApzc->GetTransformToLastDispatchedPaint() * aApzc->GetAncestorTransform();
|
||||
|
||||
@@ -18,9 +18,8 @@
|
||||
#include "mozilla/layers/APZUtils.h" // for HitTestResult
|
||||
#include "mozilla/layers/TouchCounter.h"// for TouchCounter
|
||||
#include "mozilla/Mutex.h" // for Mutex
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/TimeStamp.h" // for mozilla::TimeStamp
|
||||
#include "mozilla/Vector.h" // for mozilla::Vector
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "nsTArrayForwardDeclare.h" // for nsTArray, nsTArray_Impl, etc
|
||||
@@ -442,6 +441,14 @@ public:
|
||||
bool* aOutHitScrollbar = nullptr);
|
||||
ScreenToParentLayerMatrix4x4 GetScreenToApzcTransform(const AsyncPanZoomController *aApzc) const;
|
||||
ParentLayerToScreenMatrix4x4 GetApzcToGeckoTransform(const AsyncPanZoomController *aApzc) const;
|
||||
|
||||
/**
|
||||
* Process touch velocity.
|
||||
* Sometimes the touch move event will have a velocity even though no scrolling
|
||||
* is occurring such as when the toolbar is being hidden/shown in Fennec.
|
||||
* This function can be called to have the y axis' velocity queue updated.
|
||||
*/
|
||||
void ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY);
|
||||
private:
|
||||
typedef bool (*GuidComparator)(const ScrollableLayerGuid&, const ScrollableLayerGuid&);
|
||||
|
||||
|
||||
@@ -10,14 +10,15 @@
|
||||
#include "base/message_loop.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class WheelScrollAnimation;
|
||||
class SmoothScrollAnimation;
|
||||
|
||||
class AsyncPanZoomAnimation {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomAnimation)
|
||||
@@ -45,13 +46,16 @@ public:
|
||||
* Get the deferred tasks in |mDeferredTasks| and place them in |aTasks|. See
|
||||
* |mDeferredTasks| for more information. Clears |mDeferredTasks|.
|
||||
*/
|
||||
Vector<Task*> TakeDeferredTasks() {
|
||||
nsTArray<Task*> TakeDeferredTasks() {
|
||||
return Move(mDeferredTasks);
|
||||
}
|
||||
|
||||
virtual WheelScrollAnimation* AsWheelScrollAnimation() {
|
||||
return nullptr;
|
||||
}
|
||||
virtual SmoothScrollAnimation* AsSmoothScrollAnimation() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual bool WantsRepaints() {
|
||||
return true;
|
||||
@@ -67,7 +71,7 @@ protected:
|
||||
* Derived classes can add tasks here in Sample(), and the APZC can call
|
||||
* ExecuteDeferredTasks() to execute them.
|
||||
*/
|
||||
Vector<Task*> mDeferredTasks;
|
||||
nsTArray<Task*> mDeferredTasks;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include "mozilla/MouseEvents.h" // for WidgetWheelEvent
|
||||
#include "mozilla/Preferences.h" // for Preferences
|
||||
#include "mozilla/ReentrantMonitor.h" // for ReentrantMonitorAutoEnter, etc
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/StaticPtr.h" // for StaticAutoPtr
|
||||
#include "mozilla/Telemetry.h" // for Telemetry
|
||||
#include "mozilla/TimeStamp.h" // for TimeDuration, TimeStamp
|
||||
@@ -58,7 +59,6 @@
|
||||
#include "mozilla/unused.h" // for unused
|
||||
#include "mozilla/FloatingPoint.h" // for FuzzyEquals*
|
||||
#include "nsAlgorithm.h" // for clamped
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsDebug.h" // for NS_WARNING
|
||||
#include "nsIDOMWindowUtils.h" // for nsIDOMWindowUtils
|
||||
@@ -516,11 +516,10 @@ public:
|
||||
// while holding mMonitor, because otherwise, if the overscrolled APZC
|
||||
// is this one, then the SetState(NOTHING) in UpdateAnimation will
|
||||
// stomp on the SetState(SNAP_BACK) it does.
|
||||
if (!mDeferredTasks.append(NewRunnableMethod(mOverscrollHandoffChain.get(),
|
||||
&OverscrollHandoffChain::SnapBackOverscrolledApzc,
|
||||
&mApzc))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
mDeferredTasks.AppendElement(
|
||||
NewRunnableMethod(mOverscrollHandoffChain.get(),
|
||||
&OverscrollHandoffChain::SnapBackOverscrolledApzc,
|
||||
&mApzc));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -569,13 +568,12 @@ public:
|
||||
// the lock ordering. Instead we schedule HandleFlingOverscroll() to be
|
||||
// called after mMonitor is released.
|
||||
APZC_LOG("%p fling went into overscroll, handing off with velocity %s\n", &mApzc, Stringify(velocity).c_str());
|
||||
if (!mDeferredTasks.append(NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleFlingOverscroll,
|
||||
velocity,
|
||||
mOverscrollHandoffChain,
|
||||
mScrolledApzc))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
mDeferredTasks.AppendElement(
|
||||
NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleFlingOverscroll,
|
||||
velocity,
|
||||
mOverscrollHandoffChain,
|
||||
mScrolledApzc));
|
||||
|
||||
// If there is a remaining velocity on this APZC, continue this fling
|
||||
// as well. (This fling and the handed-off fling will run concurrently.)
|
||||
@@ -703,10 +701,9 @@ public:
|
||||
// The scroll snapping is done in a deferred task, otherwise the state
|
||||
// change to NOTHING caused by the overscroll animation ending would
|
||||
// clobber a possible state change to SMOOTH_SCROLL in ScrollSnap().
|
||||
if (!mDeferredTasks.append(NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::ScrollSnap))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
mDeferredTasks.AppendElement(
|
||||
NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::ScrollSnap));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -742,11 +739,19 @@ public:
|
||||
* frame. Returns true if the smooth scroll should be advanced by one frame,
|
||||
* or false if the smooth scroll has ended.
|
||||
*/
|
||||
bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) {
|
||||
bool DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta) override {
|
||||
nsPoint oneParentLayerPixel =
|
||||
CSSPoint::ToAppUnits(ParentLayerPoint(1, 1) / aFrameMetrics.GetZoom());
|
||||
if (mXAxisModel.IsFinished(oneParentLayerPixel.x) &&
|
||||
mYAxisModel.IsFinished(oneParentLayerPixel.y)) {
|
||||
// Set the scroll offset to the exact destination. If we allow the scroll
|
||||
// offset to end up being a bit off from the destination, we can get
|
||||
// artefacts like "scroll to the next snap point in this direction"
|
||||
// scrolling to the snap point we're already supposed to be at.
|
||||
aFrameMetrics.SetScrollOffset(
|
||||
aFrameMetrics.CalculateScrollRange().ClampPoint(
|
||||
CSSPoint::FromAppUnits(nsPoint(mXAxisModel.GetDestination(),
|
||||
mYAxisModel.GetDestination()))));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -814,12 +819,10 @@ public:
|
||||
// HandleSmoothScrollOverscroll() (which acquires the tree lock) would violate
|
||||
// the lock ordering. Instead we schedule HandleSmoothScrollOverscroll() to be
|
||||
// called after mMonitor is released.
|
||||
if (!mDeferredTasks.append(NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleSmoothScrollOverscroll,
|
||||
velocity))) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
mDeferredTasks.AppendElement(
|
||||
NewRunnableMethod(&mApzc,
|
||||
&AsyncPanZoomController::HandleSmoothScrollOverscroll,
|
||||
velocity));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -831,6 +834,15 @@ public:
|
||||
mYAxisModel.SetDestination(static_cast<int32_t>(aNewDestination.y));
|
||||
}
|
||||
|
||||
CSSPoint GetDestination() const {
|
||||
return CSSPoint::FromAppUnits(
|
||||
nsPoint(mXAxisModel.GetDestination(), mYAxisModel.GetDestination()));
|
||||
}
|
||||
|
||||
SmoothScrollAnimation* AsSmoothScrollAnimation() override {
|
||||
return this;
|
||||
}
|
||||
|
||||
private:
|
||||
AsyncPanZoomController& mApzc;
|
||||
AxisPhysicsMSDModel mXAxisModel, mYAxisModel;
|
||||
@@ -1236,6 +1248,11 @@ nsEventStatus AsyncPanZoomController::HandleGestureEvent(const InputData& aEvent
|
||||
return rv;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::HandleTouchVelocity(uint32_t aTimesampMs, float aSpeedY)
|
||||
{
|
||||
mY.HandleTouchVelocity(aTimesampMs, aSpeedY);
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent) {
|
||||
APZC_LOG("%p got a touch-start in state %d\n", this, mState);
|
||||
mPanDirRestricted = false;
|
||||
@@ -1628,6 +1645,14 @@ AsyncPanZoomController::ConvertToGecko(const ScreenIntPoint& aPoint, CSSPoint* a
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
AllowsScrollingMoreThanOnePage(double aMultiplier)
|
||||
{
|
||||
const int32_t kMinAllowPageScroll =
|
||||
EventStateManager::MIN_MULTIPLIER_VALUE_ALLOWING_OVER_ONE_PAGE_SCROLL;
|
||||
return Abs(aMultiplier) >= kMinAllowPageScroll;
|
||||
}
|
||||
|
||||
ParentLayerPoint
|
||||
AsyncPanZoomController::GetScrollWheelDelta(const ScrollWheelInput& aEvent) const
|
||||
{
|
||||
@@ -1698,12 +1723,16 @@ AsyncPanZoomController::GetScrollWheelDelta(const ScrollWheelInput& aEvent) cons
|
||||
}
|
||||
}
|
||||
|
||||
if (Abs(delta.x) > pageScrollSize.width) {
|
||||
// We shouldn't scroll more than one page at once except when the
|
||||
// user preference is large.
|
||||
if (!AllowsScrollingMoreThanOnePage(aEvent.mUserDeltaMultiplierX) &&
|
||||
Abs(delta.x) > pageScrollSize.width) {
|
||||
delta.x = (delta.x >= 0)
|
||||
? pageScrollSize.width
|
||||
: -pageScrollSize.width;
|
||||
}
|
||||
if (Abs(delta.y) > pageScrollSize.height) {
|
||||
if (!AllowsScrollingMoreThanOnePage(aEvent.mUserDeltaMultiplierY) &&
|
||||
Abs(delta.y) > pageScrollSize.height) {
|
||||
delta.y = (delta.y >= 0)
|
||||
? pageScrollSize.height
|
||||
: -pageScrollSize.height;
|
||||
@@ -1814,8 +1843,16 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS,
|
||||
(uint32_t) ScrollInputMethodForWheelDeltaType(aEvent.mDeltaType));
|
||||
|
||||
|
||||
switch (aEvent.mScrollMode) {
|
||||
case ScrollWheelInput::SCROLLMODE_INSTANT: {
|
||||
|
||||
// Wheel events from "clicky" mouse wheels trigger scroll snapping to the
|
||||
// next snap point. Check for this, and adjust the delta to take into
|
||||
// account the snap point.
|
||||
CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
|
||||
MaybeAdjustDeltaForScrollSnapping(aEvent, delta, startPosition);
|
||||
|
||||
ScreenPoint distance = ToScreenCoordinates(
|
||||
ParentLayerPoint(fabs(delta.x), fabs(delta.y)), aEvent.mLocalOrigin);
|
||||
|
||||
@@ -1845,6 +1882,25 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
|
||||
// update it.
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
// Perform scroll snapping if appropriate.
|
||||
CSSPoint startPosition = mFrameMetrics.GetScrollOffset();
|
||||
// If we're already in a wheel scroll or smooth scroll animation,
|
||||
// the delta is applied to its destination, not to the current
|
||||
// scroll position. Take this into account when finding a snap point.
|
||||
if (mState == WHEEL_SCROLL) {
|
||||
startPosition = mAnimation->AsWheelScrollAnimation()->GetDestination();
|
||||
} else if (mState == SMOOTH_SCROLL) {
|
||||
startPosition = mAnimation->AsSmoothScrollAnimation()->GetDestination();
|
||||
}
|
||||
if (MaybeAdjustDeltaForScrollSnapping(aEvent, delta, startPosition)) {
|
||||
// If we're scroll snapping, use a smooth scroll animation to get
|
||||
// the desired physics. Note that SmoothScrollTo() will re-use an
|
||||
// existing smooth scroll animation if there is one.
|
||||
SmoothScrollTo(startPosition);
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, use a wheel scroll animation, also reusing one if possible.
|
||||
if (mState != WHEEL_SCROLL) {
|
||||
CancelAnimation();
|
||||
SetState(WHEEL_SCROLL);
|
||||
@@ -2815,7 +2871,6 @@ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort(
|
||||
|
||||
CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels();
|
||||
CSSPoint velocity = aVelocity / aFrameMetrics.GetZoom();
|
||||
CSSPoint scrollOffset = aFrameMetrics.GetScrollOffset();
|
||||
CSSRect scrollableRect = aFrameMetrics.GetExpandedScrollableRect();
|
||||
|
||||
// Calculate the displayport size based on how fast we're moving along each axis.
|
||||
@@ -2825,18 +2880,22 @@ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort(
|
||||
RedistributeDisplayPortExcess(displayPortSize, scrollableRect);
|
||||
}
|
||||
|
||||
// We calculate a "displayport" here which is relative to the scroll offset.
|
||||
// Note that the scroll offset we have here in the APZ code may not be the
|
||||
// same as the base rect that gets used on the layout side when the displayport
|
||||
// margins are actually applied, so it is important to only consider the
|
||||
// displayport as margins relative to a scroll offset rather than relative to
|
||||
// something more unchanging like the scrollable rect origin.
|
||||
|
||||
// Center the displayport based on its expansion over the composition size.
|
||||
CSSRect displayPort((compositionSize.width - displayPortSize.width) / 2.0f,
|
||||
(compositionSize.height - displayPortSize.height) / 2.0f,
|
||||
displayPortSize.width, displayPortSize.height);
|
||||
|
||||
// Offset the displayport, depending on how fast we're moving and the
|
||||
// estimated time it takes to paint, to try to minimise checkerboarding.
|
||||
float paintFactor = kDefaultEstimatedPaintDurationMs;
|
||||
CSSRect displayPort = CSSRect(scrollOffset + (velocity * paintFactor * gfxPrefs::APZVelocityBias()),
|
||||
displayPortSize);
|
||||
|
||||
// Re-center the displayport based on its expansion over the composition size.
|
||||
displayPort.MoveBy((compositionSize.width - displayPort.width)/2.0f,
|
||||
(compositionSize.height - displayPort.height)/2.0f);
|
||||
|
||||
// Make sure the displayport remains within the scrollable rect.
|
||||
displayPort = displayPort.MoveInsideAndClamp(scrollableRect) - scrollOffset;
|
||||
displayPort.MoveBy(velocity * paintFactor * gfxPrefs::APZVelocityBias());
|
||||
|
||||
APZC_LOG_FM(aFrameMetrics,
|
||||
"Calculated displayport as (%f %f %f %f) from velocity %s paint time %f metrics",
|
||||
@@ -3001,7 +3060,7 @@ AsyncPanZoomController::RequestContentRepaint(const FrameMetrics& aFrameMetrics,
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
|
||||
Vector<Task*>* aOutDeferredTasks)
|
||||
nsTArray<Task*>* aOutDeferredTasks)
|
||||
{
|
||||
APZThreadUtils::AssertOnCompositorThread();
|
||||
|
||||
@@ -3035,8 +3094,15 @@ bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
|
||||
return false;
|
||||
}
|
||||
|
||||
AsyncTransformComponentMatrix AsyncPanZoomController::GetOverscrollTransform() const {
|
||||
AsyncTransformComponentMatrix
|
||||
AsyncPanZoomController::GetOverscrollTransform(AsyncMode aMode) const
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
if (aMode == RESPECT_FORCE_DISABLE && mFrameMetrics.IsApzForceDisabled()) {
|
||||
return AsyncTransformComponentMatrix();
|
||||
}
|
||||
|
||||
if (!IsOverscrolled()) {
|
||||
return AsyncTransformComponentMatrix();
|
||||
}
|
||||
@@ -3095,7 +3161,7 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
|
||||
// responsibility to schedule a composite.
|
||||
mAsyncTransformAppliedToContent = false;
|
||||
bool requestAnimationFrame = false;
|
||||
Vector<Task*> deferredTasks;
|
||||
nsTArray<Task*> deferredTasks;
|
||||
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
@@ -3117,7 +3183,7 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
|
||||
// UpdateAnimation()). This needs to be done after the monitor is released
|
||||
// since the tasks are allowed to call APZCTreeManager methods which can grab
|
||||
// the tree lock.
|
||||
for (uint32_t i = 0; i < deferredTasks.length(); ++i) {
|
||||
for (uint32_t i = 0; i < deferredTasks.Length(); ++i) {
|
||||
deferredTasks[i]->Run();
|
||||
delete deferredTasks[i];
|
||||
}
|
||||
@@ -3129,18 +3195,28 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
|
||||
return requestAnimationFrame;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SampleContentTransformForFrame(AsyncTransform* aOutTransform,
|
||||
ParentLayerPoint& aScrollOffset)
|
||||
ParentLayerPoint
|
||||
AsyncPanZoomController::GetCurrentAsyncScrollOffset(AsyncMode aMode) const
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
aScrollOffset = mFrameMetrics.GetScrollOffset() * mFrameMetrics.GetZoom();
|
||||
*aOutTransform = GetCurrentAsyncTransform();
|
||||
if (aMode == RESPECT_FORCE_DISABLE && mFrameMetrics.IsApzForceDisabled()) {
|
||||
return mLastContentPaintMetrics.GetScrollOffset() * mLastContentPaintMetrics.GetZoom();
|
||||
}
|
||||
|
||||
return (mFrameMetrics.GetScrollOffset() + mTestAsyncScrollOffset)
|
||||
* mFrameMetrics.GetZoom() * mTestAsyncZoom.scale;
|
||||
}
|
||||
|
||||
AsyncTransform AsyncPanZoomController::GetCurrentAsyncTransform() const {
|
||||
AsyncTransform
|
||||
AsyncPanZoomController::GetCurrentAsyncTransform(AsyncMode aMode) const
|
||||
{
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
if (aMode == RESPECT_FORCE_DISABLE && mFrameMetrics.IsApzForceDisabled()) {
|
||||
return AsyncTransform();
|
||||
}
|
||||
|
||||
CSSPoint lastPaintScrollOffset;
|
||||
if (mLastContentPaintMetrics.IsScrollable()) {
|
||||
lastPaintScrollOffset = mLastContentPaintMetrics.GetScrollOffset();
|
||||
@@ -3175,9 +3251,11 @@ AsyncTransform AsyncPanZoomController::GetCurrentAsyncTransform() const {
|
||||
-translation);
|
||||
}
|
||||
|
||||
AsyncTransformComponentMatrix AsyncPanZoomController::GetCurrentAsyncTransformWithOverscroll() const {
|
||||
return AsyncTransformComponentMatrix(GetCurrentAsyncTransform())
|
||||
* GetOverscrollTransform();
|
||||
AsyncTransformComponentMatrix
|
||||
AsyncPanZoomController::GetCurrentAsyncTransformWithOverscroll(AsyncMode aMode) const
|
||||
{
|
||||
return AsyncTransformComponentMatrix(GetCurrentAsyncTransform(aMode))
|
||||
* GetOverscrollTransform(aMode);
|
||||
}
|
||||
|
||||
Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const {
|
||||
@@ -3879,13 +3957,14 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics() {
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
|
||||
Maybe<CSSPoint> AsyncPanZoomController::FindSnapPointNear(
|
||||
const CSSPoint& aDestination, nsIScrollableFrame::ScrollUnit aUnit) {
|
||||
mMonitor.AssertCurrentThreadIn();
|
||||
APZC_LOG("%p scroll snapping near %s\n", this, Stringify(aDestination).c_str());
|
||||
CSSRect scrollRange = mFrameMetrics.CalculateScrollRange();
|
||||
if (Maybe<nsPoint> snapPoint = ScrollSnapUtils::GetSnapPointForDestination(
|
||||
mScrollMetadata.GetSnapInfo(),
|
||||
nsIScrollableFrame::DEVICE_PIXELS,
|
||||
aUnit,
|
||||
CSSSize::ToAppUnits(mFrameMetrics.CalculateCompositedSizeInCssPixels()),
|
||||
CSSRect::ToAppUnits(scrollRange),
|
||||
CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset()),
|
||||
@@ -3895,8 +3974,17 @@ void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
|
||||
// of the scroll frame's scroll range. Clamp it here (this matches the
|
||||
// behaviour of the main-thread code path, which clamps it in
|
||||
// nsGfxScrollFrame::ScrollTo()).
|
||||
cssSnapPoint = scrollRange.ClampPoint(cssSnapPoint);
|
||||
SmoothScrollTo(cssSnapPoint);
|
||||
return Some(scrollRange.ClampPoint(cssSnapPoint));
|
||||
}
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::ScrollSnapNear(const CSSPoint& aDestination) {
|
||||
if (Maybe<CSSPoint> snapPoint =
|
||||
FindSnapPointNear(aDestination, nsIScrollableFrame::DEVICE_PIXELS)) {
|
||||
if (*snapPoint != mFrameMetrics.GetScrollOffset()) {
|
||||
SmoothScrollTo(*snapPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3938,5 +4026,31 @@ void AsyncPanZoomController::ScrollSnapToDestination() {
|
||||
}
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::MaybeAdjustDeltaForScrollSnapping(
|
||||
const ScrollWheelInput& aEvent,
|
||||
ParentLayerPoint& aDelta,
|
||||
CSSPoint& aStartPosition)
|
||||
{
|
||||
// Don't scroll snap for pixel scrolls. This matches the main thread
|
||||
// behaviour in EventStateManager::DoScrollText().
|
||||
if (aEvent.mDeltaType == ScrollWheelInput::SCROLLDELTA_PIXEL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
CSSToParentLayerScale2D zoom = mFrameMetrics.GetZoom();
|
||||
CSSPoint destination = mFrameMetrics.CalculateScrollRange().ClampPoint(
|
||||
aStartPosition + (aDelta / zoom));
|
||||
nsIScrollableFrame::ScrollUnit unit =
|
||||
ScrollWheelInput::ScrollUnitForDeltaType(aEvent.mDeltaType);
|
||||
|
||||
if (Maybe<CSSPoint> snapPoint = FindSnapPointNear(destination, unit)) {
|
||||
aDelta = (*snapPoint - aStartPosition) * zoom;
|
||||
aStartPosition = *snapPoint;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include "Layers.h" // for Layer::ScrollDirection
|
||||
#include "LayersTypes.h"
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsTArray.h"
|
||||
#include "PotentialCheckerboardDurationTracker.h"
|
||||
|
||||
#include "base/message_loop.h"
|
||||
@@ -160,22 +162,7 @@ public:
|
||||
bool AdvanceAnimations(const TimeStamp& aSampleTime);
|
||||
|
||||
bool UpdateAnimation(const TimeStamp& aSampleTime,
|
||||
Vector<Task*>* aOutDeferredTasks);
|
||||
|
||||
/**
|
||||
* Query the transforms that should be applied to the layer corresponding
|
||||
* to this APZC due to asynchronous panning and zooming.
|
||||
* This function returns the async transform via the |aOutTransform|
|
||||
* out parameter.
|
||||
*/
|
||||
void SampleContentTransformForFrame(AsyncTransform* aOutTransform,
|
||||
ParentLayerPoint& aScrollOffset);
|
||||
|
||||
/**
|
||||
* Return a visual effect that reflects this apzc's
|
||||
* overscrolled state, if any.
|
||||
*/
|
||||
AsyncTransformComponentMatrix GetOverscrollTransform() const;
|
||||
nsTArray<Task*>* aOutDeferredTasks);
|
||||
|
||||
/**
|
||||
* A shadow layer update has arrived. |aScrollMetdata| is the new ScrollMetadata
|
||||
@@ -215,20 +202,6 @@ public:
|
||||
*/
|
||||
bool IsDestroyed() const;
|
||||
|
||||
/**
|
||||
* Returns the incremental transformation corresponding to the async pan/zoom
|
||||
* in progress. That is, when this transform is multiplied with the layer's
|
||||
* existing transform, it will make the layer appear with the desired pan/zoom
|
||||
* amount.
|
||||
*/
|
||||
AsyncTransform GetCurrentAsyncTransform() const;
|
||||
|
||||
/**
|
||||
* Returns the same transform as GetCurrentAsyncTransform(), but includes
|
||||
* any transform due to axis over-scroll.
|
||||
*/
|
||||
AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll() const;
|
||||
|
||||
/**
|
||||
* Returns the transform to take something from the coordinate space of the
|
||||
* last thing we know gecko painted, to the coordinate space of the last thing
|
||||
@@ -285,6 +258,14 @@ public:
|
||||
*/
|
||||
nsEventStatus HandleGestureEvent(const InputData& aEvent);
|
||||
|
||||
/**
|
||||
* Handler for touch velocity.
|
||||
* Sometimes the touch move event will have a velocity even though no scrolling
|
||||
* is occurring such as when the toolbar is being hidden/shown in Fennec.
|
||||
* This function can be called to have the y axis' velocity queue updated.
|
||||
*/
|
||||
void HandleTouchVelocity(uint32_t aTimesampMs, float aSpeedY);
|
||||
|
||||
/**
|
||||
* Populates the provided object (if non-null) with the scrollable guid of this apzc.
|
||||
*/
|
||||
@@ -636,15 +617,6 @@ protected:
|
||||
// Common processing at the end of a touch block.
|
||||
void OnTouchEndOrCancel();
|
||||
|
||||
// Snap to a snap position nearby the current scroll position, if appropriate.
|
||||
void ScrollSnap();
|
||||
// Snap to a snap position nearby the destination predicted based on the
|
||||
// current velocity, if appropriate.
|
||||
void ScrollSnapToDestination();
|
||||
|
||||
// Helper function for ScrollSnap() and ScrollSnapToDestination().
|
||||
void ScrollSnapNear(const CSSPoint& aDestination);
|
||||
|
||||
uint64_t mLayersId;
|
||||
RefPtr<CompositorBridgeParent> mCompositorBridgeParent;
|
||||
|
||||
@@ -730,6 +702,52 @@ private:
|
||||
friend class Axis;
|
||||
|
||||
|
||||
/* ===================================================================
|
||||
* The functions and members in this section are used to expose
|
||||
* the current async transform state to callers.
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* Allows callers to specify which type of async transform they want:
|
||||
* NORMAL provides the actual async transforms of the APZC, whereas
|
||||
* RESPECT_FORCE_DISABLE will provide empty async transforms if and only if
|
||||
* the metrics has the mForceDisableApz flag set. In general the latter should
|
||||
* only be used by call sites that are applying the transform to update
|
||||
* a layer's position.
|
||||
*/
|
||||
enum AsyncMode {
|
||||
NORMAL,
|
||||
RESPECT_FORCE_DISABLE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Query the transforms that should be applied to the layer corresponding
|
||||
* to this APZC due to asynchronous panning and zooming.
|
||||
* This function returns the async transform via the |aOutTransform|
|
||||
* out parameter.
|
||||
*/
|
||||
ParentLayerPoint GetCurrentAsyncScrollOffset(AsyncMode aMode) const;
|
||||
|
||||
/**
|
||||
* Return a visual effect that reflects this apzc's
|
||||
* overscrolled state, if any.
|
||||
*/
|
||||
AsyncTransformComponentMatrix GetOverscrollTransform(AsyncMode aMode) const;
|
||||
|
||||
/**
|
||||
* Returns the incremental transformation corresponding to the async pan/zoom
|
||||
* in progress. That is, when this transform is multiplied with the layer's
|
||||
* existing transform, it will make the layer appear with the desired pan/zoom
|
||||
* amount.
|
||||
*/
|
||||
AsyncTransform GetCurrentAsyncTransform(AsyncMode aMode) const;
|
||||
|
||||
/**
|
||||
* Returns the same transform as GetCurrentAsyncTransform(), but includes
|
||||
* any transform due to axis over-scroll.
|
||||
*/
|
||||
AsyncTransformComponentMatrix GetCurrentAsyncTransformWithOverscroll(AsyncMode aMode) const;
|
||||
|
||||
|
||||
/* ===================================================================
|
||||
* The functions and members in this section are used to manage
|
||||
@@ -1099,9 +1117,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// Extra offset to add in SampleContentTransformForFrame for testing
|
||||
// Extra offset to add to the async scroll position for testing
|
||||
CSSPoint mTestAsyncScrollOffset;
|
||||
// Extra zoom to include in SampleContentTransformForFrame for testing
|
||||
// Extra zoom to include in the aync zoom for testing
|
||||
LayerToParentLayerScale mTestAsyncZoom;
|
||||
// Flag to track whether or not the APZ transform is not used. This
|
||||
// flag is recomputed for every composition frame.
|
||||
@@ -1123,6 +1141,39 @@ private:
|
||||
// be checkerboarding. Combined with other info, this allows us to meaningfully
|
||||
// say how frequently users actually encounter checkerboarding.
|
||||
PotentialCheckerboardDurationTracker mPotentialCheckerboardTracker;
|
||||
|
||||
|
||||
/* ===================================================================
|
||||
* The functions in this section are used for CSS scroll snapping.
|
||||
*/
|
||||
|
||||
// If |aEvent| should trigger scroll snapping, adjust |aDelta| to reflect
|
||||
// the snapping (that is, make it a delta that will take us to the desired
|
||||
// snap point). The delta is interpreted as being relative to
|
||||
// |aStartPosition|, and if a target snap point is found, |aStartPosition|
|
||||
// is also updated, to the value of the snap point.
|
||||
// Returns true iff. a target snap point was found.
|
||||
bool MaybeAdjustDeltaForScrollSnapping(const ScrollWheelInput& aEvent,
|
||||
ParentLayerPoint& aDelta,
|
||||
CSSPoint& aStartPosition);
|
||||
|
||||
// Snap to a snap position nearby the current scroll position, if appropriate.
|
||||
void ScrollSnap();
|
||||
|
||||
// Snap to a snap position nearby the destination predicted based on the
|
||||
// current velocity, if appropriate.
|
||||
void ScrollSnapToDestination();
|
||||
|
||||
// Snap to a snap position nearby the provided destination, if appropriate.
|
||||
void ScrollSnapNear(const CSSPoint& aDestination);
|
||||
|
||||
// Find a snap point near |aDestination| that we should snap to.
|
||||
// Returns the snap point if one was found, or an empty Maybe otherwise.
|
||||
// |aUnit| affects the snapping behaviour (see ScrollSnapUtils::
|
||||
// GetSnapPointForDestination). It should generally be determined by the
|
||||
// type of event that's triggering the scroll.
|
||||
Maybe<CSSPoint> FindSnapPointNear(const CSSPoint& aDestination,
|
||||
nsIScrollableFrame::ScrollUnit aUnit);
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
||||
+52
-17
@@ -30,6 +30,13 @@
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
// When we compute the velocity we do so by taking two input events and
|
||||
// dividing the distance delta over the time delta. In some cases the time
|
||||
// delta can be really small, which can make the velocity computation very
|
||||
// volatile. To avoid this we impose a minimum time delta below which we do
|
||||
// not recompute the velocity.
|
||||
const uint32_t MIN_VELOCITY_SAMPLE_TIME_MS = 5;
|
||||
|
||||
bool FuzzyEqualsCoordinate(float aValue1, float aValue2)
|
||||
{
|
||||
return FuzzyEqualsAdditive(aValue1, aValue2, COORDINATE_EPSILON)
|
||||
@@ -40,7 +47,8 @@ extern StaticAutoPtr<ComputedTimingFunction> gVelocityCurveFunction;
|
||||
|
||||
Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController)
|
||||
: mPos(0),
|
||||
mPosTimeMs(0),
|
||||
mVelocitySampleTimeMs(0),
|
||||
mVelocitySamplePos(0),
|
||||
mVelocity(0.0f),
|
||||
mAxisLocked(false),
|
||||
mAsyncPanZoomController(aAsyncPanZoomController),
|
||||
@@ -67,16 +75,35 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord
|
||||
// mVelocityQueue is controller-thread only
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
|
||||
if (aTimestampMs == mPosTimeMs) {
|
||||
// This could be a duplicate event, or it could be a legitimate event
|
||||
// on some platforms that generate events really fast. As a compromise
|
||||
// update mPos so we don't run into problems like bug 1042734, even though
|
||||
// that means the velocity will be stale. Better than doing a divide-by-zero.
|
||||
if (aTimestampMs <= mVelocitySampleTimeMs + MIN_VELOCITY_SAMPLE_TIME_MS) {
|
||||
// See also the comment on MIN_VELOCITY_SAMPLE_TIME_MS.
|
||||
// We still update mPos so that the positioning is correct (and we don't run
|
||||
// into problems like bug 1042734) but the velocity will remain where it was.
|
||||
// In particular we don't update either mVelocitySampleTimeMs or
|
||||
// mVelocitySamplePos so that eventually when we do get an event with the
|
||||
// required time delta we use the corresponding distance delta as well.
|
||||
AXIS_LOG("%p|%s skipping velocity computation for small time delta %dms\n",
|
||||
mAsyncPanZoomController, Name(), (aTimestampMs - mVelocitySampleTimeMs));
|
||||
mPos = aPos;
|
||||
return;
|
||||
}
|
||||
|
||||
float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mPosTimeMs);
|
||||
float newVelocity = mAxisLocked ? 0.0f : (float)(mVelocitySamplePos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mVelocitySampleTimeMs);
|
||||
|
||||
newVelocity = ApplyFlingCurveToVelocity(newVelocity);
|
||||
|
||||
AXIS_LOG("%p|%s updating velocity to %f with touch\n",
|
||||
mAsyncPanZoomController, Name(), newVelocity);
|
||||
mVelocity = newVelocity;
|
||||
mPos = aPos;
|
||||
mVelocitySampleTimeMs = aTimestampMs;
|
||||
mVelocitySamplePos = aPos;
|
||||
|
||||
AddVelocityToQueue(aTimestampMs, mVelocity);
|
||||
}
|
||||
|
||||
float Axis::ApplyFlingCurveToVelocity(float aVelocity) const {
|
||||
float newVelocity = aVelocity;
|
||||
if (gfxPrefs::APZMaxVelocity() > 0.0f) {
|
||||
bool velocityIsNegative = (newVelocity < 0);
|
||||
newVelocity = fabs(newVelocity);
|
||||
@@ -105,23 +132,31 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord
|
||||
}
|
||||
}
|
||||
|
||||
AXIS_LOG("%p|%s updating velocity to %f with touch\n",
|
||||
mAsyncPanZoomController, Name(), newVelocity);
|
||||
mVelocity = newVelocity;
|
||||
mPos = aPos;
|
||||
mPosTimeMs = aTimestampMs;
|
||||
return newVelocity;
|
||||
}
|
||||
|
||||
// Limit queue size pased on pref
|
||||
mVelocityQueue.AppendElement(std::make_pair(aTimestampMs, mVelocity));
|
||||
void Axis::AddVelocityToQueue(uint32_t aTimestampMs, float aVelocity) {
|
||||
mVelocityQueue.AppendElement(std::make_pair(aTimestampMs, aVelocity));
|
||||
if (mVelocityQueue.Length() > gfxPrefs::APZMaxVelocityQueueSize()) {
|
||||
mVelocityQueue.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Axis::HandleTouchVelocity(uint32_t aTimestampMs, float aSpeed) {
|
||||
// mVelocityQueue is controller-thread only
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
|
||||
mVelocity = ApplyFlingCurveToVelocity(aSpeed);
|
||||
mVelocitySampleTimeMs = aTimestampMs;
|
||||
|
||||
AddVelocityToQueue(aTimestampMs, mVelocity);
|
||||
}
|
||||
|
||||
void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) {
|
||||
mStartPos = aPos;
|
||||
mPos = aPos;
|
||||
mPosTimeMs = aTimestampMs;
|
||||
mVelocitySampleTimeMs = aTimestampMs;
|
||||
mVelocitySamplePos = aPos;
|
||||
mAxisLocked = false;
|
||||
}
|
||||
|
||||
@@ -424,7 +459,7 @@ bool Axis::CanScroll(ParentLayerCoord aDelta) const
|
||||
return false;
|
||||
}
|
||||
|
||||
return DisplacementWillOverscrollAmount(aDelta) != aDelta;
|
||||
return fabs(DisplacementWillOverscrollAmount(aDelta) - aDelta) > COORDINATE_EPSILON;
|
||||
}
|
||||
|
||||
CSSCoord Axis::ClampOriginToScrollableRect(CSSCoord aOrigin) const
|
||||
@@ -438,7 +473,7 @@ CSSCoord Axis::ClampOriginToScrollableRect(CSSCoord aOrigin) const
|
||||
} else if (origin + GetCompositionLength() > GetPageEnd()) {
|
||||
result = GetPageEnd() - GetCompositionLength();
|
||||
} else {
|
||||
result = origin;
|
||||
return aOrigin;
|
||||
}
|
||||
|
||||
return result / zoom;
|
||||
|
||||
@@ -49,6 +49,13 @@ public:
|
||||
*/
|
||||
void UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, ParentLayerCoord aAdditionalDelta, uint32_t aTimestampMs);
|
||||
|
||||
protected:
|
||||
float ApplyFlingCurveToVelocity(float aVelocity) const;
|
||||
void AddVelocityToQueue(uint32_t aTimestampMs, float aVelocity);
|
||||
|
||||
public:
|
||||
void HandleTouchVelocity(uint32_t aTimestampMs, float aSpeed);
|
||||
|
||||
/**
|
||||
* Notify this Axis that a touch has begun, i.e. the user has put their finger
|
||||
* on the screen but has not yet tried to pan.
|
||||
@@ -251,7 +258,14 @@ public:
|
||||
|
||||
protected:
|
||||
ParentLayerCoord mPos;
|
||||
uint32_t mPosTimeMs;
|
||||
|
||||
// mVelocitySampleTimeMs and mVelocitySamplePos are the time and position
|
||||
// used in the last velocity sampling. They get updated when a new sample is
|
||||
// taken (which may not happen on every input event, if the time delta is too
|
||||
// small).
|
||||
uint32_t mVelocitySampleTimeMs;
|
||||
ParentLayerCoord mVelocitySamplePos;
|
||||
|
||||
ParentLayerCoord mStartPos;
|
||||
float mVelocity; // Units: ParentLayerCoords per millisecond
|
||||
bool mAxisLocked; // Whether movement on this axis is locked.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "InputData.h" // for MultiTouchInput, etc
|
||||
#include "Units.h"
|
||||
#include "mozilla/EventForwards.h" // for nsEventStatus
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ HitTestingTreeNode::HitTestingTreeNode(AsyncPanZoomController* aApzc,
|
||||
, mScrollViewId(FrameMetrics::NULL_SCROLL_ID)
|
||||
, mScrollDir(Layer::NONE)
|
||||
, mScrollSize(0)
|
||||
, mIsScrollbarContainer(false)
|
||||
, mOverride(EventRegionsOverride::NoOverride)
|
||||
{
|
||||
if (mIsPrimaryApzcHolder) {
|
||||
@@ -92,11 +93,15 @@ HitTestingTreeNode::SetLastChild(HitTestingTreeNode* aChild)
|
||||
}
|
||||
|
||||
void
|
||||
HitTestingTreeNode::SetScrollbarData(FrameMetrics::ViewID aScrollViewId, Layer::ScrollDirection aDir, int32_t aScrollSize)
|
||||
HitTestingTreeNode::SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
|
||||
Layer::ScrollDirection aDir,
|
||||
int32_t aScrollSize,
|
||||
bool aIsScrollContainer)
|
||||
{
|
||||
mScrollViewId = aScrollViewId;
|
||||
mScrollDir = aDir;
|
||||
mScrollSize = aScrollSize;;
|
||||
mIsScrollbarContainer = aIsScrollContainer;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -118,7 +123,7 @@ HitTestingTreeNode::GetScrollSize() const
|
||||
bool
|
||||
HitTestingTreeNode::IsScrollbarNode() const
|
||||
{
|
||||
return (mScrollDir != Layer::NONE);
|
||||
return mIsScrollbarContainer || (mScrollDir != Layer::NONE);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -241,7 +246,7 @@ HitTestingTreeNode::Untransform(const ParentLayerPoint& aPoint) const
|
||||
LayerToParentLayerMatrix4x4 transform = mTransform *
|
||||
CompleteAsyncTransform(
|
||||
mApzc
|
||||
? mApzc->GetCurrentAsyncTransformWithOverscroll()
|
||||
? mApzc->GetCurrentAsyncTransformWithOverscroll(AsyncPanZoomController::NORMAL)
|
||||
: AsyncTransformComponentMatrix());
|
||||
return UntransformBy(transform.Inverse(), aPoint);
|
||||
}
|
||||
|
||||
@@ -92,7 +92,10 @@ public:
|
||||
|
||||
/* Scrollbar info */
|
||||
|
||||
void SetScrollbarData(FrameMetrics::ViewID aScrollViewId, Layer::ScrollDirection aDir, int32_t aScrollSize);
|
||||
void SetScrollbarData(FrameMetrics::ViewID aScrollViewId,
|
||||
Layer::ScrollDirection aDir,
|
||||
int32_t aScrollSize,
|
||||
bool aIsScrollContainer);
|
||||
bool MatchesScrollDragMetrics(const AsyncDragMetrics& aDragMetrics) const;
|
||||
int32_t GetScrollSize() const;
|
||||
bool IsScrollbarNode() const;
|
||||
@@ -124,6 +127,7 @@ private:
|
||||
FrameMetrics::ViewID mScrollViewId;
|
||||
Layer::ScrollDirection mScrollDir;
|
||||
int32_t mScrollSize;
|
||||
bool mIsScrollbarContainer;
|
||||
|
||||
/* Let {L,M} be the {layer, scrollable metrics} pair that this node
|
||||
* corresponds to in the layer tree. mEventRegions contains the event regions
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "gfxPrefs.h" // for gfxPrefs
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/SizePrintfMacros.h" // for PRIuSIZE
|
||||
#include "mozilla/Telemetry.h" // for Telemetry
|
||||
#include "mozilla/layers/APZCTreeManager.h" // for AllowedTouchBehavior
|
||||
#include "OverscrollHandoffState.h"
|
||||
|
||||
@@ -153,6 +154,13 @@ CancelableBlockState::SetContentResponse(bool aPreventDefault)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CancelableBlockState::StartContentResponseTimer()
|
||||
{
|
||||
MOZ_ASSERT(mContentResponseTimer.IsNull());
|
||||
mContentResponseTimer = TimeStamp::Now();
|
||||
}
|
||||
|
||||
bool
|
||||
CancelableBlockState::TimeoutContentResponse()
|
||||
{
|
||||
@@ -181,6 +189,12 @@ CancelableBlockState::IsDefaultPrevented() const
|
||||
return mPreventDefault;
|
||||
}
|
||||
|
||||
bool
|
||||
CancelableBlockState::HasReceivedAllContentNotifications() const
|
||||
{
|
||||
return IsTargetConfirmed() && mContentResponded;
|
||||
}
|
||||
|
||||
bool
|
||||
CancelableBlockState::IsReadyForHandling() const
|
||||
{
|
||||
@@ -204,6 +218,26 @@ CancelableBlockState::DispatchEvent(const InputData& aEvent) const
|
||||
GetTargetApzc()->HandleInputEvent(aEvent, mTransformToApzc);
|
||||
}
|
||||
|
||||
void
|
||||
CancelableBlockState::RecordContentResponseTime()
|
||||
{
|
||||
if (!mContentResponseTimer) {
|
||||
// We might get responses from content even though we didn't wait for them.
|
||||
// In that case, ignore the time on them, because they're not relevant for
|
||||
// tuning our timeout value. Also this function might get called multiple
|
||||
// times on the same input block, so we should only record the time from the
|
||||
// first successful call.
|
||||
return;
|
||||
}
|
||||
if (!HasReceivedAllContentNotifications()) {
|
||||
// Not done yet, we'll get called again
|
||||
return;
|
||||
}
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::CONTENT_RESPONSE_DURATION,
|
||||
(uint32_t)(TimeStamp::Now() - mContentResponseTimer).ToMilliseconds());
|
||||
mContentResponseTimer = TimeStamp();
|
||||
}
|
||||
|
||||
DragBlockState::DragBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed,
|
||||
const MouseInput& aInitialEvent)
|
||||
@@ -385,15 +419,6 @@ WheelBlockState::AddEvent(const ScrollWheelInput& aEvent)
|
||||
mEvents.AppendElement(aEvent);
|
||||
}
|
||||
|
||||
bool
|
||||
WheelBlockState::IsReadyForHandling() const
|
||||
{
|
||||
if (!CancelableBlockState::IsReadyForHandling()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
WheelBlockState::HasEvents() const
|
||||
{
|
||||
@@ -654,6 +679,13 @@ PanGestureBlockState::SetContentResponse(bool aPreventDefault)
|
||||
return stateChanged;
|
||||
}
|
||||
|
||||
bool
|
||||
PanGestureBlockState::HasReceivedAllContentNotifications() const
|
||||
{
|
||||
return CancelableBlockState::HasReceivedAllContentNotifications()
|
||||
&& !mWaitingForContentResponse;
|
||||
}
|
||||
|
||||
bool
|
||||
PanGestureBlockState::IsReadyForHandling() const
|
||||
{
|
||||
@@ -721,6 +753,13 @@ TouchBlockState::CopyPropertiesFrom(const TouchBlockState& aOther)
|
||||
mTransformToApzc = aOther.mTransformToApzc;
|
||||
}
|
||||
|
||||
bool
|
||||
TouchBlockState::HasReceivedAllContentNotifications() const
|
||||
{
|
||||
return CancelableBlockState::HasReceivedAllContentNotifications()
|
||||
&& (!gfxPrefs::TouchActionEnabled() || mAllowedTouchBehaviorSet);
|
||||
}
|
||||
|
||||
bool
|
||||
TouchBlockState::IsReadyForHandling() const
|
||||
{
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
#define mozilla_layers_InputBlockState_h
|
||||
|
||||
#include "InputData.h" // for MultiTouchInput
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "mozilla/gfx/Matrix.h" // for Matrix4x4
|
||||
#include "mozilla/layers/APZUtils.h" // for TouchBehaviorFlags
|
||||
#include "mozilla/layers/AsyncDragMetrics.h"
|
||||
#include "nsAutoPtr.h" // for nsRefPtr
|
||||
#include "mozilla/TimeStamp.h" // for TimeStamp
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "TouchCounter.h"
|
||||
|
||||
@@ -121,6 +122,20 @@ public:
|
||||
*/
|
||||
virtual bool SetContentResponse(bool aPreventDefault);
|
||||
|
||||
/**
|
||||
* This should be called when this block is starting to wait for the
|
||||
* necessary content response notifications. It is used to gather data
|
||||
* on how long the content response notifications take.
|
||||
*/
|
||||
void StartContentResponseTimer();
|
||||
|
||||
/**
|
||||
* This should be called when a content response notification has been
|
||||
* delivered to this block. If all the notifications have arrived, this
|
||||
* will report the total time take to telemetry.
|
||||
*/
|
||||
void RecordContentResponseTime();
|
||||
|
||||
/**
|
||||
* Record that content didn't respond in time.
|
||||
* @return false if this block already timed out, true if not.
|
||||
@@ -150,6 +165,12 @@ public:
|
||||
*/
|
||||
virtual void DispatchEvent(const InputData& aEvent) const;
|
||||
|
||||
/**
|
||||
* @return true iff this block has received all the information it could
|
||||
* have gotten from the content thread.
|
||||
*/
|
||||
virtual bool HasReceivedAllContentNotifications() const;
|
||||
|
||||
/**
|
||||
* @return true iff this block has received all the information needed
|
||||
* to properly dispatch the events in the block.
|
||||
@@ -184,6 +205,7 @@ public:
|
||||
virtual const char* Type() = 0;
|
||||
|
||||
private:
|
||||
TimeStamp mContentResponseTimer;
|
||||
bool mPreventDefault;
|
||||
bool mContentResponded;
|
||||
bool mContentResponseTimerExpired;
|
||||
@@ -200,7 +222,6 @@ public:
|
||||
const ScrollWheelInput& aEvent);
|
||||
|
||||
bool SetContentResponse(bool aPreventDefault) override;
|
||||
bool IsReadyForHandling() const override;
|
||||
bool HasEvents() const override;
|
||||
void DropEvents() override;
|
||||
void HandleEvents() override;
|
||||
@@ -320,6 +341,7 @@ public:
|
||||
const PanGestureInput& aEvent);
|
||||
|
||||
bool SetContentResponse(bool aPreventDefault) override;
|
||||
bool HasReceivedAllContentNotifications() const override;
|
||||
bool IsReadyForHandling() const override;
|
||||
bool HasEvents() const override;
|
||||
void DropEvents() override;
|
||||
@@ -398,6 +420,12 @@ public:
|
||||
*/
|
||||
void CopyPropertiesFrom(const TouchBlockState& aOther);
|
||||
|
||||
/*
|
||||
* @return true iff this block has received all the information it could
|
||||
* have gotten from the content thread.
|
||||
*/
|
||||
bool HasReceivedAllContentNotifications() const override;
|
||||
|
||||
/**
|
||||
* @return true iff this block has received all the information needed
|
||||
* to properly dispatch the events in the block.
|
||||
|
||||
@@ -423,7 +423,7 @@ InputQueue::MaybeRequestContentResponse(const RefPtr<AsyncPanZoomController>& aT
|
||||
// need to wait to give content the opportunity to prevent-default the
|
||||
// touch events. Either way we schedule a timeout so the main thread stuff
|
||||
// can run.
|
||||
ScheduleMainThreadTimeout(aTarget, aBlock->GetBlockId());
|
||||
ScheduleMainThreadTimeout(aTarget, aBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ InputQueue::InjectNewTouchBlock(AsyncPanZoomController* aTarget)
|
||||
/* aCopyPropertiesFromCurrent = */ true);
|
||||
INPQ_LOG("injecting new touch block %p with id %" PRIu64 " and target %p\n",
|
||||
block, block->GetBlockId(), aTarget);
|
||||
ScheduleMainThreadTimeout(aTarget, block->GetBlockId());
|
||||
ScheduleMainThreadTimeout(aTarget, block);
|
||||
return block->GetBlockId();
|
||||
}
|
||||
|
||||
@@ -562,10 +562,12 @@ InputQueue::IsDragOnScrollbar(bool aHitScrollbar)
|
||||
}
|
||||
|
||||
void
|
||||
InputQueue::ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget, uint64_t aInputBlockId) {
|
||||
InputQueue::ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
CancelableBlockState* aBlock) {
|
||||
INPQ_LOG("scheduling main thread timeout for target %p\n", aTarget.get());
|
||||
aBlock->StartContentResponseTimer();
|
||||
aTarget->PostDelayedTask(
|
||||
NewRunnableMethod(this, &InputQueue::MainThreadTimeout, aInputBlockId),
|
||||
NewRunnableMethod(this, &InputQueue::MainThreadTimeout, aBlock->GetBlockId()),
|
||||
gfxPrefs::APZContentResponseTimeout());
|
||||
}
|
||||
|
||||
@@ -597,9 +599,10 @@ InputQueue::ContentReceivedInputBlock(uint64_t aInputBlockId, bool aPreventDefau
|
||||
INPQ_LOG("got a content response; block=%" PRIu64 "\n", aInputBlockId);
|
||||
bool success = false;
|
||||
for (size_t i = 0; i < mInputBlockQueue.Length(); i++) {
|
||||
if (mInputBlockQueue[i]->GetBlockId() == aInputBlockId) {
|
||||
CancelableBlockState* block = mInputBlockQueue[i].get();
|
||||
CancelableBlockState* block = mInputBlockQueue[i].get();
|
||||
if (block->GetBlockId() == aInputBlockId) {
|
||||
success = block->SetContentResponse(aPreventDefault);
|
||||
block->RecordContentResponseTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -616,8 +619,10 @@ InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const RefPtr<AsyncPan
|
||||
aInputBlockId, aTargetApzc ? Stringify(aTargetApzc->GetGuid()).c_str() : "");
|
||||
bool success = false;
|
||||
for (size_t i = 0; i < mInputBlockQueue.Length(); i++) {
|
||||
if (mInputBlockQueue[i]->GetBlockId() == aInputBlockId) {
|
||||
success = mInputBlockQueue[i]->SetConfirmedTargetApzc(aTargetApzc);
|
||||
CancelableBlockState* block = mInputBlockQueue[i].get();
|
||||
if (block->GetBlockId() == aInputBlockId) {
|
||||
success = block->SetConfirmedTargetApzc(aTargetApzc);
|
||||
block->RecordContentResponseTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -640,6 +645,7 @@ InputQueue::ConfirmDragBlock(uint64_t aInputBlockId, const RefPtr<AsyncPanZoomCo
|
||||
if (block && block->GetBlockId() == aInputBlockId) {
|
||||
block->SetDragMetrics(aDragMetrics);
|
||||
success = block->SetConfirmedTargetApzc(aTargetApzc);
|
||||
block->RecordContentResponseTime();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -659,6 +665,7 @@ InputQueue::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray<Touch
|
||||
TouchBlockState *block = mInputBlockQueue[i]->AsTouchBlock();
|
||||
if (block) {
|
||||
success = block->SetAllowedTouchBehaviors(aBehaviors);
|
||||
block->RecordContentResponseTime();
|
||||
} else {
|
||||
NS_WARNING("input block is not a touch block");
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#include "DragTracker.h"
|
||||
#include "InputData.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "TouchCounter.h"
|
||||
|
||||
@@ -175,7 +175,8 @@ private:
|
||||
bool MaybeHandleCurrentBlock(CancelableBlockState* block,
|
||||
const InputData& aEvent);
|
||||
|
||||
void ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget, uint64_t aInputBlockId);
|
||||
void ScheduleMainThreadTimeout(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
CancelableBlockState* aBlock);
|
||||
void MainThreadTimeout(const uint64_t& aInputBlockId);
|
||||
void ProcessInputBlocks();
|
||||
void UpdateActiveApzc(const RefPtr<AsyncPanZoomController>& aNewActive);
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#define mozilla_layers_OverscrollHandoffChain_h
|
||||
|
||||
#include <vector>
|
||||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/RefPtr.h" // for RefPtr
|
||||
#include "nsISupportsImpl.h" // for NS_INLINE_DECL_THREADSAFE_REFCOUNTING
|
||||
#include "APZCTreeManager.h"
|
||||
#include "APZUtils.h" // for CancelAnimationFlags
|
||||
|
||||
@@ -34,6 +34,10 @@ public:
|
||||
return this;
|
||||
}
|
||||
|
||||
CSSPoint GetDestination() const {
|
||||
return CSSPoint::FromAppUnits(mFinalDestination);
|
||||
}
|
||||
|
||||
private:
|
||||
void InitPreferences(TimeStamp aTime);
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ protected:
|
||||
|
||||
// Trigger computation of the overscroll tranform, to make sure
|
||||
// no assetions fire during the calculation.
|
||||
apzc->GetOverscrollTransform();
|
||||
apzc->GetOverscrollTransform(AsyncPanZoomController::NORMAL);
|
||||
|
||||
if (!apzc->IsOverscrolled()) {
|
||||
recoveredFromOverscroll = true;
|
||||
|
||||
@@ -247,8 +247,10 @@ public:
|
||||
const TimeDuration& aIncrement = TimeDuration::FromMilliseconds(0)) {
|
||||
mcc->AdvanceBy(aIncrement);
|
||||
bool ret = AdvanceAnimations(mcc->Time());
|
||||
AsyncPanZoomController::SampleContentTransformForFrame(
|
||||
aOutTransform, aScrollOffset);
|
||||
if (aOutTransform) {
|
||||
*aOutTransform = GetCurrentAsyncTransform(AsyncPanZoomController::NORMAL);
|
||||
}
|
||||
aScrollOffset = GetCurrentAsyncScrollOffset(AsyncPanZoomController::NORMAL);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -162,6 +162,8 @@ TEST_F(APZHitTestingTester, HitTesting1) {
|
||||
|
||||
// A more involved hit testing test that involves css and async transforms.
|
||||
TEST_F(APZHitTestingTester, HitTesting2) {
|
||||
SCOPED_GFX_PREF(APZVelocityBias, float, 0.0); // Velocity bias can cause extra repaint requests
|
||||
|
||||
CreateHitTesting2LayerTree();
|
||||
ScopedLayerTreeRegistration registration(manager, 0, root, mcc);
|
||||
|
||||
|
||||
@@ -80,6 +80,7 @@ protected:
|
||||
|
||||
TEST_F(APZCPanningTester, Pan) {
|
||||
SCOPED_GFX_PREF(TouchActionEnabled, bool, false);
|
||||
SCOPED_GFX_PREF(APZVelocityBias, float, 0.0); // Velocity bias can cause extra repaint requests
|
||||
DoPanTest(true, true, mozilla::layers::AllowedTouchBehavior::NONE);
|
||||
}
|
||||
|
||||
@@ -93,22 +94,26 @@ TEST_F(APZCPanningTester, Pan) {
|
||||
// events.
|
||||
TEST_F(APZCPanningTester, PanWithTouchActionAuto) {
|
||||
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
||||
SCOPED_GFX_PREF(APZVelocityBias, float, 0.0); // Velocity bias can cause extra repaint requests
|
||||
DoPanTest(true, true, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN
|
||||
| mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
|
||||
}
|
||||
|
||||
TEST_F(APZCPanningTester, PanWithTouchActionNone) {
|
||||
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
||||
SCOPED_GFX_PREF(APZVelocityBias, float, 0.0); // Velocity bias can cause extra repaint requests
|
||||
DoPanTest(false, false, 0);
|
||||
}
|
||||
|
||||
TEST_F(APZCPanningTester, PanWithTouchActionPanX) {
|
||||
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
||||
SCOPED_GFX_PREF(APZVelocityBias, float, 0.0); // Velocity bias can cause extra repaint requests
|
||||
DoPanTest(false, true, mozilla::layers::AllowedTouchBehavior::HORIZONTAL_PAN);
|
||||
}
|
||||
|
||||
TEST_F(APZCPanningTester, PanWithTouchActionPanY) {
|
||||
SCOPED_GFX_PREF(TouchActionEnabled, bool, true);
|
||||
SCOPED_GFX_PREF(APZVelocityBias, float, 0.0); // Velocity bias can cause extra repaint requests
|
||||
DoPanTest(true, true, mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,13 +49,6 @@
|
||||
#include "mozilla/layers/GrallocTextureClient.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
# include "gfxReusableImageSurfaceWrapper.h"
|
||||
#else
|
||||
# include "gfxReusableSharedImageSurfaceWrapper.h"
|
||||
# include "gfxSharedImageSurface.h"
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
|
||||
#else
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "TextureClientPool.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION
|
||||
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
|
||||
#include "gfxReusableSharedImageSurfaceWrapper.h"
|
||||
#include "nsExpirationTracker.h" // for nsExpirationTracker
|
||||
#include "nsMathUtils.h" // for NS_lroundf
|
||||
#include "LayersLogging.h"
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
|
||||
#include "nsExpirationTracker.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "gfxReusableSurfaceWrapper.h"
|
||||
#include "pratom.h" // For PR_ATOMIC_INCREMENT/DECREMENT
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
@@ -845,11 +845,10 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
|
||||
|
||||
hasAsyncTransform = true;
|
||||
|
||||
AsyncTransform asyncTransformWithoutOverscroll;
|
||||
ParentLayerPoint scrollOffset;
|
||||
controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll,
|
||||
scrollOffset);
|
||||
AsyncTransformComponentMatrix overscrollTransform = controller->GetOverscrollTransform();
|
||||
AsyncTransform asyncTransformWithoutOverscroll =
|
||||
controller->GetCurrentAsyncTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
AsyncTransformComponentMatrix overscrollTransform =
|
||||
controller->GetOverscrollTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
AsyncTransformComponentMatrix asyncTransform =
|
||||
AsyncTransformComponentMatrix(asyncTransformWithoutOverscroll)
|
||||
* overscrollTransform;
|
||||
@@ -882,6 +881,8 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer,
|
||||
geckoZoom,
|
||||
mContentRect);
|
||||
} else {
|
||||
ParentLayerPoint scrollOffset = controller->GetCurrentAsyncScrollOffset(
|
||||
AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
// Compute the painted displayport in document-relative CSS pixels.
|
||||
CSSRect displayPort(metrics.GetCriticalDisplayPort().IsEmpty() ?
|
||||
metrics.GetDisplayPort() :
|
||||
@@ -1032,7 +1033,8 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
const FrameMetrics& metrics = aContent.Metrics();
|
||||
AsyncPanZoomController* apzc = aContent.GetApzc();
|
||||
|
||||
AsyncTransformComponentMatrix asyncTransform = apzc->GetCurrentAsyncTransform();
|
||||
AsyncTransformComponentMatrix asyncTransform =
|
||||
apzc->GetCurrentAsyncTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
|
||||
// |asyncTransform| represents the amount by which we have scrolled and
|
||||
// zoomed since the last paint. Because the scrollbar was sized and positioned based
|
||||
@@ -1147,7 +1149,9 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
|
||||
// the same coordinate space. This requires applying the content transform
|
||||
// and then unapplying it after unapplying the async transform.
|
||||
if (aScrollbarIsDescendant) {
|
||||
Matrix4x4 asyncUntransform = (asyncTransform * apzc->GetOverscrollTransform()).Inverse().ToUnknownMatrix();
|
||||
AsyncTransformComponentMatrix overscroll =
|
||||
apzc->GetOverscrollTransform(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
Matrix4x4 asyncUntransform = (asyncTransform * overscroll).Inverse().ToUnknownMatrix();
|
||||
Matrix4x4 contentTransform = aContent.GetTransform();
|
||||
Matrix4x4 contentUntransform = contentTransform.Inverse();
|
||||
|
||||
|
||||
@@ -472,10 +472,7 @@ RenderMinimap(ContainerT* aContainer, LayerManagerComposite* aManager,
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncTransform asyncTransformWithoutOverscroll;
|
||||
ParentLayerPoint scrollOffset;
|
||||
controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll,
|
||||
scrollOffset);
|
||||
ParentLayerPoint scrollOffset = controller->GetCurrentAsyncScrollOffset(AsyncPanZoomController::RESPECT_FORCE_DISABLE);
|
||||
|
||||
// Options
|
||||
const int verticalPadding = 10;
|
||||
@@ -659,8 +656,9 @@ RenderLayers(ContainerT* aContainer,
|
||||
gfx::Rect(aClipRect.ToUnknownRect()),
|
||||
asyncTransform * aContainer->GetEffectiveTransform());
|
||||
if (AsyncPanZoomController* apzc = layer->GetAsyncPanZoomController(i - 1)) {
|
||||
asyncTransform = apzc->GetCurrentAsyncTransformWithOverscroll().ToUnknownMatrix()
|
||||
* asyncTransform;
|
||||
asyncTransform =
|
||||
apzc->GetCurrentAsyncTransformWithOverscroll(AsyncPanZoomController::RESPECT_FORCE_DISABLE).ToUnknownMatrix()
|
||||
* asyncTransform;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -809,7 +807,7 @@ ContainerRender(ContainerT* aContainer,
|
||||
for (LayerMetricsWrapper i(aContainer); i; i = i.GetFirstChild()) {
|
||||
if (AsyncPanZoomController* apzc = i.GetApzc()) {
|
||||
if (!apzc->GetAsyncTransformAppliedToContent()
|
||||
&& !AsyncTransformComponentMatrix(apzc->GetCurrentAsyncTransform()).IsIdentity()) {
|
||||
&& !AsyncTransformComponentMatrix(apzc->GetCurrentAsyncTransform(AsyncPanZoomController::NORMAL)).IsIdentity()) {
|
||||
aManager->UnusedApzTransformWarning();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
#include "mozilla/layers/TiledContentClient.h"
|
||||
#include "gfxPrefs.h"
|
||||
|
||||
class gfxReusableSurfaceWrapper;
|
||||
|
||||
namespace mozilla {
|
||||
using namespace gfx;
|
||||
namespace layers {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "GLUploadHelpers.h"
|
||||
#include "GLReadTexImageHelper.h"
|
||||
#include "gfx2DGlue.h" // for ContentForFormat, etc
|
||||
#include "gfxReusableSurfaceWrapper.h" // for gfxReusableSurfaceWrapper
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Logging.h" // for gfxCriticalError
|
||||
|
||||
@@ -251,7 +251,7 @@ nsDeviceContext::IsPrinterSurface()
|
||||
}
|
||||
|
||||
void
|
||||
nsDeviceContext::SetDPI()
|
||||
nsDeviceContext::SetDPI(double* aScale)
|
||||
{
|
||||
float dpi = -1.0f;
|
||||
|
||||
@@ -280,9 +280,21 @@ nsDeviceContext::SetDPI()
|
||||
dpi = 96.0f;
|
||||
}
|
||||
|
||||
CSSToLayoutDeviceScale scale = mWidget ? mWidget->GetDefaultScale()
|
||||
: CSSToLayoutDeviceScale(1.0);
|
||||
double devPixelsPerCSSPixel = scale.scale;
|
||||
double devPixelsPerCSSPixel;
|
||||
if (aScale && *aScale > 0.0) {
|
||||
// if caller provided a scale, we just use it
|
||||
devPixelsPerCSSPixel = *aScale;
|
||||
} else {
|
||||
// otherwise get from the widget, and return it in aScale for
|
||||
// the caller to pass to child contexts if needed
|
||||
CSSToLayoutDeviceScale scale =
|
||||
mWidget ? mWidget->GetDefaultScale()
|
||||
: CSSToLayoutDeviceScale(1.0);
|
||||
devPixelsPerCSSPixel = scale.scale;
|
||||
if (aScale) {
|
||||
*aScale = devPixelsPerCSSPixel;
|
||||
}
|
||||
}
|
||||
|
||||
mAppUnitsPerDevPixelAtUnitFullZoom =
|
||||
std::max(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel));
|
||||
@@ -637,11 +649,12 @@ nsDeviceContext::CalcPrintingSize()
|
||||
return (mWidth > 0 && mHeight > 0);
|
||||
}
|
||||
|
||||
bool nsDeviceContext::CheckDPIChange() {
|
||||
bool nsDeviceContext::CheckDPIChange(double* aScale)
|
||||
{
|
||||
int32_t oldDevPixels = mAppUnitsPerDevPixelAtUnitFullZoom;
|
||||
int32_t oldInches = mAppUnitsPerPhysicalInch;
|
||||
|
||||
SetDPI();
|
||||
SetDPI(aScale);
|
||||
|
||||
return oldDevPixels != mAppUnitsPerDevPixelAtUnitFullZoom ||
|
||||
oldInches != mAppUnitsPerPhysicalInch;
|
||||
|
||||
@@ -219,12 +219,18 @@ public:
|
||||
nsresult EndPage();
|
||||
|
||||
/**
|
||||
* Check to see if the DPI has changed
|
||||
* Check to see if the DPI has changed, or impose a new DPI scale value.
|
||||
* @param aScale - If non-null, the default (unzoomed) CSS to device pixel
|
||||
* scale factor will be returned here; and if it is > 0.0
|
||||
* on input, the given value will be used instead of
|
||||
* getting it from the widget (if any). This is used to
|
||||
* allow subdocument contexts to inherit the resolution
|
||||
* setting of their parent.
|
||||
* @return whether there was actually a change in the DPI (whether
|
||||
* AppUnitsPerDevPixel() or AppUnitsPerPhysicalInch()
|
||||
* changed)
|
||||
*/
|
||||
bool CheckDPIChange();
|
||||
bool CheckDPIChange(double* aScale = nullptr);
|
||||
|
||||
/**
|
||||
* Set the full zoom factor: all lengths are multiplied by this factor
|
||||
@@ -249,7 +255,7 @@ private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~nsDeviceContext();
|
||||
|
||||
void SetDPI();
|
||||
void SetDPI(double* aScale = nullptr);
|
||||
void ComputeClientRectUsingScreen(nsRect *outRect);
|
||||
void ComputeFullAreaUsingScreen(nsRect *outRect);
|
||||
void FindScreen(nsIScreen **outScreen);
|
||||
|
||||
@@ -36,7 +36,6 @@ template <typename Base, typename Sub>
|
||||
class gfxBaseSharedMemorySurface : public Base {
|
||||
typedef mozilla::ipc::SharedMemory SharedMemory;
|
||||
typedef mozilla::ipc::Shmem Shmem;
|
||||
friend class gfxReusableSharedImageSurfaceWrapper;
|
||||
|
||||
protected:
|
||||
virtual ~gfxBaseSharedMemorySurface()
|
||||
|
||||
@@ -1081,6 +1081,9 @@ gfxContext::EnsurePathBuilder()
|
||||
Matrix toNewUS = mPathTransform * invTransform;
|
||||
|
||||
RefPtr<Path> path = mPathBuilder->Finish();
|
||||
if (!path) {
|
||||
gfxCriticalError() << "gfxContext::EnsurePathBuilder failed in PathBuilder::Finish";
|
||||
}
|
||||
mPathBuilder = path->TransformedCopyToBuilder(toNewUS);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
|
||||
static mozilla::Atomic<uint64_t> sNextFontFileKey;
|
||||
static std::unordered_map<uint64_t, IDWriteFontFileStream*> sFontFileStreams;
|
||||
@@ -158,6 +159,10 @@ gfxDWriteFontFileLoader::CreateCustomFontFile(FallibleTArray<uint8_t>& aFontData
|
||||
MOZ_ASSERT(aFontFileStream);
|
||||
|
||||
IDWriteFactory *factory = gfxWindowsPlatform::GetPlatform()->GetDWriteFactory();
|
||||
if (!factory) {
|
||||
gfxCriticalError() << "Failed to get DWrite Factory in CreateCustomFontFile.";
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
uint64_t fontFileKey = sNextFontFileKey++;
|
||||
RefPtr<IDWriteFontFileStream> ffsRef = new gfxDWriteFontFileStream(&aFontData, fontFileKey);
|
||||
|
||||
@@ -48,6 +48,10 @@ public:
|
||||
// Disabling the crash guard in DriverCrashGuard
|
||||
DECL_GFX_ENV_ONCE("MOZ_DISABLE_CRASH_GUARD", DisableCrashGuard);
|
||||
|
||||
// We force present to work around some Windows bugs - disable that if this
|
||||
// environment variable is set.
|
||||
DECL_GFX_ENV_ONCE("MOZ_DISABLE_FORCE_PRESENT", DisableForcePresent);
|
||||
|
||||
// Together with paint dumping, only when MOZ_DUMP_PAINTING is defined.
|
||||
// Dumping compositor textures is broken pretty badly. For example,
|
||||
// on Linux it crashes TextureHost::GetAsSurface() returns null.
|
||||
|
||||
@@ -325,7 +325,7 @@ GDIFontEntry::TestCharacterMap(uint32_t aCh)
|
||||
HFONT hfont = font->GetHFONT();
|
||||
HFONT oldFont = (HFONT)SelectObject(dc, hfont);
|
||||
|
||||
wchar_t str[1] = { aCh };
|
||||
wchar_t str[1] = { (wchar_t)aCh };
|
||||
WORD glyph[1];
|
||||
|
||||
bool hasGlyph = false;
|
||||
|
||||
@@ -350,13 +350,8 @@ gfxPlatformGtk::GetDPIScale()
|
||||
bool
|
||||
gfxPlatformGtk::UseImageOffscreenSurfaces()
|
||||
{
|
||||
// We want to turn on image offscreen surfaces ONLY for GTK3 builds since
|
||||
// GTK2 theme rendering still requires xlib surfaces.
|
||||
#if (MOZ_WIDGET_GTK == 3)
|
||||
return gfxPrefs::UseImageOffscreenSurfaces();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return GetDefaultContentBackend() != mozilla::gfx::BackendType::CAIRO ||
|
||||
gfxPrefs::UseImageOffscreenSurfaces();
|
||||
}
|
||||
|
||||
gfxImageFormat
|
||||
|
||||
@@ -100,10 +100,6 @@ public:
|
||||
|
||||
bool UseXRender() {
|
||||
#if defined(MOZ_X11)
|
||||
if (GetDefaultContentBackend() != mozilla::gfx::BackendType::NONE &&
|
||||
GetDefaultContentBackend() != mozilla::gfx::BackendType::CAIRO)
|
||||
return false;
|
||||
|
||||
return sUseXRender;
|
||||
#else
|
||||
return false;
|
||||
|
||||
@@ -437,6 +437,7 @@ private:
|
||||
DECL_GFX_PREF(Live, "webgl.disable-angle", WebGLDisableANGLE, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.disable-extensions", WebGLDisableExtensions, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.dxgl.enabled", WebGLDXGLEnabled, bool, false);
|
||||
DECL_GFX_PREF(Live, "webgl.dxgl.needs-finish", WebGLDXGLNeedsFinish, bool, false);
|
||||
|
||||
DECL_GFX_PREF(Live, "webgl.disable-fail-if-major-performance-caveat",
|
||||
WebGLDisableFailIfMajorPerformanceCaveat, bool, false);
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "gfxReusableImageSurfaceWrapper.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
||||
gfxReusableImageSurfaceWrapper::gfxReusableImageSurfaceWrapper(gfxImageSurface* aSurface)
|
||||
: mSurface(aSurface)
|
||||
{
|
||||
MOZ_COUNT_CTOR(gfxReusableImageSurfaceWrapper);
|
||||
}
|
||||
|
||||
gfxReusableImageSurfaceWrapper::~gfxReusableImageSurfaceWrapper()
|
||||
{
|
||||
MOZ_COUNT_DTOR(gfxReusableImageSurfaceWrapper);
|
||||
}
|
||||
|
||||
void
|
||||
gfxReusableImageSurfaceWrapper::ReadLock()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(gfxReusableImageSurfaceWrapper);
|
||||
AddRef();
|
||||
}
|
||||
|
||||
void
|
||||
gfxReusableImageSurfaceWrapper::ReadUnlock()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
gfxReusableSurfaceWrapper*
|
||||
gfxReusableImageSurfaceWrapper::GetWritable(gfxImageSurface** aSurface)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(gfxReusableImageSurfaceWrapper);
|
||||
|
||||
if (mRefCnt == 1) {
|
||||
*aSurface = mSurface;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Something else is reading the surface, copy it
|
||||
gfxImageSurface* copySurface = new gfxImageSurface(mSurface->GetSize(), mSurface->Format(), false);
|
||||
copySurface->CopyFrom(mSurface);
|
||||
*aSurface = copySurface;
|
||||
|
||||
return new gfxReusableImageSurfaceWrapper(copySurface);
|
||||
}
|
||||
|
||||
const unsigned char*
|
||||
gfxReusableImageSurfaceWrapper::GetReadOnlyData() const
|
||||
{
|
||||
return mSurface->Data();
|
||||
}
|
||||
|
||||
gfxImageFormat
|
||||
gfxReusableImageSurfaceWrapper::Format()
|
||||
{
|
||||
return mSurface->Format();
|
||||
}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
#ifndef GFXMEMCOWSURFACEWRAPPER
|
||||
#define GFXMEMCOWSURFACEWRAPPER
|
||||
|
||||
#include "gfxReusableSurfaceWrapper.h"
|
||||
|
||||
class gfxImageSurface;
|
||||
|
||||
/**
|
||||
* A cross-thread capable implementation of gfxReusableSurfaceWrapper based
|
||||
* on gfxImageSurface.
|
||||
*/
|
||||
class gfxReusableImageSurfaceWrapper : public gfxReusableSurfaceWrapper {
|
||||
public:
|
||||
explicit gfxReusableImageSurfaceWrapper(gfxImageSurface* aSurface);
|
||||
protected:
|
||||
~gfxReusableImageSurfaceWrapper();
|
||||
|
||||
public:
|
||||
const unsigned char* GetReadOnlyData() const override;
|
||||
gfxImageFormat Format() override;
|
||||
gfxReusableSurfaceWrapper* GetWritable(gfxImageSurface** aSurface) override;
|
||||
void ReadLock() override;
|
||||
void ReadUnlock() override;
|
||||
|
||||
Type GetType() override
|
||||
{
|
||||
return TYPE_IMAGE;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<gfxImageSurface> mSurface;
|
||||
};
|
||||
|
||||
#endif // GFXMEMCOWSURFACEWRAPPER
|
||||
@@ -1,98 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "gfxReusableSharedImageSurfaceWrapper.h"
|
||||
#include "gfxSharedImageSurface.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
|
||||
using mozilla::ipc::Shmem;
|
||||
using mozilla::layers::ISurfaceAllocator;
|
||||
|
||||
gfxReusableSharedImageSurfaceWrapper::gfxReusableSharedImageSurfaceWrapper(ISurfaceAllocator* aAllocator,
|
||||
gfxSharedImageSurface* aSurface)
|
||||
: mAllocator(aAllocator)
|
||||
, mSurface(aSurface)
|
||||
{
|
||||
MOZ_COUNT_CTOR(gfxReusableSharedImageSurfaceWrapper);
|
||||
ReadLock();
|
||||
}
|
||||
|
||||
gfxReusableSharedImageSurfaceWrapper::~gfxReusableSharedImageSurfaceWrapper()
|
||||
{
|
||||
MOZ_COUNT_DTOR(gfxReusableSharedImageSurfaceWrapper);
|
||||
ReadUnlock();
|
||||
}
|
||||
|
||||
void
|
||||
gfxReusableSharedImageSurfaceWrapper::ReadLock()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(gfxReusableSharedImageSurfaceWrapper);
|
||||
mSurface->ReadLock();
|
||||
}
|
||||
|
||||
void
|
||||
gfxReusableSharedImageSurfaceWrapper::ReadUnlock()
|
||||
{
|
||||
int32_t readCount = mSurface->ReadUnlock();
|
||||
MOZ_ASSERT(readCount >= 0, "Read count should not be negative");
|
||||
|
||||
if (readCount == 0) {
|
||||
mAllocator->AsShmemAllocator()->DeallocShmem(mSurface->GetShmem());
|
||||
}
|
||||
}
|
||||
|
||||
gfxReusableSurfaceWrapper*
|
||||
gfxReusableSharedImageSurfaceWrapper::GetWritable(gfxImageSurface** aSurface)
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(gfxReusableSharedImageSurfaceWrapper);
|
||||
|
||||
int32_t readCount = mSurface->GetReadCount();
|
||||
MOZ_ASSERT(readCount > 0, "A ReadLock must be held when calling GetWritable");
|
||||
if (readCount == 1) {
|
||||
*aSurface = mSurface;
|
||||
return this;
|
||||
}
|
||||
|
||||
// Something else is reading the surface, copy it
|
||||
RefPtr<gfxSharedImageSurface> copySurface =
|
||||
gfxSharedImageSurface::CreateUnsafe(mAllocator->AsShmemAllocator(), mSurface->GetSize(), mSurface->Format());
|
||||
copySurface->CopyFrom(mSurface);
|
||||
*aSurface = copySurface;
|
||||
|
||||
// We need to create a new wrapper since this wrapper has an external ReadLock
|
||||
gfxReusableSurfaceWrapper* wrapper = new gfxReusableSharedImageSurfaceWrapper(mAllocator, copySurface);
|
||||
|
||||
// No need to release the ReadLock on the surface, this will happen when
|
||||
// the wrapper is destroyed.
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
const unsigned char*
|
||||
gfxReusableSharedImageSurfaceWrapper::GetReadOnlyData() const
|
||||
{
|
||||
MOZ_ASSERT(mSurface->GetReadCount() > 0, "Should have read lock");
|
||||
return mSurface->Data();
|
||||
}
|
||||
|
||||
gfxImageFormat
|
||||
gfxReusableSharedImageSurfaceWrapper::Format()
|
||||
{
|
||||
return mSurface->Format();
|
||||
}
|
||||
|
||||
Shmem&
|
||||
gfxReusableSharedImageSurfaceWrapper::GetShmem()
|
||||
{
|
||||
return mSurface->GetShmem();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<gfxReusableSharedImageSurfaceWrapper>
|
||||
gfxReusableSharedImageSurfaceWrapper::Open(ISurfaceAllocator* aAllocator, const Shmem& aShmem)
|
||||
{
|
||||
RefPtr<gfxSharedImageSurface> sharedImage = gfxSharedImageSurface::Open(aShmem);
|
||||
RefPtr<gfxReusableSharedImageSurfaceWrapper> wrapper = new gfxReusableSharedImageSurfaceWrapper(aAllocator, sharedImage);
|
||||
wrapper->ReadUnlock();
|
||||
return wrapper.forget();
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
#ifndef GFXSHMCOWSURFACEWRAPPER
|
||||
#define GFXSHMCOWSURFACEWRAPPER
|
||||
|
||||
#include "gfxReusableSurfaceWrapper.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
class gfxSharedImageSurface;
|
||||
|
||||
namespace mozilla {
|
||||
namespace ipc {
|
||||
class Shmem;
|
||||
} // namespace ipc
|
||||
namespace layers {
|
||||
class ISurfaceAllocator;
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* A cross-process capable implementation of gfxReusableSurfaceWrapper based
|
||||
* on gfxSharedImageSurface.
|
||||
*/
|
||||
class gfxReusableSharedImageSurfaceWrapper : public gfxReusableSurfaceWrapper {
|
||||
public:
|
||||
gfxReusableSharedImageSurfaceWrapper(mozilla::layers::ISurfaceAllocator* aAllocator,
|
||||
gfxSharedImageSurface* aSurface);
|
||||
protected:
|
||||
~gfxReusableSharedImageSurfaceWrapper();
|
||||
|
||||
public:
|
||||
const unsigned char* GetReadOnlyData() const override;
|
||||
gfxImageFormat Format() override;
|
||||
gfxReusableSurfaceWrapper* GetWritable(gfxImageSurface** aSurface) override;
|
||||
void ReadLock() override;
|
||||
void ReadUnlock() override;
|
||||
|
||||
Type GetType() override
|
||||
{
|
||||
return TYPE_SHARED_IMAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shared memory segment that backs the shared image surface.
|
||||
*/
|
||||
mozilla::ipc::Shmem& GetShmem();
|
||||
|
||||
/**
|
||||
* Create a gfxReusableSurfaceWrapper from the shared memory segment of a
|
||||
* gfxSharedImageSurface. A ReadLock must be held, which will be adopted by
|
||||
* the returned gfxReusableSurfaceWrapper.
|
||||
*/
|
||||
static already_AddRefed<gfxReusableSharedImageSurfaceWrapper>
|
||||
Open(mozilla::layers::ISurfaceAllocator* aAllocator, const mozilla::ipc::Shmem& aShmem);
|
||||
|
||||
private:
|
||||
RefPtr<mozilla::layers::ISurfaceAllocator> mAllocator;
|
||||
RefPtr<gfxSharedImageSurface> mSurface;
|
||||
};
|
||||
|
||||
#endif // GFXSHMCOWSURFACEWRAPPER
|
||||
@@ -1,88 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
#ifndef GFXCOWSURFACEWRAPPER
|
||||
#define GFXCOWSURFACEWRAPPER
|
||||
|
||||
#include "gfxImageSurface.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
|
||||
/**
|
||||
* Provides an interface to implement a cross thread/process wrapper for a
|
||||
* gfxImageSurface that has copy-on-write semantics.
|
||||
*
|
||||
* Only the owner thread can write to the surface and acquire
|
||||
* read locks. Destroying a gfxReusableSurfaceWrapper releases
|
||||
* a read lock.
|
||||
*
|
||||
* OMTC Usage:
|
||||
* 1) Content creates a writable copy of this surface
|
||||
* wrapper which will be optimized to the same wrapper if there
|
||||
* are no readers.
|
||||
* 2) The surface is sent from content to the compositor once
|
||||
* or potentially many times, each increasing a read lock.
|
||||
* 3) When the compositor receives the surface, it adopts the
|
||||
* read lock.
|
||||
* 4) Once the compositor has processed the surface and uploaded
|
||||
* the content, it then releases the read lock by dereferencing
|
||||
* its wrapper.
|
||||
*/
|
||||
class gfxReusableSurfaceWrapper {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxReusableSurfaceWrapper)
|
||||
public:
|
||||
|
||||
/**
|
||||
* Returns a read-only pointer to the image data.
|
||||
*/
|
||||
virtual const unsigned char* GetReadOnlyData() const = 0;
|
||||
|
||||
/**
|
||||
* Returns the image surface format.
|
||||
*/
|
||||
virtual gfxImageFormat Format() = 0;
|
||||
|
||||
/**
|
||||
* Returns a writable copy of the image.
|
||||
* If necessary this will copy the wrapper. If there are no contention
|
||||
* the same wrapper will be returned. A ReadLock must be held when
|
||||
* calling this function, and calling it will give up this lock.
|
||||
*/
|
||||
virtual gfxReusableSurfaceWrapper* GetWritable(gfxImageSurface** aSurface) = 0;
|
||||
|
||||
/**
|
||||
* A read only lock count is recorded, any attempts to
|
||||
* call GetWritable() while this count is greater than one will
|
||||
* create a new surface/wrapper pair.
|
||||
*
|
||||
* When a surface's read count falls to zero, its memory will be
|
||||
* deallocated. It is the responsibility of the user to make sure
|
||||
* that all locks are matched with an equal number of unlocks.
|
||||
*/
|
||||
virtual void ReadLock() = 0;
|
||||
virtual void ReadUnlock() = 0;
|
||||
|
||||
/**
|
||||
* Types for each implementation of gfxReusableSurfaceWrapper.
|
||||
*/
|
||||
enum Type {
|
||||
TYPE_SHARED_IMAGE,
|
||||
TYPE_IMAGE,
|
||||
|
||||
TYPE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a unique ID for each implementation of gfxReusableSurfaceWrapper.
|
||||
*/
|
||||
virtual Type GetType() = 0;
|
||||
|
||||
protected:
|
||||
// Protected destructor, to discourage deletion outside of Release():
|
||||
virtual ~gfxReusableSurfaceWrapper() {}
|
||||
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
#endif // GFXCOWSURFACEWRAPPER
|
||||
@@ -537,11 +537,7 @@ gfxXlibNativeRenderer::Draw(gfxContext* ctx, IntSize size,
|
||||
gfxPoint deviceTranslation = gfxPoint(dtTransform._31, dtTransform._32);
|
||||
cairo_t* cairo = static_cast<cairo_t*>
|
||||
(drawTarget->GetNativeSurface(NativeSurfaceType::CAIRO_CONTEXT));
|
||||
if (!cairo) {
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_surface_t* cairoTarget = cairo_get_group_target(cairo);
|
||||
cairo_surface_t* cairoTarget = cairo ? cairo_get_group_target(cairo) : nullptr;
|
||||
cairo_surface_t* tempXlibSurface =
|
||||
CreateTempXlibSurface(cairoTarget, drawTarget, size,
|
||||
canDrawOverBackground, flags, screen, visual,
|
||||
|
||||
@@ -38,9 +38,6 @@ EXPORTS += [
|
||||
'gfxQuad.h',
|
||||
'gfxQuaternion.h',
|
||||
'gfxRect.h',
|
||||
'gfxReusableImageSurfaceWrapper.h',
|
||||
'gfxReusableSharedImageSurfaceWrapper.h',
|
||||
'gfxReusableSurfaceWrapper.h',
|
||||
'gfxSharedImageSurface.h',
|
||||
'gfxSharedQuartzSurface.h',
|
||||
'gfxSkipChars.h',
|
||||
@@ -232,8 +229,6 @@ UNIFIED_SOURCES += [
|
||||
'gfxPattern.cpp',
|
||||
'gfxPlatformFontList.cpp',
|
||||
'gfxRect.cpp',
|
||||
'gfxReusableImageSurfaceWrapper.cpp',
|
||||
'gfxReusableSharedImageSurfaceWrapper.cpp',
|
||||
'gfxScriptItemizer.cpp',
|
||||
'gfxSkipChars.cpp',
|
||||
'gfxSVGGlyphs.cpp',
|
||||
@@ -271,6 +266,7 @@ FINAL_LIBRARY = 'xul'
|
||||
GENERATED_FILES = [
|
||||
'DeprecatedPremultiplyTables.h',
|
||||
]
|
||||
GENERATED_FILES['DeprecatedPremultiplyTables.h'].script = 'genTables.py:generate'
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/workers',
|
||||
@@ -312,5 +308,9 @@ if CONFIG['CLANG_CXX']:
|
||||
# Suppress warnings from Skia header files.
|
||||
SOURCES['gfxPlatform.cpp'].flags += ['-Wno-implicit-fallthrough']
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
# This is intended as a temporary hack to support building with VS2015.
|
||||
CXXFLAGS += ['-wd4577']
|
||||
|
||||
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
|
||||
DEFINES['OTS_DLL'] = True
|
||||
|
||||
Vendored
-1
@@ -8,7 +8,6 @@ builtin(include, ../../build/autoconf/acwinpaths.m4)dnl
|
||||
builtin(include, ../../build/autoconf/hooks.m4)dnl
|
||||
builtin(include, ../../build/autoconf/config.status.m4)dnl
|
||||
builtin(include, ../../build/autoconf/toolchain.m4)dnl
|
||||
builtin(include, ../../build/autoconf/wrapper.m4)dnl
|
||||
builtin(include, ../../build/autoconf/pkg.m4)dnl
|
||||
builtin(include, ../../build/autoconf/nspr.m4)dnl
|
||||
builtin(include, ../../build/autoconf/nspr-build.m4)dnl
|
||||
|
||||
@@ -44,7 +44,7 @@ static const JSPropertySpec promise_static_properties[] = {
|
||||
PromiseObject*
|
||||
PromiseObject::create(JSContext* cx, HandleObject executor, HandleObject proto /* = nullptr */)
|
||||
{
|
||||
MOZ_ASSERT(IsCallable(executor));
|
||||
MOZ_ASSERT(executor->isCallable());
|
||||
|
||||
RootedObject usedProto(cx, proto);
|
||||
bool wrappedProto = false;
|
||||
|
||||
@@ -11,3 +11,42 @@ function mismatchError(actual, expect) {
|
||||
var str = `type mismatch: expression has type ${actual} but expected ${expect}`;
|
||||
return RegExp(str);
|
||||
}
|
||||
|
||||
function hasI64() {
|
||||
return getBuildConfiguration().x64;
|
||||
}
|
||||
|
||||
// Assert that the expected value is equal to the int64 value, as passed by
|
||||
// Baldr with --wasm-extra-tests {low: int32, high: int32}.
|
||||
// - if the expected value is in the int32 range, it can be just a number.
|
||||
// - otherwise, an object with the properties "high" and "low".
|
||||
function assertEqI64(obj, expect) {
|
||||
assertEq(typeof obj, 'object');
|
||||
assertEq(typeof expect === 'object' || typeof expect === 'number', true);
|
||||
|
||||
let {low, high} = obj;
|
||||
if (typeof expect === 'number') {
|
||||
assertEq(expect, expect | 0, "in int32 range");
|
||||
assertEq(low, expect | 0, "low");
|
||||
assertEq(high, expect < 0 ? -1 : 0), "high";
|
||||
} else {
|
||||
assertEq(typeof expect.low, 'number');
|
||||
assertEq(typeof expect.high, 'number');
|
||||
assertEq(low, expect.low | 0, "low");
|
||||
assertEq(high, expect.high | 0, "high");
|
||||
}
|
||||
}
|
||||
|
||||
function createI64(val) {
|
||||
let ret;
|
||||
if (typeof val === 'number') {
|
||||
assertEq(val, val|0, "number input to createI64 must be an int32");
|
||||
ret = { low: val, high: val < 0 ? -1 : 0 };
|
||||
} else {
|
||||
assertEq(typeof val, 'string');
|
||||
assertEq(val.slice(0, 2), "0x");
|
||||
val = val.slice(2).padStart(16, '0');
|
||||
ret = { low: parseInt(val.slice(8, 16), 16), high: parseInt(val.slice(0, 8), 16) };
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
function g(f, params) {
|
||||
entryPoints(params);
|
||||
}
|
||||
function entry1() {};
|
||||
s = "g(entry1, {function: entry1});";
|
||||
f(s);
|
||||
f(s);
|
||||
function f(x) {
|
||||
oomTest(() => eval(x));
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// evalInFrame with non-syntactic scopes.
|
||||
|
||||
load(libdir + "asserts.js");
|
||||
load(libdir + "evalInFrame.js");
|
||||
|
||||
evalReturningScope(`
|
||||
var x = 42;
|
||||
assertEq(evalInFrame(0, "x"), 42);
|
||||
`);
|
||||
@@ -0,0 +1,12 @@
|
||||
// |jit-test| error: out of memory
|
||||
|
||||
if (!('oomTest' in this))
|
||||
throw new Error("out of memory");
|
||||
|
||||
var dbg = new Debugger;
|
||||
dbg.onNewGlobalObject = function(global) {
|
||||
dbg.memory.takeCensus({});
|
||||
};
|
||||
oomTest(function() {
|
||||
newGlobal({})
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
// |jit-test| error: ReferenceError
|
||||
|
||||
g = newGlobal();
|
||||
dbg = Debugger(g);
|
||||
hits = 0;
|
||||
dbg.onNewScript = function () hits++;
|
||||
assertEq(g.eval("eval('2 + 3')"), 5);
|
||||
this.gczeal(hits,1);
|
||||
dbg = Debugger(g);
|
||||
g.h = function () {
|
||||
var env = dbg.getNewestFrame().environment;
|
||||
dbg = 0;
|
||||
assertThrowsInstanceOf;
|
||||
}
|
||||
g.eval("h()");
|
||||
@@ -0,0 +1,28 @@
|
||||
// |jit-test| slow;
|
||||
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
loadFile(`
|
||||
var o = {}
|
||||
var global = this;
|
||||
var p = new Proxy(o, {
|
||||
"deleteProperty": function (await , key) {
|
||||
var g = newGlobal();
|
||||
g.parent = global;
|
||||
g.eval("var dbg = new Debugger(parent); dbg.onEnterFrame = function(frame) {};");
|
||||
}
|
||||
})
|
||||
for (var i=0; i<100; i++);
|
||||
assertEq(delete p.foo, true);
|
||||
`);
|
||||
function loadFile(lfVarx) {
|
||||
var k = 0;
|
||||
oomTest(function() {
|
||||
// In practice a crash occurs before iteration 4000.
|
||||
if (k++ > 4000)
|
||||
quit();
|
||||
eval(lfVarx);
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
if (!('oomTest' in this))
|
||||
quit();
|
||||
|
||||
print = function() {}
|
||||
function k() dissrc(print);
|
||||
function j() k();
|
||||
function h() j();
|
||||
function f() h();
|
||||
f();
|
||||
oomTest(() => f())
|
||||
@@ -0,0 +1,5 @@
|
||||
// |jit-test| allow-oom
|
||||
var du = new Debugger();
|
||||
var obj = du.drainTraceLogger();
|
||||
oomAfterAllocations(1);
|
||||
du.drainTraceLogger().length;
|
||||
@@ -1,10 +1,10 @@
|
||||
load(libdir + "wasm.js");
|
||||
|
||||
if (!wasmIsSupported())
|
||||
quit();
|
||||
|
||||
function testConst(type, str, expect) {
|
||||
assertEq(wasmEvalText('(module (func (result ' + type + ') (' + type + '.const ' + str + ')) (export "" 0))')(), expect);
|
||||
if (type === 'i64')
|
||||
assertEqI64(wasmEvalText('(module (func (result i64) (i64.const ' + str + ')) (export "" 0))')(), expect);
|
||||
else
|
||||
assertEq(wasmEvalText('(module (func (result ' + type + ') (' + type + '.const ' + str + ')) (export "" 0))')(), expect);
|
||||
}
|
||||
|
||||
function testConstError(type, str) {
|
||||
@@ -26,19 +26,59 @@ testConst('i32', '0x80000000', -2147483648);
|
||||
testConst('i32', '-0x80000000', -2147483648);
|
||||
testConst('i32', '0xffffffff', -1);
|
||||
|
||||
//testConst('i64', '0', 0); // TODO: NYI
|
||||
//testConst('i64', '-0', 0); // TODO: NYI
|
||||
//testConst('i64', '23', 23); // TODO: NYI
|
||||
//testConst('i64', '-23', -23); // TODO: NYI
|
||||
//testConst('i64', '0x23', 35); // TODO: NYI
|
||||
//testConst('i64', '-0x23', -35); // TODO: NYI
|
||||
//testConst('i64', '9223372036854775807', 9223372036854775807); // TODO: NYI
|
||||
//testConst('i64', '18446744073709551615', -1); // TODO: NYI
|
||||
//testConst('i64', '-9223372036854775808', -9223372036854775808); // TODO: NYI
|
||||
//testConst('i64', '0x7fffffffffffffff', 9223372036854775807); // TODO: NYI
|
||||
//testConst('i64', '0x8000000000000000', -9223372036854775808); // TODO: NYI
|
||||
//testConst('i64', '-0x8000000000000000', -9223372036854775808); // TODO: NYI
|
||||
//testConst('i64', '0xffffffffffffffff', -1); // TODO: NYI
|
||||
if (hasI64()) {
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /cannot .* i64/);
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
|
||||
testConst('i64', '0', 0);
|
||||
testConst('i64', '-0', 0);
|
||||
|
||||
testConst('i64', '23', 23);
|
||||
testConst('i64', '-23', -23);
|
||||
|
||||
testConst('i64', '0x23', 35);
|
||||
testConst('i64', '-0x23', -35);
|
||||
|
||||
testConst('i64', '-0x1', -1);
|
||||
testConst('i64', '-1', -1);
|
||||
testConst('i64', '0xffffffffffffffff', -1);
|
||||
|
||||
testConst('i64', '0xdeadc0de', {low: 0xdeadc0de, high: 0x0});
|
||||
testConst('i64', '0x1337c0de00000000', {low: 0x0, high: 0x1337c0de});
|
||||
|
||||
testConst('i64', '0x0102030405060708', {low: 0x05060708, high: 0x01020304});
|
||||
testConst('i64', '-0x0102030405060708', {low: -0x05060708, high: -0x01020305});
|
||||
|
||||
// INT64_MAX
|
||||
testConst('i64', '9223372036854775807', {low: 0xffffffff, high: 0x7fffffff});
|
||||
testConst('i64', '0x7fffffffffffffff', {low: 0xffffffff, high: 0x7fffffff});
|
||||
|
||||
// INT64_MAX + 1
|
||||
testConst('i64', '9223372036854775808', {low: 0x00000000, high: 0x80000000});
|
||||
testConst('i64', '0x8000000000000000', {low: 0x00000000, high: 0x80000000});
|
||||
|
||||
// UINT64_MAX
|
||||
testConst('i64', '18446744073709551615', {low: 0xffffffff, high: 0xffffffff});
|
||||
|
||||
// INT64_MIN
|
||||
testConst('i64', '-9223372036854775808', {low: 0x00000000, high: 0x80000000});
|
||||
testConst('i64', '-0x8000000000000000', {low: 0x00000000, high: 0x80000000});
|
||||
|
||||
// INT64_MIN - 1
|
||||
testConstError('i64', '-9223372036854775809');
|
||||
|
||||
testConstError('i64', '');
|
||||
testConstError('i64', '0.0');
|
||||
testConstError('i64', 'not an i64');
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 0);
|
||||
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /cannot .* i64/);
|
||||
} else {
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (result i64) (i64.const 0)) (export "" 0))'), TypeError, /NYI/);
|
||||
}
|
||||
|
||||
testConst('f32', '0.0', 0.0);
|
||||
testConst('f32', '-0', -0.0);
|
||||
@@ -215,12 +255,6 @@ testConstError('i32', 'not an i32');
|
||||
testConstError('i32', '4294967296');
|
||||
testConstError('i32', '-2147483649');
|
||||
|
||||
//testConstError('i64', ''); // TODO: NYI
|
||||
//testConstError('i64', '0.0'); // TODO: NYI
|
||||
//testConstError('i64', 'not an i64'); // TODO: NYI
|
||||
//testConstError('i64', '9223372036854775808'); // TODO: NYI
|
||||
//testConstError('i64', '-9223372036854775809'); // TODO: NYI
|
||||
|
||||
testConstError('f32', '');
|
||||
testConstError('f32', 'not an f32');
|
||||
testConstError('f32', 'nan:');
|
||||
|
||||
@@ -1,50 +1,56 @@
|
||||
load(libdir + "wasm.js");
|
||||
|
||||
if (!wasmIsSupported())
|
||||
quit();
|
||||
|
||||
function testConversion(resultType, opcode, paramType, op, expect) {
|
||||
if (paramType === 'i64') {
|
||||
// i64 cannot be imported, so we use a wrapper function.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (result ${resultType}) (${resultType}.${opcode}/i64 (get_local 0)))
|
||||
(func (result ${resultType}) (call 0 (i64.const ${op})))
|
||||
(export "" 1))`)(), expect);
|
||||
(export "" 0))`)(createI64(op)), expect);
|
||||
// The same, but now the input is a constant.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (result ${resultType}) (${resultType}.${opcode}/i64 (i64.const ${op})))
|
||||
(export "" 0))`)(), expect);
|
||||
} else if (resultType === 'i64') {
|
||||
assertEq(wasmEvalText(`(module
|
||||
assertEqI64(wasmEvalText(`(module
|
||||
(func (param ${paramType}) (result i64) (i64.${opcode}/${paramType} (get_local 0)))
|
||||
(func (result i32) (i64.eq (i64.const ${expect}) (call 0 (${paramType}.const ${op}))))
|
||||
(export "" 1))`)(), 1);
|
||||
(export "" 0))`)(op), createI64(expect));
|
||||
// The same, but now the input is a constant.
|
||||
assertEq(wasmEvalText(`(module
|
||||
assertEqI64(wasmEvalText(`(module
|
||||
(func (result i64) (i64.${opcode}/${paramType} (${paramType}.const ${op})))
|
||||
(func (result i32) (i64.eq (i64.const ${expect}) (call 0)))
|
||||
(export "" 1))`)(), 1);
|
||||
(export "" 0))`)(), createI64(expect));
|
||||
} else {
|
||||
assertEq(wasmEvalText('(module (func (param ' + paramType + ') (result ' + resultType + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))) (export "" 0))')(op), expect);
|
||||
}
|
||||
|
||||
// TODO: i64 NYI
|
||||
for (var bad of ['i32', 'f32', 'f64']) {
|
||||
if (bad != resultType)
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param ' + paramType + ') (result ' + bad + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))))'),
|
||||
TypeError,
|
||||
mismatchError(resultType, bad)
|
||||
);
|
||||
if (bad != paramType)
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param ' + bad + ') (result ' + resultType + ') (' + resultType + '.' + opcode + '/' + paramType + ' (get_local 0))))'),
|
||||
TypeError,
|
||||
mismatchError(bad, paramType)
|
||||
);
|
||||
let formerWasmExtraTests = getJitCompilerOptions()['wasm.test-mode'];
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
for (var bad of ['i32', 'f32', 'f64', 'i64']) {
|
||||
if (bad === 'i64' && !hasI64())
|
||||
continue;
|
||||
|
||||
if (bad != resultType) {
|
||||
assertErrorMessage(
|
||||
() => wasmEvalText(`(module (func (param ${paramType}) (result ${bad}) (${resultType}.${opcode}/${paramType} (get_local 0))))`),
|
||||
TypeError,
|
||||
mismatchError(resultType, bad)
|
||||
);
|
||||
}
|
||||
|
||||
if (bad != paramType) {
|
||||
assertErrorMessage(
|
||||
() => wasmEvalText(`(module (func (param ${bad}) (result ${resultType}) (${resultType}.${opcode}/${paramType} (get_local 0))))`),
|
||||
TypeError,
|
||||
mismatchError(bad, paramType)
|
||||
);
|
||||
}
|
||||
}
|
||||
setJitCompilerOption('wasm.test-mode', formerWasmExtraTests);
|
||||
}
|
||||
|
||||
if (getBuildConfiguration().x64) {
|
||||
testConversion('i32', 'wrap', 'i64', 4294967336, 40);
|
||||
if (hasI64()) {
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
|
||||
testConversion('i32', 'wrap', 'i64', '0x100000028', 40);
|
||||
testConversion('i32', 'wrap', 'i64', -10, -10);
|
||||
testConversion('i32', 'wrap', 'i64', "0xffffffff7fffffff", 0x7fffffff);
|
||||
testConversion('i32', 'wrap', 'i64', "0xffffffff00000000", 0);
|
||||
@@ -68,28 +74,28 @@ if (getBuildConfiguration().x64) {
|
||||
testConversion('f32', 'convert_s', 'i64', 1, 1.0);
|
||||
testConversion('f32', 'convert_s', 'i64', -1, -1.0);
|
||||
testConversion('f32', 'convert_s', 'i64', 0, 0.0);
|
||||
testConversion('f32', 'convert_s', 'i64', "9223372036854775807", 9223372036854775807.0);
|
||||
testConversion('f32', 'convert_s', 'i64', "-9223372036854775808", -9223372036854775808.0);
|
||||
testConversion('f32', 'convert_s', 'i64', "314159265358979", 314159275180032.0);
|
||||
testConversion('f32', 'convert_s', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
|
||||
testConversion('f32', 'convert_s', 'i64', "0x8000000000000000", -9223372036854775808.0);
|
||||
testConversion('f32', 'convert_s', 'i64', "0x11db9e76a2483", 314159275180032.0);
|
||||
|
||||
testConversion('f64', 'convert_s', 'i64', 1, 1.0);
|
||||
testConversion('f64', 'convert_s', 'i64', -1, -1.0);
|
||||
testConversion('f64', 'convert_s', 'i64', 0, 0.0);
|
||||
testConversion('f64', 'convert_s', 'i64', "9223372036854775807", 9223372036854775807.0);
|
||||
testConversion('f64', 'convert_s', 'i64', "-9223372036854775808", -9223372036854775808.0);
|
||||
testConversion('f64', 'convert_s', 'i64', "4669201609102990", 4669201609102990);
|
||||
testConversion('f64', 'convert_s', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
|
||||
testConversion('f64', 'convert_s', 'i64', "0x8000000000000000", -9223372036854775808.0);
|
||||
testConversion('f64', 'convert_s', 'i64', "0x10969d374b968e", 4669201609102990);
|
||||
|
||||
testConversion('f32', 'convert_u', 'i64', 1, 1.0);
|
||||
testConversion('f32', 'convert_u', 'i64', 0, 0.0);
|
||||
testConversion('f32', 'convert_u', 'i64', "9223372036854775807", 9223372036854775807.0);
|
||||
testConversion('f32', 'convert_u', 'i64', "-9223372036854775808", 9223372036854775808.0);
|
||||
testConversion('f32', 'convert_u', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
|
||||
testConversion('f32', 'convert_u', 'i64', "0x8000000000000000", 9223372036854775808.0);
|
||||
testConversion('f32', 'convert_u', 'i64', -1, 18446744073709551616.0);
|
||||
testConversion('f32', 'convert_u', 'i64', "0xffff0000ffff0000", 18446462598732840000.0);
|
||||
|
||||
testConversion('f64', 'convert_u', 'i64', 1, 1.0);
|
||||
testConversion('f64', 'convert_u', 'i64', 0, 0.0);
|
||||
testConversion('f64', 'convert_u', 'i64', "9223372036854775807", 9223372036854775807.0);
|
||||
testConversion('f64', 'convert_u', 'i64', "-9223372036854775808", 9223372036854775808.0);
|
||||
testConversion('f64', 'convert_u', 'i64', "0x7fffffffffffffff", 9223372036854775807.0);
|
||||
testConversion('f64', 'convert_u', 'i64', "0x8000000000000000", 9223372036854775808.0);
|
||||
testConversion('f64', 'convert_u', 'i64', -1, 18446744073709551616.0);
|
||||
testConversion('f64', 'convert_u', 'i64', "0xffff0000ffff0000", 18446462603027743000.0);
|
||||
|
||||
@@ -105,10 +111,10 @@ if (getBuildConfiguration().x64) {
|
||||
testConversion('i64', 'trunc_s', 'f64', -1.5, -1);
|
||||
testConversion('i64', 'trunc_s', 'f64', -1.99, -1);
|
||||
testConversion('i64', 'trunc_s', 'f64', -2.0, -2);
|
||||
testConversion('i64', 'trunc_s', 'f64', 4294967296.1, "4294967296");
|
||||
testConversion('i64', 'trunc_s', 'f64', -4294967296.8, "-4294967296");
|
||||
testConversion('i64', 'trunc_s', 'f64', 9223372036854774784.8, "9223372036854774784");
|
||||
testConversion('i64', 'trunc_s', 'f64', -9223372036854775808.3, "-9223372036854775808");
|
||||
testConversion('i64', 'trunc_s', 'f64', 4294967296.1, "0x100000000");
|
||||
testConversion('i64', 'trunc_s', 'f64', -4294967296.8, "0xffffffff00000000");
|
||||
testConversion('i64', 'trunc_s', 'f64', 9223372036854774784.8, "0x7ffffffffffffc00");
|
||||
testConversion('i64', 'trunc_s', 'f64', -9223372036854775808.3, "0x8000000000000000");
|
||||
|
||||
testConversion('i64', 'trunc_u', 'f64', 0.0, 0);
|
||||
testConversion('i64', 'trunc_u', 'f64', "-0.0", 0);
|
||||
@@ -119,10 +125,10 @@ if (getBuildConfiguration().x64) {
|
||||
testConversion('i64', 'trunc_u', 'f64', -0.9, 0);
|
||||
testConversion('i64', 'trunc_u', 'f64', 40.1, 40);
|
||||
testConversion('i64', 'trunc_u', 'f64', 4294967295, "0xffffffff");
|
||||
testConversion('i64', 'trunc_u', 'f64', 4294967296.1, "4294967296");
|
||||
testConversion('i64', 'trunc_u', 'f64', 1e8, "100000000");
|
||||
testConversion('i64', 'trunc_u', 'f64', 1e16, "10000000000000000");
|
||||
testConversion('i64', 'trunc_u', 'f64', 9223372036854775808, "-9223372036854775808");
|
||||
testConversion('i64', 'trunc_u', 'f64', 4294967296.1, "0x100000000");
|
||||
testConversion('i64', 'trunc_u', 'f64', 1e8, "0x5f5e100");
|
||||
testConversion('i64', 'trunc_u', 'f64', 1e16, "0x2386f26fc10000");
|
||||
testConversion('i64', 'trunc_u', 'f64', 9223372036854775808, "0x8000000000000000");
|
||||
testConversion('i64', 'trunc_u', 'f64', 18446744073709549568.1, -2048);
|
||||
|
||||
testConversion('i64', 'trunc_s', 'f32', 0.0, 0);
|
||||
@@ -137,10 +143,10 @@ if (getBuildConfiguration().x64) {
|
||||
testConversion('i64', 'trunc_s', 'f32', -1.5, -1);
|
||||
testConversion('i64', 'trunc_s', 'f32', -1.99, -1);
|
||||
testConversion('i64', 'trunc_s', 'f32', -2.0, -2);
|
||||
testConversion('i64', 'trunc_s', 'f32', 4294967296.1, "4294967296");
|
||||
testConversion('i64', 'trunc_s', 'f32', -4294967296.8, "-4294967296");
|
||||
testConversion('i64', 'trunc_s', 'f32', 9223371487098961920.0, "9223371487098961920");
|
||||
testConversion('i64', 'trunc_s', 'f32', -9223372036854775808.3, "-9223372036854775808");
|
||||
testConversion('i64', 'trunc_s', 'f32', 4294967296.1, "0x100000000");
|
||||
testConversion('i64', 'trunc_s', 'f32', -4294967296.8, "0xffffffff00000000");
|
||||
testConversion('i64', 'trunc_s', 'f32', 9223371487098961920.0, "0x7fffff8000000000");
|
||||
testConversion('i64', 'trunc_s', 'f32', -9223372036854775808.3, "0x8000000000000000");
|
||||
|
||||
testConversion('i64', 'trunc_u', 'f32', 0.0, 0);
|
||||
testConversion('i64', 'trunc_u', 'f32', "-0.0", 0);
|
||||
@@ -150,9 +156,9 @@ if (getBuildConfiguration().x64) {
|
||||
testConversion('i64', 'trunc_u', 'f32', 1.99, 1);
|
||||
testConversion('i64', 'trunc_u', 'f32', -0.9, 0);
|
||||
testConversion('i64', 'trunc_u', 'f32', 40.1, 40);
|
||||
testConversion('i64', 'trunc_u', 'f32', 1e8, "100000000");
|
||||
testConversion('i64', 'trunc_u', 'f32', 4294967296, "4294967296");
|
||||
testConversion('i64', 'trunc_u', 'f32', 18446742974197923840.0, "-1099511627776");
|
||||
testConversion('i64', 'trunc_u', 'f32', 1e8, "0x5f5e100");
|
||||
testConversion('i64', 'trunc_u', 'f32', 4294967296, "0x100000000");
|
||||
testConversion('i64', 'trunc_u', 'f32', 18446742974197923840.0, "0xffffff0000000000");
|
||||
|
||||
// TODO: these should trap.
|
||||
testConversion('i64', 'trunc_s', 'f64', 9223372036854775808.0, "0x8000000000000000");
|
||||
@@ -179,8 +185,10 @@ if (getBuildConfiguration().x64) {
|
||||
testConversion('i64', 'trunc_u', 'f32', "infinity", "0x8000000000000000");
|
||||
testConversion('i64', 'trunc_u', 'f32', "-infinity", "0x8000000000000000");
|
||||
|
||||
testConversion('i64', 'reinterpret', 'f64', 40.09999999999968, 4630840390592548000);
|
||||
testConversion('f64', 'reinterpret', 'i64', 4630840390592548000, 40.09999999999968);
|
||||
testConversion('i64', 'reinterpret', 'f64', 40.09999999999968, "0x40440ccccccccca0");
|
||||
testConversion('f64', 'reinterpret', 'i64', "0x40440ccccccccca0", 40.09999999999968);
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 0);
|
||||
} else {
|
||||
// Sleeper test: once i64 works on more platforms, remove this if-else.
|
||||
try {
|
||||
|
||||
@@ -9,45 +9,40 @@ function testUnary(type, opcode, op, expect) {
|
||||
}
|
||||
|
||||
function testBinary(type, opcode, lhs, rhs, expect) {
|
||||
if (type === 'i64') {
|
||||
// i64 cannot be imported/exported, so we use a wrapper function.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (get_local 1)))
|
||||
(func (result i32) (i64.eq (call 0 (i64.const ${lhs}) (i64.const ${rhs})) (i64.const ${expect})))
|
||||
(export "" 1))`)(), 1);
|
||||
// The same, but now the RHS is a constant.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (result i64) (i64.${opcode} (get_local 0) (i64.const ${rhs})))
|
||||
(func (result i32) (i64.eq (call 0 (i64.const ${lhs})) (i64.const ${expect})))
|
||||
(export "" 1))`)(), 1);
|
||||
// LHS and RHS are constants.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (result i64) (i64.${opcode} (i64.const ${lhs}) (i64.const ${rhs})))
|
||||
(func (result i32) (i64.eq (call 0) (i64.const ${expect})))
|
||||
(export "" 1))`)(), 1);
|
||||
} else {
|
||||
assertEq(wasmEvalText('(module (func (param ' + type + ') (param ' + type + ') (result ' + type + ') (' + type + '.' + opcode + ' (get_local 0) (get_local 1))) (export "" 0))')(lhs, rhs), expect);
|
||||
}
|
||||
if (type === 'i64') {
|
||||
let lobj = createI64(lhs);
|
||||
let robj = createI64(rhs);
|
||||
expect = createI64(expect);
|
||||
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lobj, robj), expect);
|
||||
// The same, but now the RHS is a constant.
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (get_local 0) (i64.const ${rhs}))) (export "" 0))`)(lobj, robj), expect);
|
||||
// LHS and RHS are constants.
|
||||
assertEqI64(wasmEvalText(`(module (func (param i64) (param i64) (result i64) (i64.${opcode} (i64.const ${lhs}) (i64.const ${rhs}))) (export "" 0))`)(lobj, robj), expect);
|
||||
} else {
|
||||
assertEq(wasmEvalText(`(module (func (param ${type}) (param ${type}) (result ${type}) (${type}.${opcode} (get_local 0) (get_local 1))) (export "" 0))`)(lhs, rhs), expect);
|
||||
}
|
||||
}
|
||||
|
||||
function testComparison(type, opcode, lhs, rhs, expect) {
|
||||
if (type === 'i64') {
|
||||
// i64 cannot be imported/exported, so we use a wrapper function.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32) (i64.${opcode} (get_local 0) (get_local 1)))
|
||||
(func (result i32) (call 0 (i64.const ${lhs}) (i64.const ${rhs})))
|
||||
(export "" 1))`)(), expect);
|
||||
// Also test if, for the compare-and-branch path.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32)
|
||||
(if (i64.${opcode} (get_local 0) (get_local 1))
|
||||
(i32.const 1)
|
||||
(i32.const 0)))
|
||||
(func (result i32) (call 0 (i64.const ${lhs}) (i64.const ${rhs})))
|
||||
(export "" 1))`)(), expect);
|
||||
} else {
|
||||
assertEq(wasmEvalText('(module (func (param ' + type + ') (param ' + type + ') (result i32) (' + type + '.' + opcode + ' (get_local 0) (get_local 1))) (export "" 0))')(lhs, rhs), expect);
|
||||
}
|
||||
if (type === 'i64') {
|
||||
let lobj = createI64(lhs);
|
||||
let robj = createI64(rhs);
|
||||
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32) (i64.${opcode} (get_local 0) (get_local 1)))
|
||||
(export "" 0))`)(lobj, robj), expect);
|
||||
|
||||
// Also test if, for the compare-and-branch path.
|
||||
assertEq(wasmEvalText(`(module
|
||||
(func (param i64) (param i64) (result i32)
|
||||
(if (i64.${opcode} (get_local 0) (get_local 1))
|
||||
(i32.const 1)
|
||||
(i32.const 0)))
|
||||
(export "" 0))`)(lobj, robj), expect);
|
||||
} else {
|
||||
assertEq(wasmEvalText('(module (func (param ' + type + ') (param ' + type + ') (result i32) (' + type + '.' + opcode + ' (get_local 0) (get_local 1))) (export "" 0))')(lhs, rhs), expect);
|
||||
}
|
||||
}
|
||||
|
||||
testUnary('i32', 'clz', 40, 26);
|
||||
@@ -95,7 +90,10 @@ testComparison('i32', 'ge_u', 40, 40, 1);
|
||||
//testUnary('i64', 'popcnt', 40, 0); // TODO: NYI
|
||||
//testUnary('i64', 'eqz', 40, 0); // TODO: NYI
|
||||
|
||||
if (getBuildConfiguration().x64) {
|
||||
if (hasI64()) {
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
|
||||
testBinary('i64', 'add', 40, 2, 42);
|
||||
testBinary('i64', 'add', "0x1234567887654321", -1, "0x1234567887654320");
|
||||
testBinary('i64', 'add', "0xffffffffffffffff", 1, 0);
|
||||
@@ -157,15 +155,17 @@ if (getBuildConfiguration().x64) {
|
||||
testComparison('i64', 'eq', "0x400012345678", "0x400012345678", 1);
|
||||
testComparison('i64', 'ne', "0x400012345678", "0x400012345678", 0);
|
||||
testComparison('i64', 'ne', "0x400012345678", "0x500012345678", 1);
|
||||
testComparison('i64', 'eq', "0xffffffffffffffff", "-1", 1);
|
||||
testComparison('i64', 'eq', "0xffffffffffffffff", -1, 1);
|
||||
testComparison('i64', 'lt_s', "0x8000000012345678", "0x1", 1);
|
||||
testComparison('i64', 'lt_u', "0x8000000012345678", "0x1", 0);
|
||||
testComparison('i64', 'le_s', "-1", "0", 1);
|
||||
testComparison('i64', 'le_u', "-1", "-1", 1);
|
||||
testComparison('i64', 'gt_s', "1", "0x8000000000000000", 1);
|
||||
testComparison('i64', 'gt_u', "1", "0x8000000000000000", 0);
|
||||
testComparison('i64', 'ge_s', "1", "0x8000000000000000", 1);
|
||||
testComparison('i64', 'ge_u', "1", "0x8000000000000000", 0);
|
||||
testComparison('i64', 'le_s', -1, 0, 1);
|
||||
testComparison('i64', 'le_u', -1, -1, 1);
|
||||
testComparison('i64', 'gt_s', 1, "0x8000000000000000", 1);
|
||||
testComparison('i64', 'gt_u', 1, "0x8000000000000000", 0);
|
||||
testComparison('i64', 'ge_s', 1, "0x8000000000000000", 1);
|
||||
testComparison('i64', 'ge_u', 1, "0x8000000000000000", 0);
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 0);
|
||||
} else {
|
||||
// Sleeper test: once i64 works on more platforms, remove this if-else.
|
||||
try {
|
||||
|
||||
@@ -87,11 +87,22 @@ wasmEvalText('(module (func (result i32) (param i32) (i32.const 42)))');
|
||||
wasmEvalText('(module (func (param f32)))');
|
||||
wasmEvalText('(module (func (param f64)))');
|
||||
|
||||
var hasI64 = getBuildConfiguration().x64;
|
||||
if (!hasI64) {
|
||||
if (!hasI64()) {
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i64)))'), TypeError, /NYI/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (result i64)))'), TypeError, /NYI/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (result i32) (i32.wrap/i64 (i64.add (i64.const 1) (i64.const 2)))))'), TypeError, /NYI/);
|
||||
} else {
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i64) (result i32) (i32.const 123)) (export "" 0))'), TypeError, /i64 argument/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i32) (result i64) (i64.const 123)) (export "" 0))'), TypeError, /i64 return type/);
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
|
||||
assertEqI64(wasmEvalText('(module (func (result i64) (i64.const 123)) (export "" 0))')(), {low: 123, high: 0});
|
||||
assertEqI64(wasmEvalText('(module (func (param i64) (result i64) (get_local 0)) (export "" 0))')({ low: 0x7fffffff, high: 0x12340000}),
|
||||
{low: 0x7fffffff, high: 0x12340000});
|
||||
assertEqI64(wasmEvalText('(module (func (param i64) (result i64) (i64.add (get_local 0) (i64.const 1))) (export "" 0))')({ low: 0xffffffff, high: 0x12340000}), {low: 0x0, high: 0x12340001});
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -260,7 +271,7 @@ wasmEvalText('(module (func (local i32) (local f32) (set_local 1 (get_local 1)))
|
||||
assertEq(wasmEvalText('(module (func (result i32) (local i32) (set_local 0 (i32.const 42))) (export "" 0))')(), 42);
|
||||
assertEq(wasmEvalText('(module (func (result i32) (local i32) (set_local 0 (get_local 0))) (export "" 0))')(), 0);
|
||||
|
||||
if (!hasI64)
|
||||
if (!hasI64())
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (local i64)))'), TypeError, /NYI/);
|
||||
|
||||
assertEq(wasmEvalText('(module (func (param $a i32) (result i32) (get_local $a)) (export "" 0))')(), 0);
|
||||
@@ -347,6 +358,70 @@ assertEq(wasmEvalText(code.replace('BODY', '(call 1)'), imports)(), 4);
|
||||
|
||||
assertEq(wasmEvalText(`(module (import "evalcx" "" (param i32) (result i32)) (func (result i32) (call_import 0 (i32.const 0))) (export "" 0))`, {evalcx})(), 0);
|
||||
|
||||
if (typeof evaluate === 'function')
|
||||
evaluate(`Wasm.instantiateModule(wasmTextToBinary('(module)')) `, { fileName: null });
|
||||
|
||||
if (hasI64()) {
|
||||
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (param i64) (result i32)))'), TypeError, /i64 argument/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /i64 return type/);
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
|
||||
let imp = {
|
||||
param(i64) {
|
||||
assertEqI64(i64, {
|
||||
low: 0x9abcdef0,
|
||||
high: 0x12345678
|
||||
});
|
||||
return 42;
|
||||
},
|
||||
result(i32) {
|
||||
return {
|
||||
low: 0xabcdef01,
|
||||
high: 0x12345678 + i32
|
||||
}
|
||||
},
|
||||
paramAndResult(i64) {
|
||||
assertEqI64(i64, {
|
||||
low: 0x9abcdef0,
|
||||
high: 0x12345678
|
||||
});
|
||||
i64.low = 1337;
|
||||
return i64;
|
||||
}
|
||||
}
|
||||
|
||||
assertEq(wasmEvalText(`(module
|
||||
(import "param" "" (param i64) (result i32))
|
||||
(func (result i32) (call_import 0 (i64.const 0x123456789abcdef0)))
|
||||
(export "" 0))`, imp)(), 42);
|
||||
|
||||
assertEqI64(wasmEvalText(`(module
|
||||
(import "result" "" (param i32) (result i64))
|
||||
(func (result i64) (call_import 0 (i32.const 3)))
|
||||
(export "" 0))`, imp)(), { low: 0xabcdef01, high: 0x1234567b });
|
||||
|
||||
// Ensure the ion exit is never taken.
|
||||
let ionThreshold = 2 * getJitCompilerOptions()['ion.warmup.trigger'];
|
||||
assertEqI64(wasmEvalText(`(module
|
||||
(import "paramAndResult" "" (param i64) (result i64))
|
||||
(func (result i64) (local i32) (local i64)
|
||||
(set_local 0 (i32.const 0))
|
||||
(loop $out $in
|
||||
(set_local 1 (call_import 0 (i64.const 0x123456789abcdef0)))
|
||||
(set_local 0 (i32.add (get_local 0) (i32.const 1)))
|
||||
(if (i32.le_s (get_local 0) (i32.const ${ionThreshold})) (br $in))
|
||||
)
|
||||
(get_local 1)
|
||||
)
|
||||
(export "" 0))`, imp)(), { low: 1337, high: 0x12345678 });
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 0);
|
||||
} else {
|
||||
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (param i64) (result i32)))'), TypeError, /NYI/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /NYI/);
|
||||
}
|
||||
|
||||
var {v2i, i2i, i2v} = wasmEvalText(`(module
|
||||
(type (func (result i32)))
|
||||
(type (func (param i32) (result i32)))
|
||||
@@ -407,13 +482,6 @@ for (bad of [6, 7, 100, Math.pow(2,31)-1, Math.pow(2,31), Math.pow(2,31)+1, Math
|
||||
assertThrowsInstanceOf(() => i2v(bad, 0), RangeError);
|
||||
}
|
||||
|
||||
if (hasI64) {
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i64) (result i32) (i32.const 123)) (export "" 0))'), TypeError, /i64 argument/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (param i32) (result i64) (i64.const 123)) (export "" 0))'), TypeError, /i64 return type/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (param i64) (result i32)))'), TypeError, /i64 argument/);
|
||||
assertErrorMessage(() => wasmEvalText('(module (import "a" "" (result i64)))'), TypeError, /i64 return type/);
|
||||
}
|
||||
|
||||
var {v2i, i2i, i2v} = wasmEvalText(`(module
|
||||
(type $a (func (result i32)))
|
||||
(type $b (func (param i32) (result i32)))
|
||||
@@ -582,26 +650,28 @@ testSelect('f64', 13.37, 19.89);
|
||||
testSelect('f64', 'infinity', '-0');
|
||||
testSelect('f64', 'nan', Math.pow(2, -31));
|
||||
|
||||
if (!hasI64) {
|
||||
if (!hasI64()) {
|
||||
assertErrorMessage(() => wasmEvalText('(module (func (select (i64.const 0) (i64.const 1) (i32.const 0))))'), TypeError, /NYI/);
|
||||
} else {
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 1);
|
||||
|
||||
var f = wasmEvalText(`
|
||||
(module
|
||||
(func (result i32) (param i32)
|
||||
(i64.gt_s
|
||||
(select
|
||||
(i64.const ${Math.pow(2, 31) + 1})
|
||||
(i64.const ${-Math.pow(2, 31) - 1})
|
||||
(get_local 0)
|
||||
)
|
||||
(i64.const ${Math.pow(2, 31)})
|
||||
(func (result i64) (param i32)
|
||||
(select
|
||||
(i64.const 0xc0010ff08badf00d)
|
||||
(i64.const 0x12345678deadc0de)
|
||||
(get_local 0)
|
||||
)
|
||||
)
|
||||
(export "" 0)
|
||||
)
|
||||
`, imports);
|
||||
)`, imports);
|
||||
|
||||
assertEq(f(0), 0);
|
||||
assertEq(f(1), 1);
|
||||
assertEq(f(-1), 1);
|
||||
assertEqI64(f(0), { low: 0xdeadc0de, high: 0x12345678});
|
||||
assertEqI64(f(1), { low: 0x8badf00d, high: 0xc0010ff0});
|
||||
assertEqI64(f(-1), { low: 0x8badf00d, high: 0xc0010ff0});
|
||||
|
||||
setJitCompilerOption('wasm.test-mode', 0);
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -166,6 +166,7 @@ MSG_DEF(JSMSG_BAD_BYTECODE, 1, JSEXN_INTERNALERR, "unimplemented Java
|
||||
MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 0, JSEXN_INTERNALERR, "buffer too small")
|
||||
MSG_DEF(JSMSG_BUILD_ID_NOT_AVAILABLE, 0, JSEXN_INTERNALERR, "build ID is not available")
|
||||
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
|
||||
MSG_DEF(JSMSG_ERR_DURING_THROW, 0, JSEXN_INTERNALERR, "an internal error occurred while throwing an exception")
|
||||
MSG_DEF(JSMSG_NEED_DIET, 1, JSEXN_INTERNALERR, "{0} too large")
|
||||
MSG_DEF(JSMSG_OUT_OF_MEMORY, 0, JSEXN_INTERNALERR, "out of memory")
|
||||
MSG_DEF(JSMSG_OVER_RECURSED, 0, JSEXN_INTERNALERR, "too much recursion")
|
||||
@@ -237,7 +238,7 @@ MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 0, JSEXN_SYNTAXERR, "applying the 'dele
|
||||
MSG_DEF(JSMSG_DEPRECATED_EXPR_CLOSURE, 0, JSEXN_NONE, "expression closures are deprecated")
|
||||
MSG_DEF(JSMSG_DEPRECATED_FLAGS_ARG, 0, JSEXN_NONE, "flags argument of String.prototype.{search,match,replace} is deprecated")
|
||||
MSG_DEF(JSMSG_DEPRECATED_FOR_EACH, 0, JSEXN_NONE, "JavaScript 1.6's for-each-in loops are deprecated; consider using ES6 for-of instead")
|
||||
MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "octal literals and octal escape sequences are deprecated")
|
||||
MSG_DEF(JSMSG_DEPRECATED_OCTAL, 0, JSEXN_SYNTAXERR, "\"0\"-prefixed octal literals and octal escape sequences are deprecated; for octal literals use the \"0o\" prefix instead")
|
||||
MSG_DEF(JSMSG_DEPRECATED_PRAGMA, 1, JSEXN_NONE, "Using //@ to indicate {0} pragmas is deprecated. Use //# instead")
|
||||
MSG_DEF(JSMSG_DEPRECATED_BLOCK_SCOPE_FUN_REDECL, 1, JSEXN_NONE, "redeclaration of block-scoped function `{0}' is deprecated")
|
||||
MSG_DEF(JSMSG_DUPLICATE_EXPORT_NAME, 1, JSEXN_SYNTAXERR, "duplicate export name '{0}'")
|
||||
|
||||
+9
-3
@@ -6289,7 +6289,7 @@ void AutoFilename::setScriptSource(js::ScriptSource* p)
|
||||
void AutoFilename::setUnowned(const char* filename)
|
||||
{
|
||||
MOZ_ASSERT(!get());
|
||||
filename_.as<const char*>() = filename;
|
||||
filename_.as<const char*>() = filename ? filename : "";
|
||||
}
|
||||
|
||||
void AutoFilename::setOwned(UniqueChars&& filename)
|
||||
@@ -6559,8 +6559,11 @@ JS::SetOutOfMemoryCallback(JSRuntime* rt, OutOfMemoryCallback cb, void* data)
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CaptureCurrentStack(JSContext* cx, JS::MutableHandleObject stackp, unsigned maxFrameCount)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
MOZ_RELEASE_ASSERT(cx->compartment());
|
||||
|
||||
JSCompartment* compartment = cx->compartment();
|
||||
MOZ_ASSERT(compartment);
|
||||
Rooted<SavedFrame*> frame(cx);
|
||||
if (!compartment->savedStacks().saveCurrentStack(cx, &frame, maxFrameCount))
|
||||
return false;
|
||||
@@ -6573,9 +6576,12 @@ JS::CopyAsyncStack(JSContext* cx, JS::HandleObject asyncStack,
|
||||
JS::HandleString asyncCause, JS::MutableHandleObject stackp,
|
||||
unsigned maxFrameCount)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
MOZ_RELEASE_ASSERT(cx->compartment());
|
||||
|
||||
js::AssertObjectIsSavedFrameOrWrapper(cx, asyncStack);
|
||||
JSCompartment* compartment = cx->compartment();
|
||||
MOZ_ASSERT(compartment);
|
||||
Rooted<SavedFrame*> frame(cx);
|
||||
if (!compartment->savedStacks().copyAsyncStack(cx, asyncStack, asyncCause,
|
||||
&frame, maxFrameCount))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user